Comments
Description
Transcript
このページのPDF
ISEC セキュア・プログラミング講座 IPA IPA 7-6. coreファイルから情報が漏れる 第 7 章 セキュア Unix / Linux プログラミング [7-6.] core ファイルから情報が漏れる Unix/Linuxプロセスが異常終了するとcoreファイルが生成される。coreファ イルは異常終了したプロセスのメモリイメージをそのまま保存したもので,デ バッグや異常終了時の原因調査に役立つ。しかしcoreファイルが第三者から参 照されると,メモリ上に存在するパスワードなどの機密情報が漏洩してしまう。 ● ● ● core ファイル Unix/Linuxの使用経験がある読者の多くは,ファイルシステム中にcoreファイル(「core」という名前のファ イル)を見つけたことがあるのではないだろうか。図1に示しているcoreファイルは筆者のLinuxのファイル システムで見つかったものだ。一般的に core ファイルのファイルサイズは大きく,ファイルシステムの容量 を圧迫するため,ときに嫌われることもある。coreファイルは図2のようなバイナリファイルである。図2で は Unix のファイルダンプコマンド od を使用して 16 進ダンプし,head コマンドでその先頭部分だけを表示し ている。 core ファイルに含まれる情報 Unix プロセスが異常終了すると core ファイルが生成される。core ファイルはプロセスのメモリイメージをそ のまま保存したものでデバッグに重宝する。図2はデバッガ gdb(GNU Debugger)を使用して,プログラム divide の異常終了の原因を調査する様子を示している。 図3の 13 行目にソースファイル divide.c の 25 行目でプログラムが終了したことが示されている。終了個所は 関数 divide()中であり,関数 divide()がコールされたときには引数が a=10,b=0 であったことが示されている。 図3の 14 行目にソースファイル divide.c の 25 行目が示されており,10 を 0 で除算したことによりプログラム が異常終了したことが原因であると分かる。このようにプロセスのメモリイメージがそっくりそのまま core 図1 core ファイル 1 2 3 4 5 6 7 8 9 10 11 $ ls -l total 4212 -rw-rw-r-drwxrwxr-x -rw-------rwxrwxr-x -rw-rw-r-drwxrwxr-x -rwxrwxr-x -rw-rw-r-$ 1 2 1 1 1 2 1 1 foo foo foo foo foo foo foo foo bar bar bar bar bar bar bar bar 55 4096 4247552 19391 445 4096 11734 90 -1- Oct 9 03:35 Makefile Oct 9 09:40 bad Nov 7 06:56 core ← core ファイル Nov 7 06:54 divide Nov 7 06:51 divide.c Oct 11 14:03 good Oct 9 03:35 sleep Oct 9 03:35 sleep.c Copyright Copyright © 2002 IPA, All Rights Reserved. ISEC セキュア・プログラミング講座 IPA IPA 7-6. coreファイルから情報が漏れる 図2 core ファイルのダンプ $ od -tx1 -Ax core | head -20 000000 7f 45 4c 46 01 01 01 00 00 000010 04 00 03 00 01 00 00 00 00 000020 00 00 00 00 00 00 00 00 34 000030 00 00 00 00 04 00 00 00 74 000040 00 00 00 00 ac 06 00 00 00 000050 00 00 00 00 01 00 00 00 00 000060 00 00 00 00 00 00 00 00 00 000070 00 10 00 00 01 00 00 00 00 000080 00 00 00 00 00 10 00 00 00 000090 00 10 00 00 01 00 00 00 00 0000a0 00 00 00 00 00 00 00 00 00 0000b0 00 10 00 00 01 00 00 00 00 0000c0 00 00 00 00 00 10 00 00 00 0000d0 00 10 00 00 01 00 00 00 00 0000e0 00 00 00 00 00 20 00 00 00 0000f0 00 10 00 00 01 00 00 00 00 000100 00 00 00 00 00 00 00 00 00 000110 00 10 00 00 01 00 00 00 00 000120 00 00 00 00 00 40 00 00 00 000130 00 10 00 00 01 00 00 00 00 Broken pipe $ 00 00 00 01 00 10 10 10 10 20 30 20 10 30 20 50 d0 50 40 90 00 00 20 00 00 00 00 00 00 00 01 00 00 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 34 0a 00 00 00 05 00 06 00 05 00 06 00 06 00 05 00 06 00 00 00 00 00 00 80 00 90 00 00 00 30 00 40 00 90 00 60 00 a0 00 00 00 00 00 04 00 04 00 00 00 01 00 01 00 01 00 10 00 10 00 00 00 00 00 08 00 08 00 40 00 40 00 40 00 40 00 40 00 40 図3 core ファイルによるデバッグ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ gdb -c core divide GNU gdb 19991004 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"... Core was generated by `./divide 0'. Program terminated with signal 8, Floating point exception. Reading symbols from /lib/libc.so.6...done. Reading symbols from /lib/ld-linux.so.2...done. #0 0x8048480 in divide (a=10, b=0) at divide.c:25 ←プログラムが終了した個所 25 c = a/b; ← divide.c の 25 行目 (gdb) quit $ ファイルに保存されているため,デバッガによるプログラム動作の追跡調査が可能である。 シグナルと core ファイルの生成 シグナルは Unix / Linux のソフトウェア割り込み機構で非同期処理の実装に利用される。あるプロセスがシ グナルを受信すると,そのプロセスが現在実行している処理を一旦停止し,そのシグナルに対応したシグナ ルハンドラを実行する。シグナルハンドラの処理が終了すると,もとの処理を再開する。シグナルハンドラ はプロセスがシグナルを受信したときに実行する関数である。 -2- Copyright Copyright © 2002 IPA, All Rights Reserved. ISEC セキュア・プログラミング講座 IPA IPA 7-6. coreファイルから情報が漏れる OSによって若干差異があるが,シグナルには30前後の種類がある。参考として図4にLinuxで定義されてい るシグナルを示す。各プロセスにはシグナルの種類ごとにシグナルハンドラを設定することができる。シグ ナルハンドラが設定されていないシグナルをプロセスが受信した場合,プロセスはデフォルトの処理を行う。 デフォルト処理はシグナルごとに異なるが,次の 5 種類のうちのどれかである。 ・シグナルを無視 ・プロセスを終了 ・core ファイルを生成してプロセスを終了 ・プロセスをサスペンド(一時停止) ・サスペンドしているプロセスを再開 シグナルごとに上記のどのデフォルト処理が割り当てられているかは,OSによって若干差異がある。図4で はLinuxの場合を参考として,デフォルト処理がcoreファイルを生成してプロセスを終了するシグナルに「← core」と示した。 シグナルは様々な要因によってプロセスへ送信される。図4の右側に書かれたコメント部分にシグナルを発 生させる要因が示されている。例えば図3で示したプログラムdivideの異常終了原因となった0による除算は, 図4の 10 行目にある SIGFPE(浮動小数点演算例外)シグナルを発生させた。このシグナルにより core ファ イルが生成され,プログラムは異常終了したのだ。また適切な実行権限があれば,kill()システムコールによ り任意のプロセスに対して任意のシグナルを明示的に送信することも可能である。 図4 Linux のシグナル /usr/include/bits/signum.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 /* Signals. */ #define SIGHUP #define SIGINT #define SIGQUIT #define SIGILL #define SIGTRAP #define SIGABRT #define SIGIOT #define SIGBUS #define SIGFPE #define SIGKILL #define SIGUSR1 #define SIGSEGV #define SIGUSR2 #define SIGPIPE #define SIGALRM #define SIGTERM #define SIGSTKFLT #define SIGCLD #define SIGCHLD #define SIGCONT #define SIGSTOP #define SIGTSTP #define SIGTTIN #define SIGTTOU #define SIGURG #define SIGXCPU #define SIGXFSZ #define SIGVTALRM #define SIGPROF #define SIGWINCH #define SIGPOLL #define SIGIO #define SIGPWR #define SIGSYS #define SIGUNUSED 1 2 3 4 5 6 6 7 8 9 10 11 12 13 14 15 16 SIGCHLD 17 18 19 20 21 22 23 24 25 26 27 28 SIGIO 29 30 31 31 /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* Hangup (POSIX). */ Interrupt (ANSI). */ Quit (POSIX). */ ← core Illegal instruction (ANSI). */ ← core Trace trap (POSIX). */ ← core Abort (ANSI). */ ← core IOT trap (4.2 BSD). */ ← core BUS error (4.2 BSD). */ Floating-point exception (ANSI). */ ← core Kill, unblockable (POSIX). */ User-defined signal 1 (POSIX). */ Segmentation violation (ANSI). */ ← core User-defined signal 2 (POSIX). */ Broken pipe (POSIX). */ Alarm clock (POSIX). */ Termination (ANSI). */ Stack fault. */ Same as SIGCHLD (System V). */ Child status has changed (POSIX). */ Continue (POSIX). */ Stop, unblockable (POSIX). */ Keyboard stop (POSIX). */ Background read from tty (POSIX). */ Background write to tty (POSIX). */ Urgent condition on socket (4.2 BSD). */ CPU limit exceeded (4.2 BSD). */ File size limit exceeded (4.2 BSD). */ Virtual alarm clock (4.2 BSD). */ Profiling alarm clock (4.2 BSD). */ Window size change (4.3 BSD, Sun). */ Pollable event occurred (System V). */ I/O now possible (4.2 BSD). */ Power failure restart (System V). */ Bad system call. */ -3- Copyright Copyright © 2002 IPA, All Rights Reserved. ISEC セキュア・プログラミング講座 IPA IPA 7-6. coreファイルから情報が漏れる core ファイルから機密情報が漏洩する core ファイルはプロセスのメモリイメージをそのまま保存したファイルだ。したがって core ファイルにはプ ログラムが扱う機密情報がそのまま保存されてしまう。OSによっては生成するcoreファイルのパーミッショ ンがotherパーミッションによる読み取りを許可してしまうものもある。この場合,ローカルユーザからcore ファイルを解析されてしまう危険性がある。またCGIなどのWebアプリケーションが異常終了するなどして, core ファイルが Web ディレクトリ下に生成されてしまった場合,core ファイルの所有者は Web サーバの実行 ユーザであるため,ブラウザ経由でリモートから core ファイルを取得,解析されてしまう危険性がある。こ のように core ファイルを生成させることは,開発者にとって利便性がある反面,情報漏洩の危険性も伴うこ とを認識する必要がある。 実際に core ファイルからパスワードが読み取れてしまう例を示す。リスト1のプログラム coretest.c は,引数 からパスワード文字列を受け取り,printf()関数(7 行目)で表示し,その後 sleep()関数(8 行目)で 100 秒間 プロセス停止するプログラムである。プロセスが100秒間停止している間に,このプロセスに対しシグナルを 送信することにより,core ファイルを生成させることができる。 実行例1は,プロセスにシグナルを送信し core ファイルを生成させ,core ファイルにパスワード文字列が含 まれていることを確認する実験過程である。1∼4行目でまずcoreファイルが存在しないことを確かめている。 5 行目で coretest.c をコンパイルした coretest プログラムを実行させている。引数にパスワード文字列として 「MyPassword」を指定している。また coretest プログラムがバックグラウンドプロセスとして実行できるよう に,&を指定している。5行目を実行すると,6行目が表示され,バックグラウンドプロセスとして実行させ た coretest プログラムのプロセス ID が 2448 であることが示される。 いよいよ9行目でこのプロセスに対しシグナルを送る。killコマンドによりSIGQUITシグナル(シグナル番号 3)をこのプロセスへ送信している。kill コマンドは kill()システムコールを呼び出すコマンドで,任意のプロ セスに対して任意のシグナルを送信できる。SIGQUITシグナルはデフォルト動作で coreファイルを生成して プロセスを終了させる。9行目を実行した段階でcoreファイルが生成されプロセスは終了するが,シェル上で は何も表示されない。10行目でEnterキーを押すことにより,11行目が表示され,プロセスが終了しcoreファ イルが生成されたことが示される。12∼16行目ではlsコマンドで実際にcoreファイルが生成されていること を確認している。 最後にcoreファイルにパスワード文字列が含まれていることを確認する。17行目では,stringsコマンドとgrep コマンドを組み合わせて,core ファイル中から「My」というキーワードを含む文字列を抽出している。この 出力結果は 18 ∼ 20 行目に表示されており,core ファイルの 3 箇所に「My」を含む文字列が検出され,5 行目 で指定したパスワード文字列「MyPassword」がcoreファイルに含まれていたことが確認できる。なお,strings コマンドはバイナリファイル中から英数文字列のみを抽出し表示する Unix / Linux のコマンドである。 リスト1 coretest.c 1 2 3 4 5 6 7 8 9 10 11 #include <stdio.h> #include <unistd.h> int main(int argc, char* argv[]) { if(argc==2) { printf("your passwd is:%s\n", argv[1]); sleep(100); ←シグナルを受信するまでスリープ } return 0; } -4- Copyright Copyright © 2002 IPA, All Rights Reserved. ISEC セキュア・プログラミング講座 IPA IPA 7-6. coreファイルから情報が漏れる 実行例1 1 2 3 4 $ ls -l total 16 -rwxrwxr-x -rwxrw-r-- 5 $ ./coretest MyPassword & ←パスワード "MyPassword" を引数に指定 & 指定によりバックグラウンドで実行 6 7 8 9 [1] 2448 $ your passwd is:MyPassword ←プロセス ID は 2448 ← printf()関数による出力 $ kill -3 2448 ← SIGQUIT シグナルをプロセスへ送信し強制終了させる 1 foo 1 foo bar bar 10 11 $ ← Enter キーを押す [1]+ Quit 12 13 14 15 16 $ ls -l total 80 -rw-------rwxrwxr-x -rwxrw-r-- 17 18 19 20 21 $ strings core | grep My ./coretest MyPassword your passwd is:MyPassword MyPassword $ 1 foo 1 foo 1 foo 11875 Nov 183 Nov 7 19:01 coretest 7 19:01 coretest.c (core dumped) ./coretest MyPassword ↑ core ファイルが生成されたことを示している bar bar bar 61440 Nov 11875 Nov 183 Nov 7 19:06 core ← core ファイル 7 19:01 coretest 7 19:01 coretest.c ← core ファイル中にて "My" という文字列を検索 ← 1 つ目の "My" を含む文字列が検出された ← 2 つ目の "My" を含む文字列が検出された ← 3 つ目の "My" を含む文字列が検出された このようにプログラムがパスワードなどの機密情報を扱う場合,必ずメモリ中に(少なくとも一瞬の間だけ でも)その情報が含まれているため,core ファイルが生成されてしまうと情報漏洩の危険性に晒される。 core ファイルを生成させない coreファイルは第三者から参照できないように厳重に管理すべきである。サーバOSの設定やWebサーバなど のサードパーティソフトウェアの設定など,多岐に渡る設定項目にミスがないように注意すべきである。も しこれが困難である場合,core ファイルを生成しないようにプログラムを設計すべきだ。 setrlimit()システムコールを使用することで core ファイルの生成を抑止できる。setrlimit()システムコールはプ ロセスに対する各種リソース割り当ての最大値を設定するシステムコールだ。Linuxの場合,setrlimit()システ ムコールを使用して図5のようなリソースの最大値を設定できる。OSによりsetrlimit()システムコールで指定 できるリソースの種類は若干差異がある。 setrlimit()システムコールに RLIMIT_CORE を指定することで,生成される core ファイルの最大ファイルサイ ズを制限できる。最大ファイルサイズを0(ゼロ)に設定することにより,もはやcore ファイルは生成されな くなる。この対策を施したプログラム例をリスト2に示す。 リスト2のプログラム nocoretest.c はリスト1のプログラム coretest.c の改良版である。9 行目に no_corefile()関 数を呼び出す部分を追加し,18行目以降にno_corefile()関数の実体を追加している。no_corefile()関数はsetrlimit ()システムコールを使用して,そのプロセスがcoreファイルを生成しないように設定する関数である。20∼22 -5- Copyright Copyright © 2002 IPA, All Rights Reserved. ISEC セキュア・プログラミング講座 IPA IPA 7-6. coreファイルから情報が漏れる 図5 Linux にて setrlimit()可能なリソース一覧 RLIMIT_CPU RLIMIT_FSIZE RLIMIT_DATA RLIMIT_STACK RLIMIT_CORE RLIMIT_RSS RLIMIT_NOFILE RLIMIT_AS RLIMIT_NPROC RLIMIT_MEMLOCK /* /* /* /* /* /* /* /* /* /* Per-process CPU limit, in seconds. */ Largest file that can be created, in bytes. */ Maximum size of data segment, in bytes. */ Maximum size of stack segment, in bytes. */ Largest core file that can be created, in bytes. Largest resident set size, in bytes. */ Number of open files. */ Address space limit. */ Number of processes. */ Locked-in-memory address space. */ */ リスト2 nocoretest.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <stdio.h> #include <unistd.h> #include <sys/resource.h> void no_corefile(void); int main(int argc, char* argv[]) { no_corefile(); if(argc==2) { printf("your passwd is:%s\n", argv[1]); sleep(100); ←シグナルを受信するまでスリープ } return 0; } void no_corefile(void) { struct rlimit no_core; no_core.rlim_cur = 0; no_core.rlim_max = 0; setrlimit(RLIMIT_CORE, } ← core ファイルを生成させないように setrlimit()システムコールを呼び出す自作の関数 ← core ファイルの最大サイズを 0 バイトに ←以降の rlim_cur の設定変更を禁止 &no_core); ←設定 行目でsetrlimit()システムコールに渡す構造体を初期化し,coreファイルの最大サイズを 0(ゼロ)バイトとし ている。23行目でsetrlimit()システムコールが呼び出され,これ以降の処理でプロセスがシグナルを受信した としても,もはや core ファイルは生成されない。よって main()関数の 10 行目以降では,core ファイルは決し て生成されない。setrlimit()システムコールへ渡す構造体の2つのメンバ変数の意味については,参考文献 『Unix オンラインマニュアル』や『詳細 UNIX プログラミング[新装版]』を参照していただきたい。 実行例2はリスト2の実行結果である。実行例1と同様にkillコマンドによりSIGQUITシグナルを送信し,プ ログラムを強制終了させている。しかし10行目で表示されるメッセージが「Quit」だけになっており, 「(core dumped)」とは表示されていない。実際に11行目以降でファイル一覧を表示しているが,coreファイルが生成 されていないことが確認できる。 -6- Copyright Copyright © 2002 IPA, All Rights Reserved. ISEC セキュア・プログラミング講座 IPA IPA 7-6. coreファイルから情報が漏れる 実行例2 1 2 3 4 5 6 7 8 $ ls -l total 28 -rwxrwxr-x 1 foo bar -rw-rw-r-1 foo bar $ ./nocoretest MyPassword & your passwd is:MyPassword [1] 2899 $ kill -3 2899 9 10 $ ← Enter キーを押す [1]+ Quit 11 12 13 14 15 $ ls -l total 28 -rwxrwxr-x -rw-rw-r-$ 1 foo 1 foo 21822 Nov 403 Nov 7 20:55 nocoretest 7 20:55 nocoretest.c ./nocoretest MyPassword ↑(core dumped)というメッセージがない bar bar ↓ core ファイルは生成されていない 21822 Nov 7 20:55 nocoretest 403 Nov 7 20:55 nocoretest.c まとめ coreファイルは,Unix/Linuxシステムにおいてプロセスの終了時のメモリイメージをそのまま保存したもの である。このメモリイメージからパスワードなどの機密情報が漏洩する可能性がある。第三者から core ファ イルを参照されないように厳重に管理する必要がある。もしそれが困難である場合,setrlimit()システムコー ルを使用して,プログラム自身が core ファイルを生成しないように設計すべきである。 参考文献 『詳細 UNIX プログラミング[新装版]』,W・リチャード・スティーヴンス,大木 敦雄訳,2000 年,株式会社 ピアソン・エデュケーション Unix システム/ Linux システムのオンラインマニュアル 『What is saved in a corefile? (Solaris/SunOS)』 (英文) http://access1.sun.com/cgi-bin/rinfo2html?346499.faq 『AIX Version 4 Files Reference - core File Format』(英文) http://www.unet.univie.ac.at/aix/files/aixfiles/core.htm 『GNU Binary Utilities: objdump, readelf and strings』(英文) http://www.gnu.org/manual/binutils-2.10.1/html_node/binutils_6.html#SEC6 http://www.gnu.org/manual/binutils-2.10.1/html_node/binutils_16.html#SEC16 http://www.gnu.org/manual/binutils-2.10.1/html_node/binutils_9.html#SEC9 -7- Copyright Copyright © 2002 IPA, All Rights Reserved.