MOPB-28-2007:PHP hash_update_file() Already Freed Resource Access Vulnerability

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

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

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

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

■リファレンス
なし

■サマリ
hash_update_file()が呼ばれると、その後の処理のために最初にリソースデータが取得されます。そして、ハッシュ値を取得する為にデータをストリームから読みます。悪意のあるユーザストリームハンドラはハッシュリソースを破壊し、改ざんしたハッシュ関数ポインタテーブルを含む特別に作れた偽のリソースに置き換えることができます。関数が実行され続けると、書き換えられた関数ポインタを呼び出すのでシェルコードを実行できます。

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

■詳細情報
PHP関数はZendエンジンに登録したリソースを維持しなければなりません。リソースシステムは参照カウンタを持っており参照カウンタはリソースを保持するPHP変数の参照数のみ保持しています。しかし、幾つの関数がリソースを使っているか数えるカウンタはありません。

このため、PHPコードの中に特別なバグの種類が存在します。PHP関数がリソースデータを取得した後にユーザコードによる割り込みが可能な場合、リソースを解放し、例えば同じサイズの文字列を解放されたリソースとして同じメモリ位置に割り当てることが可能です。悪意のある割り込みにより関数が終了し、置き換えられたリソースデータを継続して使用すると、このPHP文字列は特別に生成されたリソースを作るために利用でき、PHP関数により攻撃に利用できます。

このバグは攻撃に必要な割り込みはユーザ定義エラーハンドラのみでなくユーザ定義ストリームハンドラも利用可能であることをデモンストレーションしています。

■PoC、攻撃コードまたは再現手順
添付の攻撃コードはsubstr_compare()関数の情報漏洩脆弱性を利用して有効なオフセットを決定しています。このため、攻撃コードはPHP5 のみで動作します。しかし、より多くのメモリ情報リークが可能な他のGD関数を使用して良い効率的なpeek()関数を実装できます。したがってこの攻撃はPHP4でも行えます。

攻撃コードはいつものように4444ポートに接続するとシェルを起動します。

■備考
この脆弱性は、関数に割り込むためにユーザ定義エラーハンドラでなくユーザ定義ストリームハンドラが利用されている事を除けば、MOPB-27-2007と同じ種類の脆弱性です。

適切な修正は、PHPのリソースシステムに使用数のカウンタをサポートするように作り直し、利用するようにしなければなりません。または、リソースの参照カウンタをこの目的に利用することも可能です。

この問題の修正には非常に多くの作業が必要であるため短期間での修正は難しいでしょう。

投稿者: yohgaki