2009-10-04
■[PHP][セキュリティ] Shift_JIS では、htmlspecialchars() を使用しても XSS が可能な場合がある

以下のページに関連して、htmlspecialchars() を使用している場合でも XSS が可能かどうか少し調べてみました。
その結果、いくつかのブラウザで文字エンコーディングに Shift_JIS を使用していた場合、XSS が可能なことを確認しました。
テストコードは以下の通りです。リンクにマウスポインタを乗せると埋め込んだ Javascript が実行されます。
<?php $_GET['a1'] = "\xf0"; // \xf0 - \xfc で可能 $_GET['a2'] = " href=dummy onmouseover=alert(document.title) dummy=dummy"; header( "Content-Type:text/html; charset=Shift_JIS" ); ?> <html> <head><title>Shift_JIS test</title></head> <body> <p><a title="<?php echo htmlspecialchars( $_GET['a1'], ENT_QUOTES, 'SJIS' ) ?>" href="<?php echo htmlspecialchars( $_GET['a2'], ENT_QUOTES, 'SJIS' ) ?>">test</a></p> </body> </html>
上記のコードで XSS が発生するのは、以下が原因となるようです。
- PHP の htmlspecialchars() では、SJIS(Shift_JIS) の場合、\xf0 - \xfc を単独で指定しても排除しない(PHP 5.3.0 で確認)
- 一部のブラウザでは、\xf0 - \xfc に続く1バイトを合わせて Shift_JIS の1文字として認識する(Mozilla Firefox 3.5.3 と Internet Explorer 8(8.0.6001.18813) で確認)
- このため、上記の例では、\xf0 の後ろにある "(ダブルクォート) が有効にならず、その後ろに任意の属性が追加できる
このため、ブラウザによっては、XSS が可能な場合があります。
他のブラウザとして、Google Chrome 3.0.195.24 で確認してみましたが、\xf0 - \xfc の後ろに不正な文字が続く場合では、XSS は発生しませんでした。
追記(2009.10.06)
コメントで指摘いただいたように、Shift_JIS の先行バイトに関連する記述が正しくなかったため、表現を修正しました。
コメントを書く
とおりすがり
2009/10/05 10:41
Shift_JIS-2004ではf0-fcも先行バイトです
t_komura
2009/10/06 00:34
確かにその通りですね。少し表現を修正しました。
トラックバック - http://d.hatena.ne.jp/t_komura/20091004/1254665511
リンク元
- 212 http://reader.livedoor.com/reader/
- 185 http://b.hatena.ne.jp/hotentry
- 140 http://phpspot.org/blog/archives/2009/10/2009105.html
- 97 http://bugs.php.net/bug.php?id=49785
- 91 http://b.hatena.ne.jp/hotentry/it
- 84 http://d.hatena.ne.jp/
- 81 http://d.hatena.ne.jp/IwamotoTakashi/20091005/p1
- 70 http://www.google.co.jp/reader/view/
- 47 http://twitter.com/
- 45 http://www.google.com/reader/view/