htmlspecialcharsは脆弱

Security 10月 19, 2006
(Last Updated On: 2018年3月4日)

追記:現在のPHPでは問題ありません。パフォーマンスを考えるとhtmlspecialchars()の利用をお勧めします。新しいエントリを参照してください。

PHPのHTMLエスケープ

PHPにはHTMLの文字列として出力する関数が2種類あります。

  • htmlspecialchars() <,>,&,’,”等のHTML特殊文字をエンティティ化する
  • htmlentities() HTMLエンティティ化が必要な文字全てをエンティティ化する

あまり脆弱性に関係なさそうですが文字エンコーディングとの組み合わせで攻撃に利用される可能性があります。このようなシナリオです。BBSやブログのコメントなどユーザが送信したデータをHTMLページの一部として表示するアプリケーションがあるとします。

  • ワザとアプリケーションが期待している文字エンコーディングと異なる文字エンコーディングでデータを送信し、その中にJavaScriptを実行可能なデータを入れる
  • データが保存されページが表示された際には異なる文字エンコーディングのデータが表示され文字化けする。

通常、文字化けしたページが表示されるにとどまる場合が多いと思われますが以下の状況が考えられます。

  • 文字エンコーディングが指定されていない場合、ブラウザが文字エンコーディングを自動判別し本来の文字エンコーディングとは異なる文字エンコーディングが利用されていると判断しJavaScriptが実行される。
  • ユーザが文字化けしたコンテンツを参照するために「明示的」に文字エンコーディングを変更し、その際にJavaScriptが実行される

htmlspecialcharではISO-2022-JPのマルチバイトスタート文字列などはエンティティ変換されないため意図した文字エンコーディング以外でページが表示された場合、JavaScriptが実行される可能性があります。htmlentitiesで変換していれば指定された文字エンコーディング以外のデータはエンティティ変換されます。このため意図した文字エンコーディング以外の文字エンコーディングでページが表示されてもJavaScriptが実行されることはありません。

本来、すべてのアプリケーションはユーザからの入力等が正しい文字エンコーディングがあるかチェックし不正なエンコーディングが含まれている場合はエラーとして処理を停止すべきです。このように正しく入力をチェックしている場合はhtmlspcialcharsを利用していても問題が発生する事はありませんが、このチェックが無い場合はhtmlentitiesを使用していないとJavaScriptインジェクション(XSS)に対して脆弱になります。

UTF-7エンコードされたタグ文字列によるXSS脆弱性に注意
http://slashdot.jp/security/article.pl?sid=05/12/21/2318216

これはUTF-7を使用した例です。scriptタグを隠すSJIS、EUC-JP、ISO-2022-JP等を利用した攻撃例も知られています。

投稿者: yohgaki