システムコール引数の暗号化によるコード注入攻撃の防止

システムコール引数の暗号化による
コード注入攻撃の防止
大山 恵弘
米澤 明憲
(東京大学)
2004/11/16
第16回コンピュータシステム・シンポジウム
コード注入攻撃
バッファ
return address
悪意コードを
注入!
011100001011
バッファ
011101010010
110011000100
011011001101
return address
101010110110
…
return address
を上書き!
スタック
スタック
注入されるコードの例
unsigned char exploit[]=
...
execveのシステムコール
番号11をeaxにセット
"¥xb8\x1b\x11\x11\x11" /* movl $0x1111111b, %eax */
"\x2d\x10\x11\x11\x11" /* subl $0x11111110, %eax */
システムコール引数を
ebx, ecx, edxにセット
"¥x8b\x5d\x08" /* movl 0x8(%ebp), %ebx */
"\x8b\x4d\x0c" /* movl 0xc(%ebp), %ecx */
"\x8b\x55\x10" /* movl 0x10(%ebp), %edx */
"¥xcd\x80"; /* int $0x80 */
システムコール割り込み
提案方式

システムコール番号と引数を暗号化/復号
アプリケーション
syscall(11, 12000, 800)
改造libc
暗号化
syscall(39406, 57614, 20881)
カーネルモジュール
syscall(11, 12000, 0)
カーネル
復号
効果

悪意コードが発行するシステムコールは
異常な番号と引数に変わる
攻撃者によるexecveなどの実行が失敗する
 悪意コードはエラーで終了する

実装
libcとカーネルモジュールで鍵を共有
 プロセス生成時に暗号化の鍵を作成

プロセスごとに異なる鍵を使用
 RC4などのストリーム暗号を利用


LD_PRELOADなどを用い、動的リンクする
libcを変更する
鍵の生成と共有
アプリケーション
fork()
改造libc
ここに鍵を保持
p
cfork(p)
カーネルモジュール
cfork(char *buf){ … }
• 鍵を生成
• bufとqに鍵を書き込む
fork()
カーネル
ここに鍵を保持
q
制限
return-into-libc攻撃を防止できない
 元のlibcを静的リンクしたプログラムでは
暗号化が行われない
 巧妙な攻撃コードは鍵を盗める
 システムコールフックを利用するシステム
(デバッガ、トレーサなど)が使えなくなる

関連研究

システムコール表をかきまぜてカーネルを
再コンパイルする


スタック上の制御情報(return address等)に
乱数をXORする


[Chew & Song ’02]
[StackGuard]
CPU命令セットを乱数でかきまぜる



[Barrantes et al ’03]
[Kc et al. ’03]
[大澤 et al. ’00]
今後の仕事
オーバヘッドの計測
 実際の攻撃コードを用いた実証実験
 マルチスレッド、SMPへの拡張
