SECCON CTF 2014 Online 予選 Write Up #4

#3に引き続き、解いたのがWeb 100の”jspuzzle”です。

jspuzzle解凍してみると、HTMLとJavascriptが入っているので開いてみます。

jspuzzle_blankどうやら、空欄を下の選択肢から埋めて、alert(1)を実行するコードを作ればいいようです。まさにパズルですね。同じ選択肢は1度しか使えません。

Scriptを読んだところ、10箇所の空欄を結合したSHA1ハッシュ値がFlagになってたので、正攻法以外では解けなさそう。なので、ちゃんとパズルとして考えていきます。

説明上、次の図のように番号を振ります。

jspuzzle_num

最初5行で辞書をつくって、関数オブジェクトをつっこみ、それを最後の行で参照して、実行していることがわかります。7,8の行が実際にalert(1)を実行する箇所ということになります。

まず、“[1]”と、“{9}”[“{10}”]() が同値でないとだめであることから考えます。JavaScriptでは、オブジェクトと辞書は一緒なので、Hoge.fuga()と書いてもHoge[“fuga”]()と書いてもおなじなので、きっと{10}は文字列オブジェクトのメソッドであることがわかります。

ということは、選択肢からtoLowerCaseが{10}で、Functionが{9}、対応してfunctionが{1}であることがわかりました。

同じ原理で、“{2}”と、r[“{7}”](pattern)が同値でなければいけません。rはRegExpオブジェクトなので、{7}は選択肢から考えると”constructor”か”exec”が入ります。constructorの戻り値はまたRegExpオブジェクトなので、違うだろうと推測し、{7}にexecを入れるとr.exec(pattern)となります。では次に{6}を考えてみると、正規表現の文法上/*^_^*/は入りません、それ以外の普通の文字列はいれてしまうと、execの返り値がリストになってしまいます。なので、{6}には^[w]$をいれます。そうするとexecの返り値はnullになります。

ここで疑問がでてきます、{2}は文字列なのに、nullはどうがんばっても入れられないじゃないか!と。ところがJavaScriptは辞書のキーは全部文字列で扱いますので、参照時に自動でキャストされるため”null”で問題ありません。(最初、これはちがうなぁと思っていたので少し時間がかかりました…)。なので、{2}はnullで決まりです。

最後、{3}{4}{5}と{8}ですが、”{3}{4}{5}”と結合すると、命令になるはずなので、で”return hogehoge”となるはずです。しかし、空白は選択肢にありませんが、なんとコメントをいれるとそこは空白扱いになるのです。したがって、{3}はreturn、{4}は/*^_^*/ですね。

ここまで考えると、この新しく生成されている関数で返るオブジェクトをHogeとすると、{8}の 部分ではこういうことになります。

Hoge.{8}(1);

これがalert(1)にならなければいけません。そこで、alertを持っている親オブジェクトを考えると、window….つまりはthisです!ということはreturn thisして、alertを呼びだせばOK

結果、{5}はthis、{8}はalertですね。

jspuzzle_ans

 

殴り書きなので、読みづらいのはスルーしてください…

 

 

コメントを残す

メールアドレスが公開されることはありません。

question razz sad evil exclaim smile redface biggrin surprised eek confused cool lol mad twisted rolleyes wink idea arrow neutral cry mrgreen

*