日記

日本語の勉強のためのブログ

防衛省サイバーコンテスト 2024 writeup

32問中16問解けた。合計得点は188点で84位。あと数時間あれば…

進捗

あまり参考にならないかもしれないがwriteupを置いておく。
※解きながらwriteupを書いていたので、結局解けなかった問題についても記述してある。

Crypto

Information of Certificate (10)

Easy.crt ファイルは自己署名証明書です。証明書の発行者 (Issuer) のコモンネーム (CN) 全体を flag{} で囲んだものがフラグです。

証明書を開き、発行者欄のCNを見ればよい。

flag{QRK7rNJ3hShV.vlc-cybercontest.invalid}

Forensics

NTFS Data Hide (10)

NTFSDataHide フォルダに保存されている Sample.pptx を利用して、攻撃者が実行予定のスクリプトを隠しているようです。 仮想ディスクファイル NTFS.vhd を解析して、攻撃者が実行しようとしているスクリプトの内容を明らかにしてください。

この手の問題ははじめてだったので、よく使用されるツールから調べていく。 どうやら「FTK Imager」を使えばいいらしい。 起動したらウィンドウ左上の緑のボタンAdd Evidence Itemを押してImage Fileを選択、NTFS.vhdを指定してFinishを押す。これで左側のEvidence Treeに仮想ディスクのファイル構造が表示されるようになった。

…と思っていたがFTK Imagerでは解けなかった(ヒントを見てADSが鍵になっているとわかったものの、このツールではADSを確認できなかった)。代わりに「AutoPsy」というフォレンジックツールを導入したところ、NTFSDataHide/Sample.pptx:scriptというADSファイルが見つかった。中身を次に示す。

[System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('ZmxhZ3tkYXRhX2Nhbl9iZV9oaWRkZW5faW5fYWRzfQ=='))

このZmxhZ3tkYXRhX2Nhbl9iZV9oaWRkZW5faW5fYWRzfQ==という部分をbase64でデコードすればflagが得られる。

flag{data_can_be_hidden_in_ads}

NTFS File Delete (10)

NTFSFileDelete フォルダにフラグを記載した txt ファイルを保存したのですが、どうやら何者かによって消されてしまったようです。 問題「NTFS Data Hide」に引き続き、仮想ディスクファイル NTFS.vhd を解析して、削除された flag.txt に書かれていた内容を見つけ出してください。

FTK Imagerを利用し、NTFSFileDelete/flag.txtを確認すればよい。

flag{resident_in_mft}

HiddEN Variable (20)

このメモリダンプが取得された環境にはフラグが隠されています。 memdump.raw を解析して、フラグを見つけ出してください。

時間がなかったので即ヒントを開ける。Volatilityというツールで環境変数を確認すればよいとわかったのでpython3 vol.py -f ../memdump/memdump.raw windows.envarsを実行、大量のログの中にFLAG BDkPUNzMM3VHthkj2cVEjdRBqTJcfLMJaxT9si67RgJZ45PSとあったのでこれをbase58でデコード。

flag{volatile_environment_variable}

NTFS File Rename (20)

NTFSFileRename フォルダに保存されている Renamed.docx は、以前は別のファイル名で保存されていました。 問題「NTFS File Delete」に引き続き、仮想ディスクファイル NTFS.vhdを解析して、 Renamed.docx の元のファイル名を明らかにしてください。

FTK Imagerを利用。
(追記:AutoPsyだと瞬殺できると思う)

[root]/$LogFileにファイルの変更履歴が記されている(参考リンク)。 そのため$LogFileをエクスポートし、「LogFileParser」で詳しく調べる。

