第2回tkbctf 問題「The Net」「Police」を作ってみた
EDIT
コード全体を公開しました。ご参考までに。 https://github.com/chris-x86-64/tkbctf2-Police
くりすです。
第2回tkbctfにて、問題「The Net」と、「Police」を担当しました。
- The Net
-
トップ画面右下に「π」の文字がうっすら浮かんでいたのですが、この文字を出現させるCSSは
bootstrap.css
中に定義されていました。そのCSS中に、コメントの形式でフラグの文字列を設置しておりました。通信データを逐一フィルタしていれば、何も知らなくても発見できていたでしょう。
- Police
- 吉村くん(@_yyu_)が原案のJavaScriptを制作し、わたしがその検査器をPythonで書きました。解き方は彼のブログに載せられる予定になっている[要出典]ので、わたしは裏方のタネ明かしをしたいと思います。問題自体の解法は、彼のブログに記事が上がるのを待ちましょう。用語や関数名なども彼のブログで解説されることを願いたい。
問題「Police」に挑戦してくださったみなさんはきっとお気づきかと思いますが、「validation.py
」というPython CGIが、XSS成功時にそのフォームの内容をPOSTで受け取っていました。
これは、バックエンドでユーザが入力したJavaScriptを評価するために、PyV8を用いていたからです。
では、validation.py
の内容(理解を簡単にするために一部簡単にしてあります)を見てみましょう。
#!/usr/bin/env python import PyV8 import cgi, cgitb # check JavaScript class Global(PyV8.JSClass): def isYoshimuraYuu(self): print "That was great!! The key is ... \"hatsuneMiku39\"" def notQuiteDone(self): print "You need to set the `proceedable` to true!" def evalJavaScript(post_data): try: ctxt = PyV8.JSContext(Global()) ctxt.enter() ctxt.eval(open('../public/check.js').read()) ctxt.eval(open('../private/foo.js').read()) ctxt.eval('checkSum(' + repr(post_data) + ')') ctxt.leave() except Exception, e: print "Perhaps syntax error? Try again!" # end JavaScript # CGI form = cgi.FieldStorage() print 'Content-type: text/html' print evalJavaScript(form.getvalue('solution')) # end CGI
ざっくらばんにいうと、皆さんのブラウザにも現れたcheck.js
とfoo.js
(※サーバ上で動かすための多少の改変あり)をロードし、そのJavaScriptに対して、checkSum(ユーザの入力)
を評価するということをしています。
その結果isYoshimuraYuu()
が実行されれば勝ちというわけです。isYoshimuraYuu()
はPythonで定義されていますが、PyV8を使うことでevalしたJavaScriptから呼び出せるので、こういうことができるのです。
こんな変な名前なのは、参加者のブラウザにロードされる諸JavaScriptと名前の衝突を起こさないようにするためです。
つまるところ、foo.js
で定義されたgiveMeTheFlag()
がproceedable == true
の状態のときに実行されると、PythonのisYoshimuraYuu()
が実行される仕組みになっているわけです。
こんな裏方を作っていました。結局、半数の正解者が別解で解いたため、何度か手動検査をやるはめになったのですが。
Comments
No comments.