Posts for the month of September 2013

第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.jsfoo.js(※サーバ上で動かすための多少の改変あり)をロードし、そのJavaScriptに対して、checkSum(ユーザの入力)を評価するということをしています。
その結果isYoshimuraYuu()が実行されれば勝ちというわけです。isYoshimuraYuu()はPythonで定義されていますが、PyV8を使うことでevalしたJavaScriptから呼び出せるので、こういうことができるのです。
こんな変な名前なのは、参加者のブラウザにロードされる諸JavaScriptと名前の衝突を起こさないようにするためです。

つまるところ、foo.jsで定義されたgiveMeTheFlag()proceedable == trueの状態のときに実行されると、PythonのisYoshimuraYuu()が実行される仕組みになっているわけです。

こんな裏方を作っていました。結局、半数の正解者が別解で解いたため、何度か手動検査をやるはめになったのですが。

軽くメモ

PythonでJavaScriptを評価するのにPyV8を使おうとするも、インストールに苦労した。

easy_install
503を吐いてたので使えなかった
pip
setup.pyがうんこだったので使えなかった
setup.py
setup.pyのextra_link_args = []extra_link_args = ['-lrt']に置き換えることで、 C++のclock_gettime()を呼び出せない問題を解決。リンキングのオプションがタコだった。

ZIPファイルに対するKnown Plaintext Attackについて






あやふみ女史(※男の娘)のコスプレ画像zipがパスワード付きでうpされたらしいです。

さらに、



ここでピンときた。

"Known Plaintext Attack" だ。

Known Plaintext Attack
パスワードを設定して暗号化したPKZIPファイルの中身をある程度知っていると、それをもとにストリームキーを推測してアーカイブ全体を解読できるというもの。

そして、




名指しで腕を試されている。

やるしかないね。

やってみました。


やっぱ記事書くのめんどくさい。やめた。なお解読はできた模様。