読者です 読者をやめる 読者になる 読者になる

#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: どうしよう

結論

てめぇの長ったらしい説明なんていらないから答えを見せろ用

f:id:nash716:20141207175318p:plain

解説

こんなアプリが入った zip が配布されます。

f:id:nash716:20141207175353p:plain

歴史のテストのような語句の選択当てはめ問題ですね。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 の実行時には thiswindow になるので this を使います。
returnwindow の間のスペースは /*^_^*/ で代用します。ということで 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 なので、unkonull であることが分かります。


ここまで来たら後は少しです。

({"weiwei" :function(){
    // ここはできた
}})[ "uhyoooo"[ "kokekokko~" ]() ]();

なので、"weiwei" == "uhyoooo"[ "kokekokko~" ]() となるように当てはめればOKです。
残った選択肢を見れば閃くと思いますが、weiweifunctionuhyooooFunctionkokekokko~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" ]() ]();

お疲れ様でした。

f:id:nash716:20141207175318p:plain

補足

"null" != null ですが、

var obj = { null: 1 };
console.log( obj[ "null" ] == obj[ null ] ); // true

ということを言いたかっただけなのでご勘弁ください。