MOPB-27-2007:PHP ext/gd Already Freed Resource Access Vulnerability

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

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

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

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

■リファレンス
なし

■サマリ
GD関数が呼ばれた場合、その後の処理のために最初にリソースデータが取得されます。リソースデータの取得後にこれらの関数がエラーで割り込まれた場合、悪意のあるユーザエラーハンドラによりイメージリソースを特別に用意された偽のリソースへの置き換えが可能になります。これは任意のメモリアドレスへの読み書きを許し、任意コードの実行に利用可能です。

■影響するバージョン
PHP 4.4.6以下、PHP 5.2.1以下
(訳注:ただしGD以外のモジュールには最新版でも同類の脆弱性がある)

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

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

関数に割り込むには、通常、オブジェクトを引数として渡すだけで十分です。オブジェクトを引数として渡すとPHPはlong型への変換の際にエラーを発生させます。関数が発生させる他の警告エラーや通知エラーも利用可能です。

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

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

■備考
この種類の脆弱性はGDモジュールのみでなく、他の多くのモジュールも脆弱です。

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

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

投稿者: yohgaki