Stefanさんの承諾を得て日本語訳を公開しています。このブログの「the Month of PHP Bugs」カテゴリでMOPBの翻訳ページを一覧できます。分かりやすいように意訳できる部分は意訳します。厳密に原文の通り訳していないので正確性を重視される方は原文をご覧ください。
■クレジット
発見者:Stefan Esser
攻撃コード:Stefan Esser
■PoCまたは攻撃コード
MOPB-14-2007.php
http://www.php-security.org/MOPB/code/MOPB-14-2007.php
■リファレンス
なし
■サマリ
PHP5にはsubstr_compare関数が付属しています。この関数は2つの引数を持ち、バイナリセーフでオフセットから指定した長さまでの文字列を比較します。オプションで大文字小文字を無視させることも可能です。
この関数は引数をチェックする際に整数オーバーフローが発生します。この結果、バッファを超える比較オフセットとなる場合があります。このオーバーフローはPHP変数背後の重要な情報(オフセット、カナリア値など)の読み取りを許してしまいます。
■影響するバージョン
PHP 5.2.1以下
■詳細情報
substr_compare関数は入力パラメータに対して以下の妥当性チェックを行います。
if (offset < 0) { offset = s1_len + offset; offset = (offset < 0) ? 0 : offset; } if ((offset + len) > s1_len) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The start position cannot exceed ..."); RETURN_FALSE; }
最初のチェックは負の値が文字列の終わりからの値となるようチェックしています。次のチェックはオフセットと要求された長さがバッファの大きさを超えてない事を確認しています。
しかし、二つ目のチェックで行われている2つの正の値の加算は、整数オーバーフローが発生し負の値となる場合がありますが、それを考慮していません。この為、添付の攻撃コードの様にバッファを超えたメモリにアクセス可能になります。
オフセットの範囲外のASCIIZ文字(訳注:NULL文字)とASCII 01文字を比較し、substr_compare関数の戻り値を比較すると、バッファの外のASCII値を知ることができます。この動作は第一引数の後にあるメモリのコピー作成を許してしまいます。
■PoC、攻撃コードまたは再現手順
添付の攻撃コードは変数$xの後ろの4096バイトをリークさせ、16進数ダンプを行います。
memdump --------- 00000000: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 00000010: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 00000020: 41 41 41 41 41 41 00 a7 ec be 5e 2d 00 00 00 35 AAAAAA....^-...5 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000050: 00 00 00 8b ec be 5e 31 00 00 00 2d 00 00 00 00 ......^1...-.... 00000060: 00 00 00 00 00 00 00 14 fb c1 b7 38 fb c1 b7 a8 ...........8.... 00000070: 3e c2 b7 5c fa c1 b7 00 00 00 00 00 00 00 00 10 >..\............ 00000080: 00 00 00 5b ed be 5e 1d 00 00 00 31 00 00 00 84 ...[..^....1.... ...
■備考
この脆弱性は今月公開するコード実行攻撃に必要なオフセットをメモリから直接取得するために利用されます。