2023 ACSC CTF Qual Writeup
這次賽程只有 24 hr ,題目的難度都挺高,每個都參雜一些密碼學,也許是因為亞洲賽區大家數學都很好吧,我好不容易解完數學的那些題目都已經超過二十隊解,最後才 56 th 不能出國玩QQQQ 亞洲人之恥...
題目都相當好玩,唯一缺點是時間太少來不及看
Web
Admin Dashboard
題目需要得到 admin 權限來瀏覽 index 獲得 flag。有個登入後可以 report 的功能,還有一個受 CSRF Token 保護的 addadmin 頁面可以將帳號提升為 admin
report.php 的 system
裡可以錯誤回顯造成 XSS,開個 socket server 隨便傳個東西讓 HTTP Response 解析壞掉即可
flag 位於 admin 登入後的首頁,以前使用多個 iframe 登入不同帳號造成 XSS 再跨 iframe 讀取的打法已經失效,現在 chrome 預設 cookie SameSite 為 lax,但是 iframe 只能寫入 none 屬性的 cookie,一個 rabbit hole。
只能乖乖破解 CSRF Token,生產方式大概如下
# u1,u2 透過自行註冊的兩個 username 轉換,為已知
# a,c 未知
# sx1,sx2 是 csrf token
# M 模數 固定已知,以下都是模運算
a*u1+c = sx1
a*u2+c = sx2
a = (sx2-sx1)/(u2-u1)
c = sx1-(a*u1)
剛好 addadmin 頁面的 username、CSRF Token 透過 $_REQUEST
拿取,提交 http://localhost/addadmin?username=cjiso&password=7122&csrf-token=1fe69abb084e42434627a84405d722e0
即可 , flag ACSC{C$rF_15_3VerYwh3Re!}
easySSTI
一個可以傳入任意 template 的 Golang SSTI,回傳內容需要繞過 WAF
if (/ACSC\{.*\}/.test(data)) {
return reply.code(403).send("??")
}
Golang Template 可以通過當前 .
來存取其他屬性,並且可以把屬性當作函式呼叫,這題就翻翻 source code 找利用鏈,個人感覺 Golang 相對其他語言好找,沒有一堆奇怪的 magic。翻閱 echo source code 可以找到一條 .Echo.Filesystem.Open
打開 flag ,接著在 $x.Read
卡很久,因為參數需要 []byte
的變數,雖然可以宣告變數和使用部分函式,但是生成任意型態變數就相當困難,這部分也許是可以深入研究的點。最後是想起題目 context
本身有宣告 template
作為 buffer 剛好可以拿來用,再搭配 slice
去頭。
{{$y := .Get "template" }}{{ $x := .Echo.Filesystem.Open "/flag"}} {{$x.Read $y}} {{slice $y 1 40 | .HTMLBlob 200}}
flag ACSC{h0w_did_y0u_leak_me}
題外話,我研究了好久還是不知道怎麼直接把函式回傳值做為參數,先存一下 🍁 的 payload ,神奇語法
{{ (.Echo.Filesystem.Open "/flag").Read (.Get "template") }} {{ .Get "template" }}
A parenthesized instance of one the above, for grouping. The result may be accessed by a field or map key invocation. print (.F1 arg1) (.F2 arg2) (.StructValuedMethod "arg").Field
Gotion
賽中沒解出來,看他給的題示大致猜到要透過 Nginx Byte-Range Caching 把預設給的 mp4 檔案弄出一個合法的 XSS payload,但是在 Qtime 快冷死又快日出,看了半天想不出怎麼 cache poisoning QQ
蠻有趣的題目待研究 TODO
10av 🍊
賽中沒解出來,掃過去有開一堆奇怪的防毒和郵件服務,看起來一臉上傳檔案戳服務達到 RCE,但是來不及看文檔QQ
Crypto
Merkle Hellman
題目就是 Merkle–Hellman knapsack cryptosystem ,直接給 public key、private key、ciphertext、mod number,依照 wiki 的解密法應該能解,但是我數學不好感覺實作有點麻煩,後來想到一次一個 byte 暴力破解
Reverse
serverless
這題就慢慢解 javascript 混淆,然後看懂他在做 RSA 加密
有個要看好一陣子的是這個做快速冪的函式
function w(ps1, n2_1_1, pq1) {
if (n2_1_1 === 0) return 0x1n
return n2_1_1 % 2 === 0 ? w((ps1 * ps1) % pq1, n2_1_1 / 2, pq1) : (ps1 * w(ps1, n2_1_1 - 1, pq1)) % pq1
}
有人丟到 ChatGPT 就知道是快速冪 Orz
flag ACSC{warmup_challenge_so_easy}
ngo
賽中沒解出來,程式本身主動解密送 flag,逆完會發現有個解密迴圈次數是指數成長,導致解密程式跑不完,迴圈內在計算這個 a
a = a >> 1 ^ -(a & 1) & a
感覺像 LFSR ,但忘記 LFSR state 有循環的特性 (f^n)(a) == a
可以加速運算,當時猜測 a
有循環,熬夜昏頭把範圍設 10000 而已就找不到循環 QQ。正規解是 (2**32 - 1) 會循環。
Hardware
Hardware is not so hard
一道分析 sd card SPI mode traffic 題目,最麻煩的點是找到 spec
http://ccy.dd.ncu.edu.tw/~chen/rd/SIOC/SD Card驅動程式開發2.pdf
http://chlazza.nfshost.com/sdcardinfo.html
依照 spec parse,把讀取資料照順序寫成一張圖片即可
import binascii
blocks = [0 for i in range(64)]
i = 0
with open("spi.txt", "r") as f, open("out.jpg", "wb") as outfile:
for l in f.readlines():
if "SD Card to Device : ff" in l:
l = l[l.find("fe") + 2 : -5]
print(len(l))
data = binascii.unhexlify(l)
blocks[i] = data
elif "Device to SD Card : 51" in l:
l = l[28:30]
i = int(l, 16)
for block in blocks:
outfile.write(block)
# ACSC{1tW@sE@syW@snt1t}