...

このページのPDF

by user

on
Category: Documents
3

views

Report

Comments

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.
Fly UP