#SECCON 2014 Online Quals (English) - Writeup (jspuzzle)
チーム 0x0 として参加しました。
Web要員として Web100, Web200, Web500 を解きましたので jspuzzle (Web100) の Writeup をば。
(Web300 はメンバーに投げて、Web400 は僕が寝落ちしてる間にメンバーが解いてくれました。Web400、難しい問題だったらしく、頭が上がりません。)
一応最速正解だったようで、Bonus Point (1pt) 貰いました。今回はこのポイントで順位が変動することはありませんでしたが…。
Web500 の Writeup: #SECCON 2014 Online Quals (English) - Writeup (XSS Bonsai) - 雑記
Web200 の Writeup: どうしよう
結論
てめぇの長ったらしい説明なんていらないから答えを見せろ用
解説
こんなアプリが入った zip が配布されます。
歴史のテストのような語句の選択当てはめ問題ですね。alert(1)
を出力できればいいようです。
とりあえず目を付けるところとしては、
this[ r[ "hoge" ]( pattern ) ][ "fuga" ]( 1 );
でしょうか。ここで alert(1)
を呼んでいるのは明らかなので、
this[ r[ "hoge" ]( pattern ) ][ "fuga" ]
こいつは alert()
なはずです。ということで、fuga
には alert
が当てはまることが分かります。
また同様に this[ r[ "hoge" ]( pattern ) ]
は alert()
があるオブジェクト、つまり window
が入ることが分かります。
ということで this
の中に何かを代入している箇所を探すと、
this[ "unko" ] = (new Function( "piyo" + "chun" + "nya~" ))();
があります。つまり、
"unko" == r[ "hoge" ]( pattern )
と
(new Function("piyo" + "chun" + "nya~"))() == window
を満たすように語句を当てはめればよいことが分かります。
まず Function
の中身ですが、これは
return window;
のようなコードになればよいはずです。
return
は候補にあります。window
は候補にありませんが、この Function
の実行時には this
は window
になるので this
を使います。
return
と window
の間のスペースは /*^_^*/
で代用します。ということで Function
完成です。
new Function( "return" + "/*^_^*/" + "this" )
次は unko
です。
"unko" == r[ "hoge" ]( pattern )
を満たすように語句を当てはめます。
var pattern = "wan"; var r = new RegExp( pattern ); this[ r[ "hoge" ]( pattern ) ] ...
上のコードからわかるように、hoge
は正規表現関連のメソッドの名前です。
ということで exec
が当てはまります。整理すると
"unko" == /wan/.exec( "wan" )
です。wan
の候補はたくさんありますが、とりあえず正規表現のパターンっぽい ^[w]$
を選びます。
すると /^[w]$/.exec( "^[w]$" )
は null
なので、unko
は null
であることが分かります。
ここまで来たら後は少しです。
({"weiwei" :function(){ // ここはできた }})[ "uhyoooo"[ "kokekokko~" ]() ]();
なので、"weiwei" == "uhyoooo"[ "kokekokko~" ]()
となるように当てはめればOKです。
残った選択肢を見れば閃くと思いますが、weiwei
は function
、uhyoooo
は Function
、kokekokko~
は toLowerCase
です。
"use strict"; ({"function" :function(){ this[ "null" ] = (new Function( "return" + "/*^_^*/" + "this" ))(); var pattern = "^[w]$"; var r = new RegExp( pattern ); this[ r[ "exec" ]( pattern ) ][ "alert" ]( 1 ); }})[ "Function"[ "toLowerCase" ]() ]();
お疲れ様でした。
補足
"null" != null
ですが、
var obj = { null: 1 }; console.log( obj[ "null" ] == obj[ null ] ); // true
ということを言いたかっただけなのでご勘弁ください。