LogFileParserを実行すると複数のファイルが出力されるが、そのうちLogFileParser_vXXX\LogFile_XXX\LogFile_FileNames.csvにファイル名の変遷が記されている。 このファイルをExcelで開く。MftRefがMFTのレコード番号、つまりMFT(マスターファイルテーブル)におけるファイルの通し番号を示す。大雑把に言えば、この問題においては、MftRefが同じであれば同じファイルであるといってよい。 Renamed.docxと同じMftRefを持つファイルはjournaling_system_is_powerful.docxであるから、このファイルがリネームされてRenamed.docxになったと考えられる。

flag{journaling_system_is_powerful}

My Secret (30、解けなかった)

問題「HiddEN Variable」に引き続き、メモリダンプファイル memdump.raw を解析して、秘密(Secret)を明らかにしてください。

即ヒント開ける。7zip関連のプロセスを見ればよいとのことなので

$ python3 vol.py -f ../memdump/memdump.raw windows.pstree.PsTree | grep 7z 
**** 5516  100.03468    7z.exean0xe206bb303080  4       -       1       False   2023-12-26 00:51:23.000000      N/A     \Device\HarddiskVolume3\Program Files\7-Zip\7z.exe      7z  x -pY0uCanF1ndTh1sPa$$w0rd C:\Users\vauser\Documents\Secrets.7z -od:\        C:\Program Files\7-Zip\7z.exe

このSecrets.7zをダンプする。

$ python3 vol.py -f ../memdump/memdump.raw windows.dumpfiles --pid="5516"
Volatility 3 Framework 2.6.1
Progress:  100.00       PDB scanning finished
Cache   FileObject      FileName        Result

DataSectionObject 0xe206bbc4a2f0        Secrets.7z      Error dumping file
SharedCacheMap  0xe206bbc4a2f0  Secrets.7z      file.0xe206bbc4a2f0.0xe206bbabada0.SharedCacheMap.Secrets.7z.vacb
ImageSectionObject      0xe206bbc491c0  7z.dll  file.0xe206bbc491c0.0xe206bb46d770.ImageSectionObject.7z.dll.img
ImageSectionObject      0xe206bba6c490  7z.exe  file.0xe206bba6c490.0xe206b8b49730.ImageSectionObject.7z.exe.img
ImageSectionObject      0xe206b6121570  KernelBase.dll  file.0xe206b6121570.0xe206b610dc10.ImageSectionObject.KernelBase.dll.img
ImageSectionObject      0xe206b61210c0  win32u.dll      file.0xe206b61210c0.0xe206b62e17c0.ImageSectionObject.win32u.dll.img
ImageSectionObject      0xe206b9139e80  cryptbase.dll   file.0xe206b9139e80.0xe206b912bcc0.ImageSectionObject.cryptbase.dll.img
ImageSectionObject      0xe206b6122380  msvcp_win.dll   file.0xe206b6122380.0xe206b610e460.ImageSectionObject.msvcp_win.dll.img
ImageSectionObject      0xe206b6122ce0  gdi32full.dll   file.0xe206b6122ce0.0xe206b610e9a0.ImageSectionObject.gdi32full.dll.img
ImageSectionObject      0xe206b611bed0  oleaut32.dll    file.0xe206b611bed0.0xe206b62d5a50.ImageSectionObject.oleaut32.dll.img
ImageSectionObject      0xe206b61213e0  combase.dll     file.0xe206b61213e0.0xe206b62d6a20.ImageSectionObject.combase.dll.img
ImageSectionObject      0xe206b6122e70  ucrtbase.dll    file.0xe206b6122e70.0xe206b62da2b0.ImageSectionObject.ucrtbase.dll.img
ImageSectionObject      0xe206b61229c0  sechost.dll     file.0xe206b61229c0.0xe206b62d6cf0.ImageSectionObject.sechost.dll.img
ImageSectionObject      0xe206b611b3e0  advapi32.dll    file.0xe206b611b3e0.0xe206b62e1010.ImageSectionObject.advapi32.dll.img
ImageSectionObject      0xe206b6121250  imm32.dll       file.0xe206b6121250.0xe206b62d7cc0.ImageSectionObject.imm32.dll.img
ImageSectionObject      0xe206b611c380  rpcrt4.dll      file.0xe206b611c380.0xe206b62e3cd0.ImageSectionObject.rpcrt4.dll.img
ImageSectionObject      0xe206b611c830  user32.dll      file.0xe206b611c830.0xe206b62d5d00.ImageSectionObject.user32.dll.img
ImageSectionObject      0xe206b611c9c0  gdi32.dll       file.0xe206b611c9c0.0xe206b62e3a20.ImageSectionObject.gdi32.dll.img
ImageSectionObject      0xe206b611c510  msvcrt.dll      file.0xe206b611c510.0xe206b62e06c0.ImageSectionObject.msvcrt.dll.img
ImageSectionObject      0xe206b611ce70  kernel32.dll    file.0xe206b611ce70.0xe206b62e3520.ImageSectionObject.kernel32.dll.img
ImageSectionObject      0xe206b0ef9940  ntdll.dll       file.0xe206b0ef9940.0xe206b0bc5010.ImageSectionObject.ntdll.dll.img

