TSALVIA技術メモ

CTFのWriteupや気になったツールについて書いていきます。また、このサイトはGoogle Analyticsを利用しています。

BackdoorCTF 2019 Writeup

BackdoorCTF 2019 について

BackdoorCTF 2019 が開催されました。
2019年10月27日午前0時30分~2019年10月28日午前0時30分(24時間)

backdoor.sdslabs.co

同日に Tasteless CTF 2019 もあり、あまり問題を見れていませんが、難易度高めのCTFだと思います。 今回もチームで参加しました。チームのメンバが2問解いてくれました。 結果は、30/205位で376点でした。 私も1問だけ解くことができたので、そのWriteupを紹介します。

f:id:tsalvia:20191028022414p:plain

同日に Tasteless CTF 2019 も開催されていました。 こちらも同時に参加していました。Writeupを書きましたので、参考にしてみてください。

tsalvia.hatenablog.com

BackdoorCTF 2019 Writeup(1問)

meow-1(web)

問題

Can you get all the flags???
Source: http://backdoor.static.beast.sdslabs.co/static/meow/dist.zip
Link: http://51.158.118.84:16001/
Created by: Faizal Hasanwala

解答例

http://51.158.118.84:16001/ に接続すると、ログイン画面が表示されます。

f:id:tsalvia:20191028024625p:plain

適当にアカウントを作成し、ログインしてみるとTwitterのようなページが表示されました。 ツイートのようなこともできそうです。

f:id:tsalvia:20191028024741p:plain

また、下のほうのツイートを見てみると、公式アカウントのようなアカウントがプライベート限定のツイートをしているようです。

f:id:tsalvia:20191028192344p:plain

今回は、ソースコードがすべて提供されているので、読んでみます。 app.pyを見てみると、以下のような処理がありました。 idinstance を指定して、呼び出すと該当するツイートをデータベースから取得して表示するようになっています。

# 省略

@app.route('/post')
@ensure_csrf
@login_required
@apply_csp
def view_post(request):
    if request.method == 'GET':
        post_id = request.args.get('id')
        instance = request.args.get('instance')
        success, post = get_post(session, post_id, instance)
        if success:
            return render_template('post.html',
                                   post=post,
                                   csrf=request.session['csrf'])
        else:
            return render_template('404.html')

# 省略

また、db.pyのget_postを見てみると、以下のようになっており、プライベートのツイートかどうかを判断しているように見えません。

# 省略

def get_post(session, post_id, instance):
    post = session.query(Post).filter_by(id=post_id,
                                         instance=instance).first()
    if not post:
        return (False, 'Post does not exist')

    poster = session.query(User).filter_by(username=post.posted_by).first()

    res = {'posted_by': post.posted_by, 'posted_name': poster.name,
           'content': post.content, 'preview': post.preview,
           'link': post.link, 'instance': post.instance,
           'id': post.id}

    return (True, res)

# 省略

idinstanceが分かれば、任意のツイートを読み出すことができそうです。 開発者モードで見ていると、そのまま書かれていました。

f:id:tsalvia:20191028025139p:plain

idinstanceが判明したので、実際にアクセスしてみると、自分のツイートを参照することができました。
アクセス先:http://51.158.118.84:16001/post?instance=a8e46c63-6e31-4445-bd80-3218275130e8&id=2112

f:id:tsalvia:20191028025247p:plain

公式アカウントのプライベート限定ツイートも同様の手順で参照してみました。 下から3つ目のツイートを参照してみると、フラグが書かれていました。
アクセス先:http://51.158.118.84:16001/post?instance=a8e46c63-6e31-4445-bd80-3218275130e8&id=2104

f:id:tsalvia:20191028025423p:plain

FLAG

BackdoorCTFでは、出てきたフラグのSHA256のハッシュ値を求めて、その結果を解答する必要があります。 以下のように実行して得られたハッシュ値が正解となります。

$ echo -n "flag{463048332a5a102f091f5620dfa6a261}" | sha256sum
2929e0dcbae938d2bfd5533c6ae0f0406aa5d444f81dfadbd2a5b2d4fc6046b6  -

2929e0dcbae938d2bfd5533c6ae0f0406aa5d444f81dfadbd2a5b2d4fc6046b6