MOPB-35-2007:PHP 4 zip_entry_read() Integer Overflow Vulnerability

(Last Updated On: 2018年8月16日)

Stefanさんの承諾を得て日本語訳を公開しています。このブログの「the Month of PHP Bugs」カテゴリでMOPBの翻訳ページを一覧できます。分かりやすいように意訳できる部分は意訳します。厳密に原文の通り訳していないので正確性を重視される方は原文をご覧ください。

■クレジット
発見者:Stefan Esser
攻撃コード:Stefan Esser

■PoCまたは攻撃コード
MOPB-35-2007.php
x.zip

■リファレンス
なし

■サマリ
zip_read_entry()関数は.ZIPアーカイブの保存されている内容を読み込むために利用されます。この関数は整数オーバーフローに脆弱性で攻撃可能なバッファオーバーフローを引き起こします。

■影響するバージョン
PHP 4.4.5未満

■詳細情報
zip_read_entry()関数は受け渡された長さ引数を全くチェックしていません。これにより、メモリ確保時に文字列の終端のASCIIZバイトを保存するための1バイトを追加するさいに整数オーバーフローが発生します。

buf = emalloc(len + 1);
ret = zzip_read(entry->fp, buf, len);
buf[ret] = 0;

長さ引数に0xffffffffが渡されるとサイズ0のメモリブロック割り当てられ、4GBまでのデータがZIPアーカイブとしてこのメモリブロックに読み込まれます。これにより確保されたメモリブロック以降の全てのデータの書き換えが可能となり任意コードの実行を可能とします。

■PoC、攻撃コードまたは再現手順
添付の攻撃コードは小さなPHPのPoCとバッファをオーバーフローさせるデータを含んだZIPアーカイブで構成されます。これは普通のヒープオーバーフローなのでPoCはunlinkマクロ内でクラッシュすることだけ明らかにしています。

$ gdb ./php
(…)
(gdb) run MOPB-35-2007.php
Starting program: /../php-4.4.4/sapi/cli/php MOPB-35-2007.php

Program received signal SIGSEGV, Segmentation fault.
0x0812c127 in _efree (ptr=0x81d76ec) at /../php-4.4.4/Zend/zend_alloc.c:274
274 REMOVE_POINTER_FROM_LIST(p);
(gdb) x/5i $eip
0x812c127 <_efree+71>: mov %eax,(%edx)
0x812c129 <_efree+73>: mov (%ebx),%edx
0x812c12b <_efree+75>: test %edx,%edx
0x812c12d <_efree+77>: je 0x812c135 <_efree+85>
0x812c12f <_efree+79>: mov 0x4(%ebx),%eax
(gdb) i r
eax 0x44444444 1145324612
ecx 0x8c8c8c9 147376329
edx 0x45454545 1162167621
ebx 0x81d76e0 136148704
esp 0xbff3ae20 0xbff3ae20
ebp 0xbff3ae28 0xbff3ae28
esi 0x81d265c 136128092
edi 0x81d71b4 136147380
eip 0x812c127 0x812c127 <_efree+71>
eflags 0x10216 66070
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)

■備考
特別な事はありません。通常のヒープオーバーフローです。

投稿者: yohgaki