MOPB-37-2007:PHP iptcembed() Interruption Information Leak Vulnerability

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

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

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

■PoCまたは攻撃コード
MOPB-37-2007.php

■リファレンス
なし

■サマリ
関数がリファレンスを受け入れる場合(デフォルト設定で受け入れるようになっている)悪意のあるユーザ定義エラーハンドラで関数が既に実行を開始しパラメータを変更した後に割り込みが可能です。このアドバイザリは関数を使って任意のメモリアドレスを読み込む例となっています。iptcembed()関数はこの種の脆弱性の例で、攻撃者は任意のヒープメモリのリークに利用できます。

■影響するバージョン
PHP 4.4.6以下、PHP 5.2.1以下

■詳細情報
iptcembed()関数が呼ばれると、3つの引数が定義されている形式に変換されます。

if (zend_get_parameters_ex(3, &iptcdata, &jpeg_file, &spool_flag) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(iptcdata);
convert_to_string_ex(jpeg_file);
convert_to_long_ex(spool_flag);
spool = Z_LVAL_PP(spool_flag);

残念ながらconvert_to_*関数は特定の条件でエラーを発生させます。例えば、配列をjpeg_fileとして渡す、spool_flag引数にオブジェクトを渡すなどです。このような状況が発生するとユーザ定義エラーハンドラは、はじめにiptcdata保持する変数をintにキャストし、その後longに値とします。これにより文字列と間違えられ、文字列の長さを保持するメモリ位置のlong値で指定された長さとしたZVALを作成できます。

簡単なトリックで任意のメモリブロックをリークされる事ができるのは明らかです。

■PoC、攻撃コードまたは再現手順
添付の攻撃コードが実行されると0x08048000から256バイトリークします。通常のLinuxシステムはこのアドレスに現在実行中のプログラムのELFヘッダが保存されています。

memdump
———

00000000: 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 02 ELF………….
00000010: 00 03 00 01 00 00 00 d0 72 08 08 34 00 00 00 bc ……..r..4….
00000020: 1d b7 00 00 00 00 00 34 00 20 00 08 00 28 00 26 …….4. …(.&
00000030: 00 23 00 06 00 00 00 34 00 00 00 34 80 04 08 34 .#…..4…4…4
00000040: 80 04 08 00 01 00 00 00 01 00 00 05 00 00 00 04 …………….
00000050: 00 00 00 03 00 00 00 34 01 00 00 34 81 04 08 34 …….4…4…4
00000060: 81 04 08 13 00 00 00 13 00 00 00 04 00 00 00 01 …………….
00000070: 00 00 00 01 00 00 00 00 00 00 00 00 80 04 08 00 …………….
00000080: 80 04 08 60 af 3a 00 60 af 3a 00 05 00 00 00 00 …`.:.`.:……
00000090: 10 00 00 01 00 00 00 00 b0 3a 00 00 30 3f 08 00 ………:..0?..
000000a0: 30 3f 08 ac 84 02 00 cc 19 04 00 06 00 00 00 00 0?…………..
000000b0: 10 00 00 02 00 00 00 14 b0 3a 00 14 30 3f 08 14 ………:..0?..
000000c0: 30 3f 08 50 01 00 00 50 01 00 00 06 00 00 00 04 0?.P…P……..
000000d0: 00 00 00 04 00 00 00 48 01 00 00 48 81 04 08 48 …….H…H…H
000000e0: 81 04 08 20 00 00 00 20 00 00 00 04 00 00 00 04 … … ……..
000000f0: 00 00 00 50 e5 74 64 98 ae 3a 00 98 2e 3f 08 00 …P.td..:…?..

■備考
この分類の脆弱性はZendエンジンのアーキテクチャ上の脆弱性です。我々はこの例のような割り込みバグが
直ぐに修正されるとは考えていません。allow_call_time_pass_referenceを無効にすることはこのアドバイザリの攻撃コードを無効化させるには役立ちます。しかし、リファレンスや別のデータ構造が渡される場合、類似する「関数割り込み攻撃」から守ることはできません。

投稿者: yohgaki