MOPB-30-2007:PHP _SESSION unset() Vulnerability

(Last Updated On: )

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

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

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

■リファレンス
なし

■サマリ
セッション拡張モジュールは、セッショングローバル内の内部ポインタを含めていないため、セッション変数に正しい参照カウンタ値を設定していません。この為、$_SESSION配列と$HTTP_SESSION_VARSをunset()するとセッションデータを保持するハッシュテーブルは解放されているにも関わるセッションモジュールの内部ポインタはリセットされずセッションモジュール内で使い続けられます。この動作はハッシュテーブルを任意コードを実行するための特別に用意された文字列に置き換えることを許してしまいます。

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

■詳細情報
サマリが全てを解説しています。詳しくは攻撃コードを試してみてください。

■PoC、攻撃コードまたは再現手順
添付のPoCコードはこの脆弱性を使用してシェルコードを実行します。例えば、最初はNULLであるzend_execute_internal(訳注:PHPの内部のZendエンジンの関数)へのオフセットが必要です。

単純にシェルコードを入れ替えることはできません。シェルコードは特別に用意されたx86のjmpインストラクションをシェルコードのnopspeceにするハッシュキーを持つハッシュテーブルバケット用に作られている為です。

■備考
通常の状態ではこの脆弱性はローカルかのみ攻撃できます。しかし、特定の状況下ではリモートコード実行が可能となります。リモートからコード実行を行うにはアプリケーションが$HTTP_SESSION_VARSと$_SESSIONをunsetするようなコードを持っていなければなりません。unsetはsession_strat()関数が呼び出された後か自動的にセッションが開始された後に呼び出されなければなりません。両方の状況が当てはまる場合、リモートからのコード実行が可能となるかもしれません。

投稿者: yohgaki