括弧なしのXSS

T.Teradaさんによる実例を拝見して

2009-07-18のT.Teradaさんの日記の『括弧なしのXSS』という題名の記事を興味深く読ませて頂きました。実際に実例があったのですねぇ。ため息。
括弧なしのXSSという題材については、その後、Our Favorite XSS Filters/IDS and how to Attack Them を読んでみたところ、setterを使用しない解があることを知りました。 setterの古い記述を使っていた、Firefox専用のexploitではなく、より汎用的なベクタがあるのですね、まったく気がつきませんでした。手元で試しましたが、複数のブラウザで有効のようでした。ベクタの表記は極めて簡単でして、普通に暗記できます。以下。

location = name
罠のページに誘導しておいて、そのページにおいてname属性つきのiframe要素などで脆弱なサイトのページを呼び出します。name属性の値に、たとえば、『alert(document.domain)』などと設定しておけば良いという簡明さです。T.Teradaさんが見つけたような事例が今後もしも発見できたならば、より容易に脆弱性レポートを書き出すことができることでしょう。
さて、括弧なしのXSSについては、上記であげた参考文献のPDFに、もっとすごいのが出ていまして、なんと、括弧も等号も使わない例が出ていました。なんといいいますか、すごいですねぇ。そんなことがありうるなんて、信じられず、本当に度肝を抜かれました。発火の仕組みが想像もできませんでした。もう少し調べてみたい気もいたします。そこで。

括弧も等号も使わないなんて?(未検証)


IE8 Blocks JS by disabling:
  • =
  • (
  • )

• BUT It is possible to execute code without () and =
• {valueOf:location,toString:[].join,0:name,length:1}
<snip>
• Some JSON parsers passing a “sanitized” string to eval()
may also be vulnerable to this same bypass.
Bypassing the JavaScript based Filter
うーん。うーん。うーん。「Some JSON parsers」が脆弱と。本家のは大丈夫?

追記::Thornmaker's IE8 Filter Bypass

どうやら、元ネタは、Thornmaker氏(=David Lindsay)のブログ、"p42 labs"にアップされた記事、IE8 Filter Bypass::p42 labsであるらしいですね。
ええと、いろいろいじくったのですけれど、以下・・・


location = {toString:[].join,0:name,length:1}
が、ほとんど全てのブラウザにおいて、window.nameをペイロードとした以下の、

location = name
と等価であるとわかりました。わからないのは、valueOf:location の部分でして、これがあると、等号を使わずにlocation=nameを実現できる上、IE8のXSS Filterをバイパス可能らしい。。。。でも私には再現不可能なんでして、、ハテ?

''+{valueOf:location,toString:[].join,0:name,length:1}
たとえ、暗黙のうちに行われる型変換の最中にlocationで上書きされたvalueOfメソッドが使われたとしても、どういうわけでlocation=nameになるのでしょう?locationってメソッドじゃぁないじゃんか?みたいな気分。

さらに追記::2009/08/20

いやぁ、完全に勘違いでした。等号も括弧も使わないという上のPoCの本筋は、


location=name
ではなかったのでした。愕然。最近の私の頭の中の流れで、location=nameが先入観念になっていたのですねぇ、大間違いです。
まず、押さえておくべき点なのですけれど、以下は全く駄目ですね、当然。

location(name) // no good
Firefoxでなら、"location is not a function" とでもしかられるところでしょうし、IEでなら、"このオブジェクトではサポートされていない操作です"とかのエラーメッセージを貰っても不思議ではありません。locationは関数ではないからですよね、あるいは、windowという名前のグローバルオブジェクトのメソッドでもない…はず。…でも…でも!以下はIEで成立してしまいます。

""+{valueOf:location(name)} // good
window.nameに格納されているURIがlocation.replace()に喰われているものと推察されます。コレは尋常でないように感じます。""+{なんかのオブジェクト}で、なんかのオブジェクトのvalueOfメソッドがJavaScriptインタプリタのおかげで内部的に実行されるのだけれども、その実行以前にvalueOfメソッドが『不自然にも』location(name)で上書きされているという感じなのでしょうかねぇ。いや、上書きされたものに制御がうつるのは良いとして、location(name)が実行可能ってどういうことなんでしょ?IEの機能なんでしょうかねぇ。じゃぁどうして、<script>location(name)</script>はIEで作動しないんでしょ? うーん、私の能力ではわかりそうにありません。いつも通りの教えて君状態であります。
もうひとつ壁がありましてね、

""+{valueOf:location, ...以下略
上のthornmaker氏のオリジナルのコードでは、locationメソッドにキックしているのですけれど、そのメソッドにどうやってnameを与えているのかが全く見当もつかない点ですね、この点こそが実は、括弧がいらない本当の理由なんでしょうけれども。
以上をまとめると、雰囲気的には、括弧も等号も回避しているのではなくて、もともと等号がいらないコードに対して変形をして括弧が不要になりました、ということなんでしょうねぇ。元がlocation=nameという等号が必要なものじゃなくて、元のlocation(name)から括弧を取り去った…というところ。
以上を振り返ってみると、なんとなくですが、バリエーションを作れなくてはおかしいはずなんです、なにもlocationメソッド【謎】をつかわなくたっていいじゃないか!なにか他にもコード実行可能なメソッドがあってそれに括弧なしでストリング相当を与えればいいじゃないか!ということなんですよねぇ。私には到底できない作業ですけれども。
ということで、この方面でのこれ以上の私のお勉強は一時停滞です。