javascript://のXSS

こんな場合、普通はjavascriptやdataスキームなどを使ってXSSさせるのでしょう。

<a href="ここにHTMLエンコードされて入る">link</a>

しかし、このアプリは「javascript://...」のように、先頭からアルファベット数文字が続き、その直後に「://」が付いている値以外は、エラーではじいてしまいます。

この「:」のあとの「//」が曲者です。

dataスキーマを試してみましたが、「//」があるとどうやらダメらしいということで、javascriptスキームで頑張ってみます。

まずはこんな感じです。

<a href="javascript://hoge[0x0A]alert(111)">link</a>

「//」が行コメントの開始になるため、[0x0A](LF)や[0x0D][0x0A](CRLF)を入れてみて、その後に動かしたいJavaScriptコードを入れています。

ですがこれでは動きません。Firefox2やIE6は、hrefなどのURI属性値に含まれる改行文字を無視するからです*1

試行錯誤の結果、以下のようにすれば動くことが判りました。

<a href="javascript://hoge[0xE2][0x80][0xA8]alert(111)">link</a>

上記のコードは、HTMLがUTF-8で、かつFirefox環境であることを前提としています。

仕組みとしては、JavaScriptコード内のU+2028(あるいはU+2029)を、Firefoxが改行文字と認識することを利用しています*2UNICODE系でない文字コードでも、&#x2028;のように文字参照にすると動くはずですが、「&」が「&amp;」にエスケープされる場合は厳しそうです。

*1:RFC2396に「The whitespace should be ignored when extracting the URI」と書いてあるからだと思いますが、正確な理由はよく知りません。

*2:Standard ECMA-262 3rd Editionの12ページに改行文字について書いてあります。