MOPB-18-2007:PHP ext/filter HTML Tag Stripping Bypass Vulnerability

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

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

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

■PoCまたは攻撃コード
必要なし

■リファレンス
なし

■サマリ
PHP 5.2.0から新しくFilter拡張モジュールが追加されました。このモジュールはアプリケーションからユーザ入力をフィルタしたり、サイト全体に対する入力フィルタ機能を実装するために利用されます。

FILTER_SANITIZE_STRINGフィルタがFILTER_SLAG_STRIP_LOWと一緒に利用されると、値の小さいASCIIの空白文字をHTMLタグを開く文字(<)の後ろに置くとHTMLタグフィルタをバイパスできます。

■影響するバージョン
PHP 5.2.0

■詳細情報
FilterモジュールのFILTER_SANITIZE_STRINGフィルタは一つの単純なルールを守っていません。複数の異なるエンティティを文字列から除去する場合、文字列を除去する操作は次の操作に影響を与えないか、文字列の除去操作ができなくなるまで繰り返し行わなければなりません。

Filterモジュールは、”< “( “<“と” ”)を除き、HTMLタグを最初に除去します。これは除去しなくても安全と考えられます。

タグ除去の後にASCII文字の除去が行われます。幾つかのASCII空白文字は32よりも小さい値を持ち、FILTER_FLAG_STRIP_LOWフィルタが適用されるとこれらの文字も除去され、不正なタグの混入を許してしまいます。この動作はHTMLタグ除去を完全にバイパスさせてしまいます。

■PoC、攻撃コードまたは再現手順
この問題を再現するには、次のサンプルコードを保存し、「var=<%0script>alert(/XSS/);<%0/script>」などで呼び出します。

<?php
  $var = filter_input(INPUT_GET, "var", FILTER_SANITIZE_STRING,
                      array("flags" => FILTER_FLAG_STRIP_LOW));
  echo $var;
?>

脆弱性を持つFilterモジュールを利用している場合、XSS脆弱性を確認できます。

■備考
このバグはFilterモジュール導入の動機(考え)に潜む弱さを表しています。Filterモジュールの実装にバグがあるたびに、モジュールを利用する全てのアプリケーションはPHPをバージョンアップしなければ脆弱性を回避できません。(Filterモジュールはデフォルトでは静的にコンパイルされる為です)しかし、新しいPHPバージョンはそれほど頻繁にリリースされません。この為、アプリケーションは何か月にもわたってこれらの問題にさらされる可能性があります。

私たちの考えでは、入力フィルタ(入力の検証と出力のエスケープ)はPHPの再コンパイルの必要がないく、ユーザが容易に修正なユーザレベルのライブラリに属する物だと考えています。2007年後半にHardened-PHPプロジェクトでこのようなライブラリの開発を行う事を計画しています。

投稿者: yohgaki