Archives for: 2007年March
MOPB-30-2007:PHP _SESSION unset() Vulnerability
March 31st, 2007Link: http://www.php-security.org/MOPB/MOPB-30-2007.html
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()関数が呼び出された後か自動的にセッションが開始された後に呼び出されなければなりません。両方の状況が当てはまる場合、リモートからのコード実行が可能となるかもしれません。
SPAM急増中...
March 31st, 2007このブログのコメント・トラックバックには日本語フィルタが追加されているのですが、今月からこのフィルタの回避方法に気が付いたと思われるSPAMMERから大量にSPAMがくる様になっています。ボットによる分散型なので効果的な対処情報はトークンを用いた方法くらいしかありません。自分で作っている時間がないのでとりあえず放置するしかないです。
コメント・トラックバックを頂いても気が付かない可能性が非常に高いです....
2度あることは3度ある?
March 30th, 2007Link: http://opentechpress.jp/security/07/03/30/0945215.shtml
カーソルファイルの脆弱性で.aniブラウズするだけで攻撃される可能性がある、ということですが似たような脆弱性があったと思いググるとありました。
http://itpro.nikkeibp.co.jp/free/ITPro/NEWS/20041224/154283/
実際、同じような脆弱性が何度か現れることは非常に多いです。
2、3年後にもう一度はある!?
MOPB-29-2007:PHP 5.2.1 unserialize() Information Leak Vulnerability
March 30th, 2007Link: http://www.php-security.org/MOPB/MOPB-29-2007.html
Stefanさんの承諾を得て日本語訳を公開しています。このブログの「the Month of PHP Bugs」カテゴリでMOPBの翻訳ページを一覧できます。分かりやすいように意訳できる部分は意訳します。厳密に原文の通り訳していないので正確性を重視される方は原文をご覧ください。
■クレジット
発見者:Stefan Esser
攻撃コード:Stefan Esser
■PoCまたは攻撃コード
MOPB-29-2007.php
http://www.php-security.org/MOPB/code/MOPB-29-2007.php
■リファレンス
なし
■サマリ
PHP 5.2.1から追加されたS: データ型シリアライズフォーマットは完全に壊れています。エスケープされた文字列を処理するための新機能ですが動作しないだけでなくヒープメモリ情報の漏えいを可能にしています。
■影響するバージョン
PHP 5.2.1
■詳細情報
新たにPHP 5.2.1からS: データタイプがunserialize()に追加されました。この機能は将来リリースされるPHP6とシリアライズされたデータの互換性を保つために追加されました。データ型自体は簡単なエスケープバイトがサポートされている以外は通常のs: データ型と同じです。以下の文字列がS:データ型の例です。
S:10:"\55\44APXY"
残念ながらこれらのエスケープされた文字列のアンシリアライズ処理は完全に壊れており、公表されているように全く働きません。
アンシリアライズ処理が行われた場合、6バイトの文字列を返すさず、上記の例は常に10バイトと返すかエラーとなります。アンシリアライズ処理が10バイトの入力を処理した時に終了せず、10バイトの出力が書かれた時に終了するからです。
次のバイトが"(ダブルクオート)文字である場合、最後の出力バイトから“(ダブルクオート)までのメモリ情報をリークします。
■PoC、攻撃コードまたは再現手順
添付の攻撃コードが実行されるとヒープメモリ情報をリークさせるようなデータをPHP変数に代入してリーク可能なメモリレイアウトを作り、16進数ダンプを出力します。成功した場合、メモリダンプはメモリクッキーとハッシュバケットをメモリヘッダ付きで出力します。このヒープのアドレス(または秘密であるべきクッキー情報)から別の攻撃を行うことが可能になります。
Heapdump
---------00000000: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa
00000010: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa
00000020: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa
00000030: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa
00000040: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa
00000050: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa
00000060: 61 61 61 61 22 00 00 00 00 63 da 58 21 fd 00 00 aaaa"....c.X!...
00000070: 00 45 01 00 00 26 bb b9 7e ca 00 00 00 b0 72 91 .E...&..~.....r.
00000080: b7 18 6f 91 b7 a0 73 91 b7 00 00 00 00 00 00 00 ..o...s.........
00000090: 00 00 00 00 00 22 22 22 22 22 22 22 22 22 22 22 ....."""""""""""
000000a0: 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 """"""""""""""""
000000b0: 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 """"""""""""""""
000000c0: 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 """"""""""""""""
000000d0: 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 """"""""""""""""
000000e0: 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 """"""""""""""""
000000f0: 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 """"""""""""""""
00000100: 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 """"""""""""""""
00000110: 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 """"""""""""""""
00000120: 22 22 22 22 22 22 22 22 22 22 22 22 .. .. .. .. """"""""""""....
■備考
我々にとっては全くテストされていないコードがPHPリリースに含まれてしまったことは謎です。S: データ型は全く動作せず、情報リーク攻撃だけにしか利用できません。最も簡単なテストでこれが壊れていることを発見できるはずです。
さらに、PHP開発者がシリアライズデータがPHP5とPHP6と互換性を持つような機能を追加したことも謎です。unserialize()にセキュリティ脆弱性が発見されるたびにユーザは開発者から「ユーザからのデータ対してunserialize()を使ってはならないものだ」にと言われます。(訳注:マニュアルには書いてないですが実際にそう言っている開発者もいます。unserialize()はユーザが送信したデータに対して利用しない方が安全なのは確かですが、壊れた実装が一番問題です)ユーザデータに使ってはならない関数であれば、なぜデータ交換を簡単にする為(つまりユーザからの入力データに対して)の機能を実装したのでしょうか?
MOPB-28-2007:PHP hash_update_file() Already Freed Resource Access Vulnerability
March 29th, 2007Link: http://www.php-security.org/MOPB/MOPB-28-2007.html
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のリソースシステムに使用数のカウンタをサポートするように作り直し、利用するようにしなければなりません。または、リソースの参照カウンタをこの目的に利用することも可能です。
この問題の修正には非常に多くの作業が必要であるため短期間での修正は難しいでしょう。
MOPB-27-2007:PHP ext/gd Already Freed Resource Access Vulnerability
March 28th, 2007Link: http://www.php-security.org/MOPB/MOPB-27-2007.html
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のリソースシステムに使用数のカウンタをサポートするように作り直し、利用するようにしなければなりません。または、リソースの参照カウンタをこの目的に利用することも可能です。
この問題の修正には非常に多くの作業が必要であるため短期間での修正は難しいでしょう。
MOPB-26-2007:PHP mb_parse_str() register_globals Activation Vulnerability
March 27th, 2007Link: http://www.php-security.org/MOPB/MOPB-26-2007.html
Stefanさんの承諾を得て日本語訳を公開しています。このブログの「the Month of PHP Bugs」カテゴリでMOPBの翻訳ページを一覧できます。分かりやすいように意訳できる部分は意訳します。厳密に原文の通り訳していないので正確性を重視される方は原文をご覧ください。
■クレジット
発見者:Stefan Esser
攻撃コード:Stefan Esser
■PoCまたは攻撃コード
MOPB-26-2007.php
http://www.php-security.org/MOPB/code/MOPB-26-2007.php
■リファレンス
HPHP-19-2005
■サマリ
parse_str関数のマルチバイト版のmb_parse_str関数が一つのパラメータのみで呼び出された場合、memory_limit制限などで割り込まれると内部的に有効化されたregister_globals設定が無効化されません。このため、このApacheプロセスはPHPコードからは検出不可能な状態でregister_globals設定が有効化されてしまいます。
この脆弱性は2005年にHardened-PHPプロジェクトが非マルチバイト版のparse_strに発見した脆弱性と類似しています。
■影響するバージョン
PHP 4.4.6以下、PHP 5.2.1以下
■詳細情報
mb_parse_str()関数が一つの引数で呼び出された場合、内部的にregister_globalsを有効化します。この有効化memory_limitによる割り込みを考慮せずに直接メモリのフラグを操作によって行われています。
if (info->force_register_globals) {
prev_rg_state = PG(register_globals);
PG(register_globals) = 1;
}
もしフラグのリセットが行われる前にスクリプトの実行が停止すると、フラグが元に戻されないので非常に危険です。これは添付の攻撃コードで示すようにメモリリミット違反などにより攻撃可能な状態が発生します。
この種のregister_globalsの有効化はPHPスクリプトからはregister_globalsが無効に見えてしまい、Apacheのチルドプロセスが終了するまでregister_globalsが有効化されてしまうので、php.ini設定によるregister_globalsの有効化より危険です。register_globals有効化に対するセーフガードはほとんど機能しません。
■PoC、攻撃コードまたは再現手順
添付の攻撃コードはメモリリミット制限近くまでメモリを割り当てます。その後、mb_parse_str()関数を呼び、内部的にregister_globalsが有効化されている間にmemory_limit制限違反を発生させます。
この脆弱性をテストするにはApacheサーバを少なくとも2つの仮想ホストを有効化し、サーバ全体でregister_globals設定を無効化して機動している必要があります。そして、以下の様なリクエストを送信します。
GET /rg.php?global_var=injected_global_var HTTP/1.1
Host: mopb-test
Connection: Keep-Alive
Keep-Alive: 100HTTP/1.1 200 OK
Date: Sun, 18 Mar 2007 13:33:10 GMT
Server: Apache
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-112
string(0) ""
NULL0
GET /MOPB-26-2007.php HTTP/1.1
Host: other-vhost
Connection: Keep-Alive
Keep-Alive: 100HTTP/1.1 200 OK
Date: Sun, 18 Mar 2007 13:33:10 GMT
Server: Apache
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1b4
Fatal error: Allowed memory size of 482344960 bytes exhausted (tried to allocate 164001 bytes) in /var/www/other-vhost/MOPB-26-2007.phpon line 290
GET /rg.php?global_var=injected_global_var HTTP/1.1
Host: mopb-test
Connection: CloseHTTP/1.1 200 OK
Date: Sun, 18 Mar 2007 13:33:14 GMT
Server: Apache
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-12e
string(0) ""
string(19) "injected_global_var"
この場合、rg.phpスクリプトはini_get("register_globals");とグローバル変数global_varの値のみを出力します。グローバル変数が最後のリクエストで、ini_get()関数ではregister_globalsは無効であるにも関わらず、グローバル変数が設定されていることは明らかです。
■備考
この種類の脆弱性の危険性は、多くの最近のスクリプトはregister_globalsの有効化されていると、警告を表示したり、処理を中止したり、register_globalsの処理が無かったように処理したりしていますが、これらの処理が役に立たなくなる点です。
この脆弱性を攻撃された場合、スクリプトはregister_globalsが有効化されていることに(醜いトリックを使わない限り)気付かず、register_globalsが無効化されているものとして実行してしまいます。
mod_php(訳注:PHPをWebサーバのモジュールとして)を利用している共有環境では悪意のあるユーザによってほかのVHOSTのregister_globalsが有効化されてしまいます。専用環境の場合、mb_parse_str()関数が1つの引数でのみ利用されている場合、register_globalsを有効化され更なる攻撃に利用されます。
MOPB-25-2007:PHP header() Space Trimming Buffer Underflow Vulnerability
March 27th, 2007Link: http://www.php-security.org/MOPB/MOPB-25-2007.html
Stefanさんの承諾を得て日本語訳を公開しています。このブログの「the Month of PHP Bugs」カテゴリでMOPBの翻訳ページを一覧できます。分かりやすいように意訳できる部分は意訳します。厳密に原文の通り訳していないので正確性を重視される方は原文をご覧ください。
■クレジット
発見者:Stefan Esser
攻撃コード:Stefan Esser
■PoCまたは攻撃コード
MOPB-25-2007.php
http://www.php-security.org/MOPB/code/MOPB-25-2007.php
■リファレンス
MOPB-19-2007
■サマリ
PHP 5.2.0以降のメモリマネージャーは1バイトのアンダーフロー脆弱性の場合も攻撃を許してしまいます。
header()関数に全て空白の文字列が渡された場合、少なくともPPC MacOS Xのようなビッグエンディアンシステムの場合、コード実行が可能となります。
■影響するバージョン
PHP 5.2.0
■詳細情報
PHP 5.2.0は簡単なmalloc()/free()のラッパー関数を含まない、リクエストメモリプールを実装する独自のヒープ管理を行う新しいメモリマネージャを利用しています。新しいヒープ管理機構は内部に制御情報を含み、これによりオーバーフロー攻撃に脆弱になりました。さらに、以前のメモリマネージャと異なり、1バイトのアンダーフローに脆弱になりました。
header()関数が呼ばれると、空白文字のトリムを行います。これは以下のコードで実行されます。
/* cut of trailing spaces, linefeeds and carriage-returns */
while(isspace(header_line[header_line_len-1]))
header_line[--header_line_len]='\0';
このコードは後ろの空白文字列をポインタを前に移動させ文字列の終端にNULLバイトを書き込みトリムを行います。残念ながら、すべて空白文字の場合、前へのポインタ移動が文字列の先端で終了しないため、このトリムは正しく動作しません。割り当てられたメモリアドレスの1バイト前の値がASCIIの空白文字である場合、このトリムコードは割り当てられたメモリアドレスの1バイト前にNULLバイトを書き込みます。
新しいメモリマネージャはバッファの先頭にメモリブロックのサイズを保存しています。リトルエンディアンのシステムでは、メモリブロックの1バイト前にASCIIの空白文字となる値が書き込まれるのは非現実的です。しかし、PPCのようなビッグエンディアンシステムの場合、リモートの攻撃者がバッファの直前の1バイトがASCIIの空白文字となるようなヒープレイアウトを作ることが可能です。トリムコードはそのバイトをNULLバイトで上書きする為、制御情報を破壊し、フリーメモリブロックのメモリリストのアンリンク時に行える標準的な攻撃が可能となり、POCで示すようにリモートからコード実行が可能となります。
$ gdb ./php
(gdb) run MOPB-25-2007.php
Starting program: /Users/Benutzer/php-5.2.0/sapi/cli/php MOPB-25-2007.php
Reading symbols for shared libraries . doneProgram received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x55555561
_zend_mm_free_int (heap=0x2000400, p=0xcba9e8) at /Users/Benutzer/php-5.2.0/Zend/zend_alloc.c:480
480 prev->next_free_block = next;
これはリンクリストのフリーリスト内部での典型的なクラッシュを示しています。有効なオフセットを使用することにより任意のコードを実行できます。デモ攻撃はローカルで動作するので、substr_compare()関数の情報漏えいぜい弱性を利用して有効なオフセットを自動的に決定します。これは以下のようになります。
$ gdb ./php
(gdb) run MOPB-25-2007.php
Starting program: /Users/Benutzer/php-5.2.0/sapi/cli/php MOPB-25-2007.php
Reading symbols for shared libraries . done
^C
Program received signal SIGINT, Interrupt.
0x00cd4544 in ?? ()
(gdb) x/20x $pc
0xcd4544: 0x44000002 0x7c000278 0x7c7e1b78 0x38a00002
0xcd4554: 0x3800005a 0x7fc3f378 0x7ca42b78 0x44000002
0xcd4564: 0x7c000278 0x38a5ffff 0x2c05ffff 0x4082ffe5
0xcd4574: 0x38000042 0x44000002 0x7c000278 0x7ca52a79
0xcd4584: 0x4082fffd 0x7c6802a6 0x38630028 0x9061fff8
(gdb) x/5i $pc
0xcd4594: stw r5,-4(r1)
0xcd4598: addi r4,r1,-8
0xcd459c: li r0,59
0xcd45a0: sync
0xcd45a4: sc
(gdb) bt
#0 0x00cd4544 in ?? ()
#1 0x00cd44fc in ?? ()
warning: Previous frame identical to this frame (corrupt stack?)
#2 0x0020ffd8 in _zval_dtor_func (zvalue=0xb) at /.../php-5.2.0/Zend/zend_variables.c:43
#3 0x00204144 in _zval_ptr_dtor (zval_ptr=0xcbb4bc) at /.../php-5.2.0/Zend/zend_variables.h:35
...
(gdb) continue
この例はコード実行攻撃が成功し、4444ポートに誰かが接続するのを待っていることを示しています。
■PoC、攻撃コードまたは再現手順
添付の攻撃コードはこのバッファアンダーフローが攻撃可能で、PPC MacOS Xプラットフォームでコード実行を許してしまうことをデモンストレーションしています。この攻撃は、攻撃に利用する関数が異なることをheader()関数が失敗するため出力が省略されている点を除けば、MOPB-19-2007と全く同じです。
この攻撃コードは有効なオフセットを決定するためにsubstr_compare()関数の情報漏えい脆弱性を利用しています。
攻撃が成功すると、攻撃コードは4444ポートに接続するとシェルを起動します。シェルコードはMetasploitシェルコードジェネレータから借用しています。
■備考
論理的には、この脆弱性はリモートから攻撃可能です。まだ多くのPHPアプリケーションはheaderインジェクションに脆弱です。しかし、リモートからのインジェクション攻撃が成功するためには文字列の最初からインジェクション可能でなければなりません。(\0によるトランケート動作)
(訳注:攻撃なコードはheader($_GET['location']) のようなコードでなければならない。原理的には”Location: http://example.com/some/where/ "といった文字列を$_GET['location']に設定すれば、正しいHTTPヘッダになりますが、この様なコードは別のセキュリティ問題含むため元々間違っています。注意: HTTP Response Splittingに脆弱でないheader()でheader('Location: '.$_GET['location'])としてもセキュリティ上問題です)
さらに、この攻撃コードは類似している脆弱性性に対して攻撃コード全体がほとんど変更なしに再利用であるか示しています。
MOPB-24-2007:PHP array_user_key_compare() Double DTOR Vulnerability
March 21st, 2007Link: http://www.php-security.org/MOPB/MOPB-24-2007.html
Stefanさんの承諾を得て日本語訳を公開しています。このブログの「the Month of PHP Bugs」カテゴリでMOPBの翻訳ページを一覧できます。分かりやすいように意訳できる部分は意訳します。厳密に原文の通り訳していないので正確性を重視される方は原文をご覧ください。
■クレジット
発見者:Stefan Esser
攻撃コード:Stefan Esser
■PoCまたは攻撃コード
MOPB-24-2007.php
http://www.php-security.org/MOPB/code/MOPB-24-2007.php
■リファレンス
なし
■サマリ
array_user_key_compare()は、例えばuksort()など、利用される内部関数(訳注:PHPコードから利用できる関数です)です。この関数はキーの値を比較するユーザが定義した配列比較関数として呼び出すことが目的です。この関数が復帰する際にパラメータがリファレンスで渡されていたとしても両方のパラメータは開放されてしまいます。このため既に開放済みのZVALがシンボルテーブルに残り、任意コード実行攻撃に利用可能な二重のDOTRが可能な状態になります。
■影響するバージョン
PHP 4.4.6以下、PHP 5.2.1以下
■詳細情報
例えばuksort()関数がユーザスペースでキーを比較するためにarray_user_key_compare()関数を内部的に呼び出されると、array_user_key_compare()関数はa,bの2つのハッシュバケットからkey1,key2のZVALを取得します。これらのZVALはユーザスペースの関数に渡され、zval_dtor()(訳注:PHP内部のZVALデストラクタ関数)によって開放されます。
static int array_user_key_compare(const void *a, const void *b TSRMLS_DC)
{
...
zval key1, key2;
zval *args[2];
...
args[0] = &key1;
args[1] = &key2;
...
status = call_user_function(EG(function_table), NULL, *BG(user_compare_func_name), &retval, 2, args TSRMLS_CC);zval_dtor(&key1);
zval_dtor(&key2);
...
}
このコードの問題点はユーザスペースの関数がリファレンスのキーを渡すかもしれない点を考慮していないことです。単純にzval_dtor()によって開放すると既に開放済みのメモリを参照してしまいます。これによりあらゆるメモリ破壊が発生し添付の攻撃コードで示すように任意コード実行攻撃にも利用できます。
この問題を解決する正しい方法はzval_dtor()を変数の解放前にリファレンスを考慮するzval_ptr_dtor()に置き換えることです。
■PoC、攻撃コードまたは再現手順
添付の攻撃コードはMOPBの最初に紹介したバグをトリックに利用しています。文字列をハッシュテーブルの同じ場所に配置し、ハッシュテーブルの初めに配置されたエントリのアドレスを読み出し、シェルコードへのオフセットを割り出し、同じ文字列を使ってハッシュテーブルのデストラクタフィールドを上書きします。ハッシュテーブルが開放される際にコードが実行されます。
■備考
この脆弱性はローカルからのみ攻撃可能です。しかし、攻撃コードはPHP4とPHP5でいかに簡単に任意のマシン語実行できるか示し、PHPに組み込まれたdisable_functions, open_basedir, safe_modeが完全に無意味であることを明らかにしています。
MOPB-23-2007:PHP 5 Rejected Session Identifier Double Free Vulnerability
March 21st, 2007Link: http://www.php-security.org/MOPB/MOPB-23-2007.html
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バージョンから導入され、直接関係していません。さらに、この脆弱性は、前の脆弱性と異なり、リモートからの攻撃が容易な物になっています。従ってリモートからの攻撃が可能である可能性は高くなっています。この仮定が正しいか将来調査するかもしれません。


