Stefanさんの承諾を得て日本語訳を公開しています。このブログの「the Month of PHP Bugs」カテゴリでMOPBの翻訳ページを一覧できます。分かりやすいように意訳できる部分は意訳します。厳密に原文の通り訳していないので正確性を重視される方は原文をご覧ください。
■クレジット
発見者:Stefan Esser
攻撃コード:Stefan Esser
■PoCまたは攻撃コード
必要なし
■リファレンス
なし
■サマリ
外部のコントリビュートモジュールであるOvrimosモジュールはOvrimos SQL Server用のモジュールです。Ovrimos SQL Serverはクライアントサーバ型でWeb機能と高速トランザクションをサポートしたRDBMSです。
このモジュールのソースコードを見ている際に、PHPの内部データ構造と接続を管理するリソースを使っていない事を発見しました。これは非常に危険であり、直接にメモリアクセスを許しコードを実行することを許してしまいます。
■影響するバージョン
PHP 4.4.5未満
■詳細情報
以下がOvrimos拡張モジュールのコードの一部です。
PHP_FUNCTION(ovrimos_longreadlen) { pval *arg1, *arg2; PSTATEMENT stmt; if (getParameters(ht, 2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(arg1); convert_to_long(arg2); stmt = (PSTATEMENT) Z_LVAL_P(arg1); stmt->longreadlen = Z_LVAL_P(arg2); RETURN_TRUE; }
この例では最初のパラメータはSTATEMENT構造体を直接さすポインタです。2つ目のパラメータはSTATEMENT構造体のlongreadlenフィールドに書き込まれます。もちろんこれは任意コード実行攻撃に利用される、任意のメモリアドレスへの任意のデータ書き込みを許してしまいます。
例は複数ある任意コード実行方法の一つだと考えてください。他の攻撃にはovrimos_close()(訳注:モジュール関数)からコード実行を行う任意アドレスでefree()(訳注:PHP内部のC関数)を呼ぶ方法が考えられます。
■PoC、攻撃コードまたは再現手順
Ovrimos拡張モジュールを利用して任意のメモリアドレスに任意の値を書き込むには以下のコードで十分です。
<?php $address = 0xbfbfbfbf /* - sizeof SQLS */; $value = 0xcccccccc; ovrimos_longreadlen($address, $value); ?>
■備考
Ovrimos拡張モジュールのコードは完全に壊れているので、私たちはPHPソースに含めない事を推奨します。もちろんユーザ数は非常に少ないと思われますが、Ovrimosモジュールを含めないことにより間違って有効化する事から全てのユーザを守ることができます。
この問題のインパクトは非常に低いことを認識していますが、重要性が低い脆弱性であっても監査報告には含まれなければなりません。