zz log

zaininnari Blog

htmlspecialchars()/htmlentities()の使用にはPHP 5.2.12以降/PHP 5.3.2以降を使う

携帯の絵文字について調べている際に、見つけたエントリーのまとめです。

htmlspecialchars()/htmlentities()を使用する際には、
PHP 5.2.12以降、PHP 5.3.2以降を使うこと。
以前のバージョンでは、
htmlspecialchars(ENT_QUOTES)を使用しても、XSSの可能性があります。

条件はかなり特殊(PHP側がShift_JISオンリー&特定のブラウザ)です。
(携帯はどうなのだろう。docomo買うしかないのかぁ。auとsoftbankの2個でもきついのに(非Wi-Fi搭載機種)。すべてがWi-Fi対応なら、パケット代が楽になるのに!)

問題点その1:PHP側で先行バイトの一部(0xF0〜0xFC)のチェックがすり抜ける

徳丸浩の日記 - [php][xss] - htmlspecialcharsのShift_JISチェック漏れによるXSS回避策より引用:


問題が発生する条件


幸いなことに、この問題が発生するためには、色々条件がつきます。それを以下に示します。すべてAND条件です。



  1. PHPが内部で扱う文字エンコーディングがShift_JISである

  2. 入力から出力までの過程で文字エンコーディングが変換されない

  3. 入力値のバリデーションとして文字エンコーディングを検査していない


すなわち、1.と2.を合わせますと、入口・処理・出口まで一貫してShift_JISで扱っている、という条件が攻撃には必須ということになります。


問題点その2:一部ブラウザ側で先行バイトが続く1バイトで1文字と認識される

Shift_JIS では、htmlspecialchars() を使用しても XSS が可能な場合がある - t_komuraの日記より引用:


上記のコードで XSS が発生するのは、以下が原因となるようです。



  1. PHP の htmlspecialchars() では、SJIS(Shift_JIS) の場合、\xf0 - \xfc を単独で指定しても排除しない(PHP 5.3.0 で確認)

  2. 一部のブラウザでは、\xf0 - \xfc に続く1バイトを合わせて Shift_JIS の1文字として認識する(Mozilla Firefox 3.5.3 と Internet Explorer 8(8.0.6001.18813) で確認)

  3. このため、上記の例では、\xf0 の後ろにある "(ダブルクォート) が有効にならず、その後ろに任意の属性が追加できる


このため、ブラウザによっては、XSS が可能な場合があります。


対策