https://alpacahack.com/daily/challenges/curl-as-a-service-2
/frontend/app.py
@app.post("/curl")
def curl():
url = request.form.get("url", "")
completed_process = subprocess.run(
[
"curl",
"--silent",
"--show-error",
url,
],
capture_output=True,
text=True,
)
return {
"output": completed_process.stderr or completed_process.stdout,
}
POST /curl の url パラメータに任意の文字列を渡せることがわかる。ただし curl への引数としては1つだけ
secret/app.py (1337 番ポートに接続があったとき実行されると律儀に教えてくれている)
# This program is executed when there is a connection to 1337/tcp by socat
answer = input("What is your wish?").strip()
print(f"Your wish: {answer}")
if answer == "Give me a flag":
print("Sure! Here is the flag!")
with open("flag.txt") as f:
print(f.read().strip())
else:
print("Sorry, I can't do that...")
標準入力に Give me a flag と入力すればいいらしい。
secret/Dockerfile
# 中略
CMD ["socat", "-T1", "tcp-listen:1337,fork,reuseaddr", "exec:'python app.py'"]
...というプログラムが secret:1337 で実行されていることがわかる。
curl の仕様を読むと良い https://curl.se/docs/manpage.html#--telnet-option
すると何やら大量のプロトコルがサポートされていることがわかる。いろいろ目をつけてもいいが、今回は CTF 関連でよく使われる Gopher プロトコルの仕様を読む。
https://datatracker.ietf.org/doc/html/rfc4266 (自動で日本語訳されたもの) https://tex2e.github.io/rfc-translater/html/rfc4266.html
このプロトコルは以下のURLを受け取る。
gopher://<host>:<port>/<gopher-path>
<gopher-path> は以下の形式のいずれか。
<gophertype><selector>
<gophertype><selector>%09<search>
<gophertype><selector>%09<search>%09<gopher+_string>