file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.datを7zで解凍したがエラーが出る。パスワードが違う?

$ 7z  x -pY0uCanF1ndTh1sPa$$w0rd file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,6 CPUs Intel(R) Core(TM) i5-8500 CPU @ 3.00GHz (906EA),ASM,AES-NI)

Scanning the drive for archives:
1 file, 4096 bytes (4 KiB)

Extracting archive: file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat

WARNINGS:
There are data after the end of archive

--
Path = file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat
Type = 7z
WARNINGS:
There are data after the end of archive
Physical Size = 418
Tail Size = 3678
Headers Size = 146
Method = LZMA2:12 7zAES
Solid = -
Blocks = 1

ERROR: Data Error in encrypted file. Wrong password? : Secrets.rtf

Sub items Errors: 1

Archives with Errors: 1

Warnings: 1

Sub items Errors: 1

別の方法でダンプを試みたがダメだった。

$ python3 vol.py -f ../memdump/memdump.raw windows.dumpfiles --physaddr 0xe206bbc4a2f0   
Volatility 3 Framework 2.6.1
Progress:  100.00       PDB scanning finished
Cache   FileObject      FileName        Result
(※注:何も出力されなかった)

Miscellaneous

Une Maison (10)

画像 maison.jpg の中にフラグが隠されています。探してみてください。

stringsでもfileでも異常なし。steghideも違った。 わからずヒント1を開くと、

メタデータやバイナリの解析は必要ありません。

とのこと。とりあえず画像検索してみると似た画像が出てきたが、一部異なる部分がある。よく見るとバーコードになっていたため、そこを切り出してGoogle Lensに投げるとflagが得られた。

切り取ったバーコード

flag{$50M!}

String Obfuscation (10)

難読化された Python コード string_obfuscation.py ファイルからフラグを抽出してください。

ソースコードを見ると

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)

との表記があるので、これをそのままprintしてやればよい。

$ 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.
>>> 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)
>>> print(FLAG)
3FxYFm4uTYDFFzmb3

flag{3FxYFm4uTYDFFzmb3}

Where Is the Legit Flag? (20)

fakeflag.py を実行しても偽のフラグが出力されてしまいます。難読化されたコードを解読し、本物のフラグを見つけ出してください。

fakeflag.pyの難読化を解除すると、次のようになる。

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)) 
# ↳ exec("import zlib, base64")

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(b'exec(zlib.decompress(base64.b64decode(TANAKA)))')

ここでexec(b'exec(zlib.decompress(base64.b64decode(TANAKA)))')を実行すると、以下のコードが実行される。

