========================================== The Shadow Penguin Documents. No. 9 - ログの解体と消去法 - Written by うにゅん Oct.29, 1998 ========================================= 1. はじめに 本テキストは,Solarisの接続ログの詳細とその消し方についての技術資料です. こういったログの消去法もあるので、ログなんて何の証拠にもならないことが良く分かり ますね。必要ならば書き換えもできるのですから。 また,ログ消しツールulw.cの使用法も解説します.本テキストでは,以下の5つのログ を対象に実験を行った結果を示します. /var/adm/wtmp /var/adm/wtmpx /var/adm/utmp /var/adm/utmpx /var/adm/lastlog 実験はSolaris2.6(Sparc)で行いました。 2. Solarisの接続ログ管理 Solarisでは,telnetやftp等の接続ログ管理ファイルとしてwtmp,wtmpxという2つ のファイルを用います.この2つのファイルにlogin,logput日時やホスト等のログが保 存されています.また,現在誰がloginしてるのか等を管理するファイルとしてutmp,utmpx という2つのファイル,各ユーザ毎に最後にloginした日時やホストなどを保存する lastlogというファイルも用意されています.侵入者は、普通こういうログを消していき ますね。もちろん,これらのログを消すにはrootになる必要があります. まぁ,rmで消せばたしかにログは消えますが,これでは「侵入しましたよ」って大声で 叫んでるみたいなものなので、普通はそんなことはしないです。 でもこれらのログはクリアテキストじゃないので,viとかで編集できるものじゃありま せん.そこで,ログ消しツールを使って,特定のログだけ消すっていうのが一般的ですね. 一番有名なのがzapで,Solaris用だとwtmpx.cというヤツです.これでたしかに特定ユ ーザのログだけ消して,lastコマンドを使っても表示されないようになっています.で もコレにも欠点があります.この問題と解決策を解説する前に,まずこれらのログがどの ように生成・保存されているのかを解説します. 3. 各種ログファイルの動き 5つのログファイルの生成・保存過程はlastコマンドでは正確に把握できません.ま た,クリアテキストではないのでcatで検査することもできません.これらのログはFig.1 に示すようなレコード形式で保存されています. /var/adm/wtmp,utmp /var/adm/wtmpx,utmpx /var/adm/lastlog ------------------------ ------------------------ ---------------------- user名 8byte user名 32byte login時刻 4byte ID 4byte ID 4byte デバイス名 8byte デバイス名 12byte デバイス名 12byte ホスト名 16byte プロセスID 2byte プロセスID 2byte エントリタイプ 2byte エントリタイプ 2byte 終了ステータス 4byte 終了ステータス 4byte エントリ追加時刻 4byte エントリ追加時刻 4byte セッションID 4byte 予備バッファ 20byte Host名長 2byte Host名 257byte Fig.1 各ログファイルのレコード このレコードが,login,logout等のたびにwtmpなどに追加されていきます.telnet等 の場合は,接続・login・logoutと3回にわたりwtmp,wtmpxに追加されます.lastコマ ンドでは,そのうち最終のものしか表示されません(エントリタイプで識別)ので,全ての 過程のログを見るには専用のログビューアが必要になります.本テキストでの実験は,コ コに掲載されているlogchk.cを用いました.なお,logchkでは,レコード中の有用であ ると思われるパラメータしか表示しませんが,ログの生成過程を理解する上では十分でし ょう.logchkでのログ生成過程を実例を交えて解説します.  まず,各種ログが空の状態でユーザunyunがtelnetでlogin,logoutしたときのログの 生成過程をFig.2に示します. [wtmp] Name id Line Type Time ---------------------------------------------------------------------- .telnet tn10 /dev/pts/7 6 Tue Oct 27 22:44:42 1998 (*1) unyun tn10 pts/7 7 Tue Oct 27 22:44:46 1998 (*2) unyun tn10 pts/7 8 Tue Oct 27 22:49:46 1998 (*3) [wtmpx] Name id Line Type Host ---------------------------------------------------------------------- .telnet tn10 /dev/pts/7 6 (*1) unyun tn10 pts/7 7 pentagon.com (*2) unyun tn10 pts/7 8 pentagon.com (*3) [utmp] Name id Line Type Time ---------------------------------------------------------------------- unyun tn10 pts/7 8 Tue Oct 27 22:49:46 1998 [utmpx] Name id Line Type Host ---------------------------------------------------------------------- unyun tn10 pts/7 8 pentagon.com [lastlog] Name : Host Line Time ---------------------------------------------------------------------- unyun : pentagon.com pts/7 Tue Oct 27 22:50:43 1998 Fig.2 telnetでのloginとlogout telnetで接続すると,まず(*1)に示すようにwtmp,wtmpxに".telnet"という名前で追 加されます.そして,idやデバイスが割り振られ,接続時刻が記録され,エントリタイ プは6(接続)として記録されます.次に,telnetではLogin名とPasswordを求められま すので,それを通過すると(*2)に示すようにlogin名,エントリタイプ7(login完了),login 時刻,ホスト名等が記録されます.logoutすると,(*3)に示すようにlogout時刻などが 記録されます.なお,telnetだけでなく,rloginやftpもwtmp,wtmpxに記録されます. rlogin,ftpの記録例をFig.3に示します.ftpに関しては接続時の記録はなく,エント リタイプは7からの記録となります.また,idは"ftp"統一となり,識別にはLine(デバ イス名)を用います. (1) rlogin ※wtmpにも記録される [wtmpx] Name id Line Type Time -------------------------------------------------------------- .rlogin rl10 /dev/pts/7 6 (接続時) (2) ftp ※wtmpにも記録される [wtmpx] Name id Line Type Host -------------------------------------------------------------- unyun ftp ftp9609 7 pentagon.com (login時) ftp ftp9609 7 (logout時) Fig.3 rloginおよびftpの記録例 utmp,utmpxは,そのユーザの最新のwtmp,wtmpxエントリが書かれます.つまり,接続 時は(*1),login後は(*2)が上書き,logout後は(*3)が上書きされます.whoコマンド等 はutmp,utmpx中のエントリタイプ7の項目のみを整形して表示しているものと思われま す.lastlogはlogin直後,つまりloginユーザのエントリタイプ7の状態のユーザ名, ホスト名,デバイス,時刻が記録されます. wtmp,wtmpxは接続履歴の保存が目的ですから,普通は(消されない限り)ログが上書き されたり減ったりすることはありません(ただし保存管理上,管理者やOSが古いログを保 存・消去して0クリアすることもある).ただし,utmp,utmpxは,現在のlogin状況を知 るためのログですので,logoutしたユーザのエントリには上書きがあります.上書きが 起こる可能性のあるutmpの例をFig.4に示します. [utmp] Name id Line Type Time ---------------------------------------------------------- unyun tn10 pts/7 7 Tue Oct 27 22:50:43 1998 aho tn20 pts/8 7 Tue Oct 27 22:52:10 1998 hoge rl10 pts/11 8 Tue Oct 27 22:53:59 1998 < 上書き可能性アリ herohero rl20 pts/12 7 Tue Oct 27 22:48:47 1998 hohoho tn30 pts/11 8 Tue Oct 27 22:53:25 1998 < 上書き可能性アリ bokeboke rl30 pts/8 8 Tue Oct 27 22:51:23 1998 < 上書き可能性アリ             Fig.4 utmpの上書きタイミング utmpは,idでソートされます.idはtelnet用の"tn",およびrlogin用の"rl"があり, それぞれlogin時に他のloginとの識別用に用いられます.utmp中のidは重複がありま せん.つまり,logoutしたユーザは,次に同じidが割り振られたloginが現わると,そ の接続で上書きされます.なお,utmp,utmpxには,ftpの接続は記録されません.lastlog は各ユーザで管理されますので,最大ユーザID数のエントリが存在します.lastlogの 例をFig.5に示します. [lastlog] Name : Host Line Time ----------------------------------------------------------------------- unyun : pentagon.com 73 Tue Oct 27 22:53:01 1998 hoge : police.com pts/11 Tue Oct 27 22:53:57 1998 herohero : usa.com pts/11 Tue Oct 27 22:52:26 1998 hohoho : localhost pts/12 Tue Oct 27 22:46:58 1998 hoge : host1 pts/8 Tue Oct 27 22:52:10 1998 bokeboke : ppp.hoge.com pts/11 Tue Oct 27 22:53:25 1998 Fig.5 Lastlogの例 lastlogはユーザIDでソートされています.logchk.cでは,実際に存在するユーザのみ のlastlogを表示しますが,実際はもう少し多くのエントリがある場合があります.たと えばユーザbokebokeのユーザIDが2000の場合,2000エントリ存在することになります. これらのエントリはloginごとに上書きされます.なお,lastlogはftpログもloginと みなし記録されます. 以上のログの実際のサンプルをFig.6に示し,動作を追跡してみます. なお,wtmpx,utmpxは省略します. [wtmp] Name id Line Type Time ------------------------------------------------------ .telnet tn10 /dev/pts/7 6 Tue Oct 27 22:44:42 1998 unyun tn10 pts/7 7 Tue Oct 27 22:44:46 1998 unyun1がtelnetでlogin .telnet tn20 /dev/pts/8 6 Tue Oct 27 22:45:15 1998 unyun tn20 pts/8 7 Tue Oct 27 22:45:18 1998 unyun2がtelnetでlogin addely ftp ftp9569 7 Tue Oct 27 22:45:38 1998 addelyがftpでlogin .rlogin rl10 /dev/pts/11 6 Tue Oct 27 22:45:58 1998 unyun rl10 pts/11 7 Tue Oct 27 22:46:00 1998 unyun3がrloginでlogin ftp ftp9569 7 Tue Oct 27 22:46:09 1998 addelyがftplogout .rlogin rl20 /dev/pts/12 6 Tue Oct 27 22:46:49 1998 addely rl20 pts/12 7 Tue Oct 27 22:46:58 1998 addelyがrloginでlogin .telnet tn30 /dev/pts/13 6 Tue Oct 27 22:47:15 1998 rockhop tn30 pts/13 7 Tue Oct 27 22:47:18 1998 rockhopがtelnetでlogin .telnet tn40 /dev/pts/14 6 Tue Oct 27 22:47:37 1998 humboldt tn40 pts/14 7 Tue Oct 27 22:47:41 1998 humboldtがtelnetでlogin humboldt tn40 pts/14 8 Tue Oct 27 22:47:42 1998 humboldtがtelnetlogout rockhop tn30 pts/13 8 Tue Oct 27 22:47:54 1998 rockhopがtelnetlogout humboldt ftp ftp9609 7 Tue Oct 27 22:48:17 1998 humboldtがftpでlogin addely rl20 pts/12 8 Tue Oct 27 22:48:23 1998 addelyがrloginlogout .rlogin rl20 /dev/pts/12 6 Tue Oct 27 22:48:45 1998 unyun rl20 pts/12 7 Tue Oct 27 22:48:47 1998 unyun3がrloginでlogout .rlogin rl30 /dev/pts/13 6 Tue Oct 27 22:49:16 1998 rockhop rl30 pts/13 7 Tue Oct 27 22:49:17 1998 rockhopがrloginでlogin ftp ftp9609 7 Tue Oct 27 22:49:35 1998 humboldtがftplogout unyun tn10 pts/7 8 Tue Oct 27 22:49:46 1998 unyun1がtelnetlogout unyun tn20 pts/8 8 Tue Oct 27 22:49:47 1998 unyun2がtelnetlogout rockhop rl30 pts/13 8 Tue Oct 27 22:49:54 1998 rockhopがrloginlogout ・・・以下略 [utmp] Name id Line Type Time ------------------------------------------------------ unyun tn10 pts/7 7 Tue Oct 27 22:50:43 1998 tn10はunyunがlogin中 snares tn20 pts/8 7 Tue Oct 27 22:52:10 1998 tn20はsnareslogin中 humboldt rl10 pts/11 8 Tue Oct 27 22:53:59 1998 rl10はhumboldtが最終 unyun rl20 pts/12 7 Tue Oct 27 22:48:47 1998 rl20はunyunがlogin中 gentoo tn30 pts/11 8 Tue Oct 27 22:53:25 1998 tn30はgentooが最終 humboldt tn40 pts/14 8 Tue Oct 27 22:47:42 1998 tn40はhumboldtが最終 rockhop rl30 pts/8 8 Tue Oct 27 22:51:23 1998 rl30はrockhopが最終 [lastlog] Name : Host Line Time ------------------------------------------------------ unyun : hacker.com 73 Tue Oct 27 22:53:01 1998 unyunは22:53:10にftp humboldt: pentagon.com pts/11 Tue Oct 27 22:53:57 1998 humboldtは22:53:57にlogin rockhop : yyy.ne.jp pts/11 Tue Oct 27 22:52:26 1998 rockhopは22:52:26にlogin addely : hacker.com pts/12 Tue Oct 27 22:46:58 1998 addelyは22:46:58にlogin snares : pentagon.com pts/8 Tue Oct 27 22:52:10 1998 snaresは22:52:10にlogin gentoo : xxx.ac.jp pts/11 Tue Oct 27 22:53:25 1998 gentooは22:53:25にlogin Fig.6 ログサンプル 4. ZAP系ログ消しとその問題点 ZAPは,指定されたユーザ名を含むエントリを全てnullで埋めます.lastコマンドなど は,nullがあるとその行は表示しないという特徴があり,それを利用したものです.つ まり,Fig.6の例にZAP系ログ消しツールを用いてユーザunyunとaddelyを削除した場 合,ログはFig.7のようになります. ※ wtmpx,utmpxは省略してあります. [wtmp] Name id Line Type Time -------------------------------------------------------------------- .telnet tn10 /dev/pts/7 6 Tue Oct 27 22:44:42 1998 .telnet tn20 /dev/pts/8 6 Tue Oct 27 22:45:15 1998 .rlogin rl10 /dev/pts/11 6 Tue Oct 27 22:45:58 1998 ftp ftp9569 7 Tue Oct 27 22:46:09 1998 .rlogin rl20 /dev/pts/12 6 Tue Oct 27 22:46:49 1998 .telnet tn30 /dev/pts/13 6 Tue Oct 27 22:47:15 1998 .telnet tn40 /dev/pts/14 6 Tue Oct 27 22:47:37 1998 humboldt tn40 pts/14 7 Tue Oct 27 22:47:41 1998 humboldt tn40 pts/14 8 Tue Oct 27 22:47:42 1998 rockhop tn30 pts/13 8 Tue Oct 27 22:47:54 1998 humboldt ftp ftp9609 7 Tue Oct 27 22:48:17 1998 .rlogin rl20 /dev/pts/12 6 Tue Oct 27 22:48:45 1998 .rlogin rl30 /dev/pts/13 6 Tue Oct 27 22:49:16 1998 rockhop rl30 pts/13 7 Tue Oct 27 22:49:17 1998 ftp ftp9609 7 Tue Oct 27 22:49:35 1998 rockhop rl30 pts/13 8 Tue Oct 27 22:49:54 1998 ・・・以下略 [utmp] Name id Line Type Time -------------------------------------------------------------------- snares tn20 pts/8 7 Tue Oct 27 22:52:10 1998 humboldt rl10 pts/11 8 Tue Oct 27 22:53:59 1998 unyun rl20 pts/12 7 Tue Oct 27 22:48:47 1998 gentoo tn30 pts/11 8 Tue Oct 27 22:53:25 1998 humboldt tn40 pts/14 8 Tue Oct 27 22:47:42 1998 [lastlog] Name : Host Line Time --------------------------------------------------------------------- humboldt : pentagon.com pts/11 Tue Oct 27 22:53:57 1998 rockhop : yyy.ne.jp pts/11 Tue Oct 27 22:52:26 1998 snares : pentagon.com pts/8 Tue Oct 27 22:52:10 1998 gentoo : xxx.ac.jp pts/11 Tue Oct 27 22:53:25 1998 Fig.7 ZAP系ログ消しで消されたログ このように,いたるところにnullによる空行ができ,lastlogより消されたユーザ,wtmp の.telnet,.rloginエントリなどから侵入時刻が特定できます(IRIX等ではログ保存形式 が異なるため,不正使用ユーザのlogout時刻も特定できます).何より,ログを消した痕 跡が完全に残ってしまいます.しかし,少し工夫すれば,これらの痕跡を消すことも可能 です. 5. 痕跡の分からないログの消去法 特定のユーザの1エントリ分のログを削除したい場合,wtmp/wtmpxの場合は,そのユ ーザが使用している他のエントリも消す必要があります.telnetの場合,ユーザ名がName 部にロギングされるのはエントリタイプが7と8の時だけで,6の時は.telnet等の名前 でロギングされます.つまり,login中にログを削除したい場合,エントリタイプの6,7, 過去のログを削除したい場合は6,7,8を削除する必要があります.ftpの場合も,ftplogout 後は1ユーザにつき2エントリ分削除しないと,Nameが空白のエントリが残ってしまい ます.これらに注意してwtmp/wtmpxのログを削除しなければなりません.また,utmp/utmpx に関しては,wtmp/wtmpxで対象となったエントリかどうかを検査する必要があります. つまり,wtmp/wtmpxで対象となったユーザのidがtn10であった場合,utmp/utmpxでは tn10以外のログを変更してはいけません.そして,utmp/utmpx中のtn10のエントリは削 除するのではなく,対象となったユーザより一つ古い同一idのユーザのものと置きかえ る必要があります.置き換えは,エントリタイプは8でないと,whoで出てきますので8 のものを選びます.lastログはwtmp/wtmpxを検査して,消去したいエントリと同一ユー ザ名の一つ古いwtmp/wtmpxエントリからパラメータを抽出して埋める必要があります. これらの一連の作業を行うログ消しがulw.cです.なお、このツールは、実験用です。 実際にどこかに侵入してコレをつかってログを消さないようにしましょうね。 6. ulwの使い方 ulwはココのHPで入手できます.まず,ulwをコンパイルしてください. %cc ulw.c -o ulw (もしくは gcc ulw.c -o ulw) Rootになる #./ulw 消したいユーザ名 これで,指定したユーザのログが1つ分消えます.最新のログから消えていきます. なお, #./ulw -u で,zapなどで消去されたログを可能な限り再構築し,ZAP系ログ消しの痕跡を消します. また, #./ulw -u 消したいユーザ名 とすると,ZAP系ログの再構築を行ってから,指定ユーザのログ消しを行います. 7. さいごに ログが痕跡も残さず消せるからって、どっかに侵入してログをさらっと消してくるなんて のはやめましょうね。追跡できなくなってしまう可能性もありますから(笑) − 参考文献 − [1] Reverse,"xxプログラミング","http://members.tripod.com/‾reverse/",1998 [2] "wtmpx.c","zap2.c" − 参考資料 − [ Solaris2.6 utmp,utmpx構造体抜粋 ] struct exit_status { short e_termination; /* Process termination status */ short e_exit; /* Process exit status */ }; struct utmp { char ut_user[8]; /* User login name */ char ut_id[4]; /* /etc/inittab id(usually line #) */ char ut_line[12]; /* device name (console, lnxx) */ short ut_pid; /* short for compat. - process id */ short ut_type; /* type of entry */ struct exit_status ut_exit; /* The exit status of a process */ /* marked as DEAD_PROCESS. */ time_t ut_time; /* time entry was made */ }; struct utmpx { char ut_user[32]; /* user login name */ char ut_id[4]; /* inittab id */ char ut_line[32]; /* device name (console, lnxx) */ pid_t ut_pid; /* process id */ short ut_type; /* type of entry */ #if !defined(_XPG4_2) || defined(__EXTENSIONS__) /*通常はこの条件はtrue*/ struct exit_status ut_exit; /* process termination/exit status */ #else struct ut_exit_status ut_exit; /* process termination/exit status */ #endif struct timeval ut_tv; /* time entry was made */ long ut_session; /* session ID, used for windowing */ #if !defined(_XPG4_2) || defined(__EXTENSIONS__) /*通常はこの条件はtrue*/ long pad[5]; /* reserved for future use */ #else long __pad[5]; /* reserved for future use */ #endif short ut_syslen; /* significant length of ut_host */ /* including terminating null */ char ut_host[257]; /* remote host name */ } struct lastlog { time_t ll_time; char ll_line[8]; char ll_host[16]; /* same as in utmp */ };