文字コードとHTMLエンコードとCross-Site Scriptingの微妙な関係

もっといっぱい動くっぽかった。まとまったら後で書くですよ。っていうか、対策としてそういう条件を強いるのはなんだかなぁな位幅が広いかも?*1

ダメだった……。残念。次はEUC調べよっと。

EUCの場合

脆弱なコード例(もちろん文字コードEUCで)

<form>
text: <input type='text' name='text' value="<?= htmlspecialchars($_GET{'text'}) ?>"><br>
text2: <input type='text' name='text2' value="<?= htmlspecialchars($_GET{'text2'}) ?>"><br>
<input type=submit value="送信">
</form>

攻撃例*2

http://localhost/break_quote_euc.php?text=text%A1&text2=%20style%3dbackground:url(javascript:alert('xss'))%20%A1

UTF8の場合

脆弱なコード例(はEUCと同じで。)

攻撃例*3

http://localhost/break_quote_utf8.php?text=text%E1&text2=%20style%3dbackground:url(javascript:alert('xss'))%20%E1

UTF8はよくわかんないので、もっと動くパターンあるかもですにぇ。

対策

基本的には、一度UTF8に変換して戻すってすると大丈夫らしい。

  • PerlでEncode.pmを使う場合は、encode('sjis', decode('sjis', $query->param('text')))ってすると半端モノ消える(教えてもらった)
  • PerlでJcode.pmを使う場合は、Jcode::convert(Jcode::convert($test, "utf8", "sjis" ), "sjis", "utf8" )ってすると半端モノが「?」になる
  • phpの場合はhtmlspecialchars(mb_convert_encoding($_GET{'text'},'SJIS','SJIS'))ってすると半端モノ消える(教えてもらった)
  • Javaでは、出力文字セットを指定しておけば(普通の日本語サイトでは指定しないとまともに動かない)、一度UTF8に変換して戻してくれるらしいので大丈夫っぽい

その他は

  • URLエンコードしとけ?
  • 属性値は全部同じもの「"」か「'」括っておけ?(表示は崩れる)


とかそこらへん?

*1:間違ってたらこの文章は消えますw

*2:%A1の箇所には%A1〜%AF、%B1〜………と色々いけます。

*3:%E1の箇所にはたぶん%E1〜%EFまでいけます。もっといけるのかな?