# Than volleyball vanish against lumpy berry.
SATO = '[QI3?)c^J:6RK/FV><ex7#kdYov$G0-A{qPs~w1@+`MO,h(La.WuCp5]i ZbjD9E%2yn8rTBm;f*H"!NS}tgz=UlX&4_|\'\\'
# Above face explain for physical decision.
# Via snake name round terrific brass.
# Following suggestion sound regarding female recess.
# Toward vessel disagree beneath huge porter.
SUZUKI = [74-0+0,
        87*1,int(48**1),
# Off purpose land as rural statement.
        int(8_3),int(32.00000),int('34'),
        76 & 0xFF,72 | 0x00,79 ^ 0x00,[65][0],
# During knot rely save wretched scarecrow.
        (2),47 if True else 0,int(12/1),10 % 11,ord(chr(26)),
        30+5,int(48/2*2),9*9]
#  Plus toe settle with vast insect.
#  Save hands shelter with ratty produce.
#  Outside legs nest versus tranquil relation.
#  As walk pat round rightful advice.
# Beside payment train by large key.
# Past behavior post toward unable home.
#  Among place complain considering unknown current.
( #  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.
)
#  Opposite yoke need beside superb lumber.
print("flog{8vje9wunbp984}")

これを整形したコードを次に示す。

SATO = '[QI3?)c^J:6RK/FV><ex7#kdYov$G0-A{qPs~w1@+`MO,h(La.WuCp5]i ZbjD9E%2yn8rTBm;f*H"!NS}tgz=UlX&4_|\'\\'
SUZUKI = [74-0+0,87*1,int(48**1),int(8_3),int(32.00000),int('34'),76 & 0xFF,72 | 0x00,79 ^ 0x00,[65][0],(2),47 if True else 0,int(12/1),10 % 11,ord(chr(26)),30+5,int(48/2*2),9*9]
(''.join([SATO[i] for i in SUZUKI]))
print("flog{8vje9wunbp984}")

注目すべきなのは3行目の(''.join([SATO[i] for i in SUZUKI]))である。この処理の結果はどこからも参照されていないので、試しにprintしてみる。するとflagが得られた。

flag{PHmN2ILK6vsa}

Network

FileExtract (10)

添付の FileExtract.pcapng ファイルからフラグを見つけ出し、解答してください。

wiresharkで添付ファイルを開く。ファイル -> オブジェクトをエクスポート → FTP-DATAをクリックすると、s3cr3t.zipなるファイルをエクスポートできる。しかしパスワードがかかっており解凍できない。 パケットを眺めると230 Login successfulという記述が見つかったため、この前後のパケットを見ると、Request: PASS br2fWWJjjab3という記述を発見。br2fWWJjjab3をパスワードとしたところ、s3cr3t.zipを解凍することができ、中身のファイルfl@gを確認できた。

flag{6qhFJSHAP4A4}

Programming

Logistic Map (10)

下記のロジスティック写像について、x_0 = 0.3 を与えた時の x_9999 の値を求め、小数第7位までの値を答えてください(例:flag{0.1234567})。なお、値の保持と計算には倍精度浮動小数点数を使用してください。 x_{n+1} = 3.99 x_n (1 - x_n)

Pythonで解いた。

x: float = 0.3
for i in range(1, 10000): # x_1 ... x_9999
    x = 3.99 * x * (1 - x)

print(x)
# -> 0.8112735...

flag{0.8112735}

Trivia

The Original Name of AES (10)

Advanced Encryption Standard (AES) は、公募によって策定された標準暗号です。 現在採用されているアルゴリズムの候補名は何だったでしょうか?

wikipediaを見る。

