MOPB-23-2007:PHP 5 Rejected Session Identifier Double Free Vulnerability

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

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

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

■PoCまたは攻撃コード
MOPB-23-2007.php
http://www.php-security.org/MOPB/code/MOPB-23-2007.php

■リファレンス
MOPB-22-2007.php
http://www.php-security.org/MOPB/code/MOPB-23-2007.php

■サマリ
PHP 5.2.0のセッションモジュールからセッションIDを拒否できるようになりました。例えば悪意があると思われる文字などで拒否します。セッションモジュールにセッションIDが無効であることが通知されると、セッションID生成コードを呼び出す前に既に開放済みの無効なセッションIDへポインタをクリアしていません。セッションID生成コード中でエラーが発生した場合、ローカルからは簡単に攻撃可能、リモートからも攻撃可能となる可能性がある、ダブルフリーが発生させることができます。

■影響するバージョン
内部のセッションストレージモジュールがセッションIDを拒否する場合、フラグを設定してセッションモジュールに通知します。このアドバイザリを書いている時点では、デフォルトのファイルストレージモジュールのみ、このフラグを利用しています。無効なセッションIDが送信され、このフラグが設定された場合、無効なIDへのポインタは開放され新しいIDへのポインタが設定されます。


new_session:
PS(id) = PS(mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC);

PS(invalid_session_id) = 0;
if (PS(mod)->s_read(&PS(mod_data), PS(id), &val, &vallen TSRMLS_CC) == SUCCESS) {
php_session_decode(val, vallen TSRMLS_CC);
efree(val);
} else if (PS(invalid_session_id)) { /* address instances where … due to an invalid id */
PS(invalid_session_id) = 0;
efree(PS(id));
goto new_session;
}

しかし、この代入はアトミックな操作ではありません。memory_limit制限などにより割り込み可能です。PHPの設定によっては、PHPエラーによりセッションID生成コード中に割り込むことができます。

PHPAPI char *php_session_create_id(PS_CREATE_SID_ARGS)
{

switch (PS(hash_func)) {

default:
php_error_docref(NULL TSRMLS_CC, E_ERROR, “Invalid session hash function”);
efree(buf);
return NULL;
}

if (PS(hash_bits_per_character) < 4
|| PS(hash_bits_per_character) %gt; 6) {
PS(hash_bits_per_character) = 4;

php_error_docref(NULL TSRMLS_CC, E_WARNING, “The ini setting hash_bits_per_character…”);
}

このため悪意のあるユーザ定義エラーハンドらを利用してこの問題をローカルから攻撃するのは非常に簡単です。このハンドラが呼ばれた時、前のセッションIDが配置された同じ場所にハッシュテーブルが割り当てられます。ユーザエラーハンドラが終了する際にPHPは上書きされたハッシュテーブルを解放し、攻撃者のコードを実行します。

■PoC、攻撃コードまたは再現手順
添付の攻撃コードを実行すると、substr_compare()関数の情報漏えい脆弱性を利用してシェルコードのアドレスを決定して実行します。

■備考
この脆弱性は前の脆弱性と非常に良く似ています。同じ種類・分類の脆弱性ですが、これらは同じ脆弱性ではありません。攻撃方法はほとんど同じですが、脆弱性を発生させるコードはそれぞれ別のPHPバージョンから導入され、直接関係していません。さらに、この脆弱性は、前の脆弱性と異なり、リモートからの攻撃が容易な物になっています。従ってリモートからの攻撃が可能である可能性は高くなっています。この仮定が正しいか将来調査するかもしれません。

投稿者: yohgaki