はじめに

10/08 22:00 ~ 10/09 22:00 の期間に開催されたBlackHat MEA Qualification CTFに参加しました。

チームでは主にGuessを担当しました。

Writeup

Authy

Webです。Goで書かれたソースコードがあります。Easy

RegistrationとLoginができ、Registrationのとき、stringのpasswordは6文字以上である必要があります。

        var user models.Users
        body, _ := io.ReadAll(c.Request().Body)
        err := json.Unmarshal(body, &user)
        if err != nil {
                return err
        }
        if len(user.Password) < 6 {
                log.Error("Password too short")
                resp := c.JSON(http.StatusConflict, helper.ErrorLog(http.StatusConflict, "Password too short", "EXT_REF"))
                return resp
        }

が、login時にそのpasswordを []rune(user.Password) で変換し、lenが6未満だとFlagが出力されます。

func LoginController(c echo.Context) error {
        var user models.Users
        payload, _ := io.ReadAll(c.Request().Body)
        err := json.Unmarshal(payload, &user)

        if err != nil {
                log.Error(err)
                return err
        }
        var result models.Users
        DB := db.DB()
        sqlStatement := "select * from users where username=?"

        err = DB.QueryRow(sqlStatement, user.Username).Scan(&result.Username, &result.Firstname, &result.Lastname, &result.Password, &result.Token, &result.DateCreated)
        if err != nil {
                log.Error(err)
                resp := c.JSON(http.StatusInternalServerError, helper.ErrorLog(http.StatusInternalServerError, "Invalid Username", "EXT_REF"))
                return resp
        }

        err = bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(user.Password))
        if err != nil {
                log.Error("Invalid Password :", err)
                resp := c.JSON(http.StatusInternalServerError, helper.ErrorLog(http.StatusInternalServerError, "Invalid Password", "EXT_REF"))
                return resp
        }
        password := []rune(user.Password)
        result.Token = helper.JwtGenerator(result.Username, result.Firstname, result.Lastname, os.Getenv("SECRET"))
        if len(password) < 6 {
                flag := os.Getenv("FLAG")
                res := &Flag{
                        Flag: flag,
                }
                resp := c.JSON(http.StatusOK, res)
                log.Info()
                return resp
        }
        resp := c.JSON(http.StatusOK, result)
        log.Info()
        return resp
}

なんかruneなので適当に日本語を入れてみます。

$ curl -X POST http://.playat.flagyard.com/registration -d '{"username":"dog","password":"いぬ"}'
{"username":"dog","password":"$2a$05$kl.h7g7CJl70jC./xkagMuw78OBTf6PUNVsWQYHyVlZq8N5ukIGKG","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInVzZXJuYW1lIjoiZG9nIn0.QNXncia0bCSI92baY2kj0gR0zMrstjtW51R24Uww2WE","date_created":"2023-10-08 14:27:32"}
$ curl -X POST http://.playat.flagyard.com/login -d '{"username":"dog","password":"いぬ"}'
{"flag":"BHFlagY{a2768d0d66f6e377190997130c9e1846}"}

いけました

USB100

Forensicsです。Easy

USBのパケットが与えられるので、binwalkします。

PEが入ってるのでwineで実行したらFlagが出ました。以上。

BHflagy{1d3cbfa0e052b1729a00950e9fc0f61a3f393bc97c0c74c8ecab1b58cd0f95c32e4c970bdfa6e23371d50680ca0c37f61f7206974d20d5cbb2f00151f4735dde}

と思ったらこれだと弾かれます。長すぎるらしい。問題文を読むとBHFlagY{}を消せ。と書いてあります。:thinking:

どこにもBHFlagYとは書いていませんが、多分BHflagyのことでしょう。消してsubmitすればOKです。

1d3cbfa0e052b1729a00950e9fc0f61a3f393bc97c0c74c8ecab1b58cd0f95c32e4c970bdfa6e23371d50680ca0c37f61f7206974d20d5cbb2f00151f4735dde

Not supported

これもForensicsです。Medium

メモリダンプが渡されるので。stringsしたら出ました。

strings memdump.mem| rg -i bhflag
BHflagY{d22a 3  e e  d 0  5 0  c 2  3 c  0 8  8 0  c c  9 1  2 3  6 8 9 0  5  c  9  d 2 5  2 7 a  4 1 c 3 2 8  f 8 1  e f  1 1  5 b  9  4 64 b  8 0  0f 7 42 5 33 3 edb7 1d5  7b4 40b  94 d c 7  6 6a 2d 4 9 61 1 d4  69 68 47  7b09dfa1  f246585d  8 7d 7b 5 a}
BHflagY{d22a 3  e e  d 0  5 0  c 2  3 c  0 8  8 0  c c  9 1  2 3  6 8 9 0  5  c  9  d 2 5  2 7 a  4 1 c 3 2 8  f 8 1  e f  1 1  5 b  9  4 64 b  8 0  0f 7 42 5 33 3 edb7 1d5  7b4 40b  94 d c 7  6 6a 2d 4 9 61 1 d4  69 68 47  7b09dfa1  f246585d  8 7d 7b 5 a}
BHflagY{d22a 3  e e  d 0  5 0  c 2  3 c  0 8  8 0  c c  9 1  2 3  6 8 9 0  5  c  9  d 2 5  2 7 a  4 1 c 3 2 8  f 8 1  e f  1 1  5 b  9  4 64 b  8 0  0f 7 42 5 33 3 edb7 1d5  7b4 40b  94 d c 7  6 6a 2d 4 9 61 1 d4  69 68 47  7b09dfa1  f246585d  8 7d 7b 5 a}

BHflagY{d22a3eed050c23c0880cc912368905c9d2527a41c328f81ef115b9464b800f7425333edb71d57b440b94dc766a2d49611d46968477b09dfa1f246585d87d7b5a}

Light up the Server

Reversingです。Hard

改変されたlighttpdのバイナリとconfigなどが渡されます。

改変されている部分を追っていくと正規表現っぽいのが見つかったので、gdbでブレークポイントを貼って抽出します

^\\([a-z]\\?[^a-e,g-z]\\)la[g]{\\(h\\)0\\(s\\)t_\\2\\(e\\)4d\\4\\(r\\([_]\\?[^a-z]\\)\\)\\(!\\)n\\(\\(j\\(3\\)\\)cti0\\)n\\(_\\)1s\\6\\{1\\}5up3\\5c3wl}$

あとは脳内でやるだけ

flag{h0st_he4der_!nj3cti0n_1s_5up3r_c3wl}

なんでフォーマット違うん?

BHFlagY{h0st_he4der_!nj3cti0n_1s_5up3r_c3wl}

こっちをsubmitすればOKです

おわりに

PwnやCryptoは良かったっぽいですが、Web(Authyを除く)やForensicsはかなりアレです。FlagのフォーマットがバラバラなCTF久々に見たな。

まさかBlackHatがこんなだとは思わなかったね。中東の治安が悪いでしょうがない気もしたけど作問の時はこんなじゃなかっただろ。

GG(Grep & Geuss)