Advanced Encryption Standard (AES) は、アメリカが2001年に標準暗号として定めた共通鍵暗号アルゴリズムである。アメリカ国立標準技術研究所(NIST)が公募し、Rijndael(ラインダール)がAESとして採用された。 (https://ja.wikipedia.org/wiki/Advanced_Encryption_Standard より引用)

flag{Rijndael}

CVE Record of Lowest Number (10)

最も番号が若い CVE レコードのソフトウェアパッケージにおいて、脆弱性が指摘された行を含むソースファイル名は何でしょう?

最も番号が若いCVEレコードは、GitHubに上がっているCVEリストより、CVE-1999-0001であるとわかる。 この脆弱性の詳細を調べると、

BSD 由来の TCP/IP 実装の ip_input.c により、リモート攻撃者は細工されたパケットを介してサービス拒否 (クラッシュまたはハング) を引き起こすことができます。 (https://www.cvedetails.com/cve/CVE-1999-0001/ より引用、google翻訳使用)

とあるので、脆弱性が指摘された行を含むソースファイル名ip_input.cである。

flag{ip_input.c}

MFA Factors (10)

多要素認証に使われる本人確認のための3種類の情報の名前は何でしょう?それぞれ漢字2文字で、50音の辞書順で並べて「・」で区切ってお答えください。

IPAによると多要素認証に使われる本人確認のための3種類の情報は記憶情報、所持情報、生体情報である。

flag{記憶・所持・生体}

Web

Browsers Have Local Storage (10)

http://10.10.10.30 にアクセスしてフラグを見つけ出し、解答してください。

問題タイトルにあるように、ローカルストレージにflagが書いてある。ブラウザのF12キーを押して開発者ツールを起動し、アプリケーション -> ストレージ -> ローカルストレージで確認できる。

FLAG{Th1s_1s_The_fIrst_flag}

Are You Introspective? (10、解けなかった)

http://10.10.10.31 にアクセスしてフラグを見つけ出し、解答してください。 このサイトでは GraphQL が使用されているため、まずは endpoint を探す必要があります。

そもそもエンドポイントとは何かというと、APIの呼び出しが行われる場所APIにアクセスするためのURIのことらしい。

エンドポイントを探す必要があるが、goctopus(docker run --rm -it escapetech/goctopus:latest -a 10.10.10.31)を使用しても見つからなかった。

Insecure (20)

あなたは社内ポータルサイト(http://10.10.10.33)の管理者に依頼されて、profile ページが安全に保護されているかチェックすることになりました。 以下のログイン情報を用いてサイトにログインし、管理者の profile ページに記載されている秘密の情報を見つけてください。 なお、依頼の際に「管理者ページのidは0だよ」というヒントをもらっています。

testUserとしてログイン後、ページ下部の「プロフィールを見る」(http://10.10.10.33/show_profile.php?id=1)をクリックすると、プロフィールページ(http://10.10.10.33/profile_success.php)に遷移した。 次に、管理者のidが0であるというヒントを利用し、管理者のプロフィール(http://10.10.10.33/show_profile.php?id=0)にアクセスしてみたが、エラーページ(http://10.10.10.33/profile_error.php)に遷移してしまった。

そこで、BurpSuiteを用いて強引に管理者プロフィールにアクセスする。具体的には、

  1. BurpSuiteを起動、InterceptをONにしてから「プロフィールを見る」(http://10.10.10.33/show_profile.php?id=1)をクリック
  2. BurpSuiteでid=0id=1に書き換えてForward
  3. http://10.10.10.33/profile_error.phpにリダイレクトされるので、同じくBurpSuiteで遷移先をprofile_error.phpからprofile_success.phpに書き換えてForward

以上のプロセスを踏むことで管理者プロフィールにアクセスでき、フラグを得られる。

FLAG{1qaz7ujmbgt5}

Variation (20、解けなかった)

http://10.10.10.32 のWebサーバーで下記形式の XSS を発生させ、フラグを入手してください。 <script>alert(1)</script>

与えられたWebページでNameを入力してSubmitボタンを押すと、入力したNameが表示されるという問題。 試しに<script>alert(1)</script>を入力したところ、Hey, scriptalert(1)/scriptと表示された。 <>が削除されているため、パーセントエンコーディングして%3Cscript%3Ealert(1)%3C/script%3Eを入力してみたが、そのままHey, %3Cscript%3Ealert(1)%3C/script%3Eと出力されてしまう。