はまやんはまやんはまやん

hamayanhamayan's blog

Two Sides of a Coin [BalCCon2k20 CTF]

Two Sides of a Coin
oioki
Bulletin Board where you can buy or sell cool stuff. Check it out:
https://two-sides-of-a-coin.pwn.institute

まずはエンドポイントを試す

  • / 色々出てくる
  • /add -> Sorry, new advertisements are temporarily not allowed.
    • ですよねー
    • READONLYはtrueのようだ
  • /view/bctf0eua8o7nl8uv9bpn6yho41p52wel 普通に表示される

んー、これ環境変数書き換えないとダメじゃないか?

Writeup

CTFtime.org / BalCCon2k20 CTF / Two Sides of a Coin / Writeup
ソースコードをよく読みましょう。

ID推測

/view/<_id>のエンドポイントを見る。
SELECT id_viewer, id_editor, posted_at, title, text_viewer, text_editor FROM board WHERE id_viewer = ? OR id_editor = ? LIMIT 1'というSQL文になっていて、?にはどちらも指定のIDが入る。
id_editor側でヒットさせることができれば、追加情報が手に入る。
サイト側で使われているのは、id_viewerの方である。
id_viewerからid_editorを推測することはできないだろうか。

/addのエンドポイントを見ると、使うことはできないが、idの作成方法が書いてある。

def get_random_id():
    alphabet = list(string.ascii_lowercase + string.digits)
    return ''.join([random.choice(alphabet) for _ in range(32)])

...

posted_at = round(time.time(), 4)
random.seed(posted_at)
id_viewer = get_random_id()
id_editor = get_random_id()

見ると時間をシードとして、IDを取得している。
時間は取得できるので、コードを参考にしてIDを復元してみよう。

time.timeはエポック秒を小数で返す。roundで小数点4位までにして、シードに使っている。
エポック秒については、

Will code for food
If you're interested, drop me a message.
Posted at 2020-09-22 21:09 UTC

というところから、秒を0-59で全探索すれば見つかる。
小数点部分についても全探索をして、指定の時間を見つけていこう。

例えば、2020-09-22 21:09:001600808940であり、00.0000-59.9999の間を全探索しよう。
すると見つかる。
フラグはWill code for foodの記事にあるので、以下スクリプトでid_editorを見つけ出して、GETしよう。
/view/k6wfi4zwhdcwqtqgay57djxpcv9gb7fkとするとフラグが得られる。
BCTF{numb3rs_from_PRNG_are_n0t_really_rand0m}

import string
import random
from tqdm import tqdm

def get_random_id():
    alphabet = list(string.ascii_lowercase + string.digits)
    return ''.join([random.choice(alphabet) for _ in range(32)])

ans = 'cfddcxulrhohtilq03qke9v0iqwddmvz'
epo = 1600808940 * 10000

for i in tqdm(range(1011010)):
    random.seed((epo + i) / 10000)
    id_viewer = get_random_id()
    id_editor = get_random_id()

    if id_viewer == ans:
        tqdm.write(f'find! {id_editor}')
        exit(0)