2013年3月30日土曜日

CVE-2008-5814を巡る冒険

脆弱性情報を見ていると、たまに(しばしば)詳細の不明なものがあります。
先日脆弱性情報を調べていたら、JVN#50327700(CVE-2008-5814)PHP におけるクロスサイトスクリプティングの脆弱性が目にとまりました。CVSS値が2.6なので危険な脆弱性ではなさそうですが、詳細が分からないと気持ちが悪いですね。このエントリでは、CVE-2008-5814について調べた結果を報告します。

JVN iPediaの説明には以下のように書かれています。
概要
PHP には、クロスサイトスクリプティングの脆弱性が存在します。
影響を受けるシステム
PHP 5.2.7 およびそれ以前
PHP の設定で display_errors=off である場合は、この問題の影響を受けません。
謝辞
この脆弱性情報は、情報セキュリティ早期警戒パートナーシップに基づき下記の方が IPA に報告し、JPCERT/CC が開発者との調整を行いました。
報告者:インターナショナル・ネットワーク・セキュリティ(株) 佐名木 智貴 氏
佐名木さんの報告なのですね。
display_errors=offの場合は影響を受けないというのが救いです。本番環境でdisplay_errorsが有効というのは「あり得ない」状態なので、対処としては、まずdisplay_errorsを確実にoffにした上で、対策済みのバージョンのPHPを導入することです。PHP5.3以降は問題ないということなので、現在メンテナンスされているバージョンのPHPでは問題ありません。

この脆弱性、発表当時(2008年12月19日)から謎という点が話題になったようで、例えば以下のような記事があります。
■ JVN#50327700 PHP におけるクロスサイトスクリプティングの脆弱性がよくわからない件について
PHP の設定で display_errors=off である場合は、この問題の影響を受けません。
の時点でまぁ自分の手元にはほぼ影響ないんですが、該当の記事からのリンク先であるPHPのChangeLogにはそれっぽいのがかいてなくて非常に気持ち悪い思いをしてるわけです。
こまってWassrでつぶやいてみたらますがたさんよりこれじゃないかみたいなレスをもらったけど、Cookieまわりっぽいので、CookieってXSSないとそもそもかきかえられないよなぁ(いや、レンタルサーバとかだといろいろあるけえど)とか悩んでるわけです。で、もし詳細ご存知の人いたら教えてください。
http://d.hatena.ne.jp/cocoiti/20081223より引用
CVEではどうなっているでしょうか。MITREもNVDも同じで、以下のようにあります。
Cross-site scripting (XSS) vulnerability in PHP, possibly 5.2.7 and earlier, when display_errors is enabled, allows remote attackers to inject arbitrary web script or HTML via unspecified vectors. NOTE: because of the lack of details, it is unclear whether this is related to CVE-2006-0208.
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5814
攻撃経路不明だし、いろいろ情報不足でよくわかんねーよ、という感じですね。
そこで、MITREやNVDからリンクされているサイトをたどったり、ググったりして以下のサイトを見つけました。

http://anonscm.debian.org/gitweb/?p=pkg-php/php.git;a=commitdiff;h=a71a80d0465f4e82210559c51217f03057c7e028より引用

これだと分かりますね。PHPのソースに戻って確認すると、上記の改修はPHP5.2.6からPHP5.2.7への変更として実施されています。すなわち、影響を受けるシステムにPHP5.2.7以前となっているのは誤りで、PHP5.2.6以前が正しいようです。
具体的には、Cookieの名前あるいは値にCookieとして使えない文字(空白、カンマ、セミコロン、水平タブ、垂直タブ、フォームフィード、改行、復帰)があった場合に、PHP-5.2.6以前だと、その文字列を「そのまま」エラーとして表示しているのです(下記)。

  • Cookieの名前の場合は、setcookieまたはsetrawcookieを使っている場合
  • Cookieの値の場合は、setrawcookieを使っている場合

このため、以下のコードを実行すると 2, 3, 4 がalertとして表示されます。1の場合は、値がパーセントエンコーディングされるため禁止文字は出現せずエラーになりません。
<?php
  setcookie('a', '<script>alert(1);</script>');
  setrawcookie('a', '<script>alert(2);</script>');
  setcookie('<script>alert(3);</script>', 'a');
  setrawcookie('<script>alert(4);</script>', 'a');
この脆弱性を悪用するためには、Cookieの名前か値を外部からコントロールする必要がありますが、通常のアプリケーションではCookieの名前をコントロールすることはできないので、setrawcookieを使って、外部からの入力をCookieに出力している場合が問題になると考えられます。
脆弱なコードの例を以下に示します。display_errors=Onが前提です。
<?php
  setrawcookie('a', $_GET['x']);
以下のように呼び出します。
http://example.jp/x.php?x=<script>alert(1);</script>

実行例は以下の通りです。IEやGoogle ChromeだとXSSフィルタによりJavaScriptは実行されないので、Firefoxにて試しています。


さて、ようやくCVE-2008-5814による攻撃を試すことができました。脆弱性の影響を受ける条件は以下となります。
  • PHP5.2.6以下を使っている
  • display_errorsが有効
  • 以下のいずれか
    • setrawcookieにより外部からコントロールできる文字例をCookieの値として出力している
    • setcookieかsetrawcookieにより外部からコントロールできる文字例をCookieの名前として出力している
対処は下記となります。全部実施を推奨します。
  • PHPの最新の安定版を使う(必須)
  • display_errorsを無効にする(必須)
  • Cookieの出力にはsetcookie関数を使う
  • Cookieの名前は外部から指定できなくする
さて、display_errorが仮に有効になっている場合、最新のPHPを使っていてもクロスサイト・スクリプティング(XSS)になるケースはあります。これについては別途紹介します。

0 件のコメント:

コメントを投稿

フォロワー