net-nyan-cat

俺たちがインフラ野郎Aチーム

taskctf 2020 writeup

2020/12/05~行われたtaskctfのwriteupです。
主催者のtaskerさんが誕生日とのことで行われているCTFの模様です。
今回は47チーム中7位(全問正解)でした。
面白い問題もあったので来年も楽しみです。以下、writeupです。

Web

Caesar Cipher Translator

問題文

シーザー暗号をエンコードするページを作成途中なのですが, どうもこのままだとマズいと先輩に指摘されました。 どうもXSSというのがあるようです。本当に実施できるか信じられないので, 実際にinjectedという文字列を出してもらえますか?

ページはこのようになっています。
f:id:xrzhev:20201206211106p:plain
XSSの問題かつ、公式からscriptタグを用いたXSSはうまく動作しない場合がある、ということだったのでimgタグでjavascriptの発火を狙います。
Ceasar cipherの通り、入力値がROT13で置き換えられた値が出力されます。

f:id:xrzhev:20201206211311p:plain
実はxrzhevはkemuriをROT13にかけたものなんです
ソースを見るとinputタグの終点を閉じればXSSができそうです。
というわけで埋めてみました。
f:id:xrzhev:20201206211612p:plain
f:id:xrzhev:20201206211644p:plain
無事にinputタグを埋めることができました。
次にalertを出すコードを埋め込んでいきます。
埋め込むコードは<img src=/ onerror=alert('injected')>です。
まずは上記のコードをROT13にかけ、<vzt fep=/ bareebe=nyreg('vawrpgrq')> とします。
その後、前述のinputタグを埋める">を先頭につけ、"><vzt fep=/ bareebe=nyreg('vawrpgrq')>という値を変換すると...?
f:id:xrzhev:20201206212443p:plain
alert発火

f:id:xrzhev:20201206212509p:plain
フラグ
フラグはtaskctf{n1ce_inject10n!}

Evil Eval

問題文

シーザー暗号の次は, base64をデコードするページを実装したらしい。
とはいえ, この実装ってあまり良くないんじゃ......

flag.txtが同じディレクトリにあるらしいから, それを読みだしてこの実装の危険性を教えてあげて。

提示されたソースコード

<?php
$result = "";
    if (isset($_GET['data'])) {
        $data = $_GET['data'];
        $raw = base64_decode($data);
        eval('$result = ' . $raw . ';');
    }
?>
<html>
<head>
    <meta charset="utf-8">
    <title>result</title>
</head>
<body>
    <h1>結果</h1>
    <p><?= $result ?></p>
</body>
</html>

ソースを見た感じ、base64エンコードしたflag表示用のコードを送り付けてやればいいみたいです。
flagを表示させるコードはfile_get_contents("./flag.txt")を用いました。
これをbase64エンコードしたものがZmlsZV9nZXRfY29udGVudHMoIi4vZmxhZy50eHQiKQ== これをクエリストリングにつけてリクエストすると…。

f:id:xrzhev:20201206213118p:plain
フラグ

フラグは taskctf{eval_1s_b4d_h4bit}

Gacha

問題文

ガチャを作ったらしいけど, そのseedの使い方間違ってない?

提示されたソースコード

package main

--- snip ---

func main() {
    srv := &http.Server{Addr: ":3334"}
    http.HandleFunc("/", gachaHandler)

    go func() {
        if err := srv.ListenAndServe(); err != nil {
            log.Printf("shutdown the server with error: %+v\n", err)
        }
    }()

    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGTERM)
    log.Printf("SIGNAL %d received, then shutting down...\n", <-quit)

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    if err := srv.Shutdown(ctx); err != nil {
        log.Println("failed to shutdown: %+v", err)
        os.Exit(1)
    }
}

func gachaHandler(w http.ResponseWriter, r *http.Request) {
    seed := r.FormValue("seed")
    if len(seed) == 0 {
        seed = "1"
    }
    seedInt, err := strconv.Atoi(seed)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // get current time(HHmmss)
    jst := time.FixedZone("Asia/Tokyo", 9*60*60)
    nowStr := time.Now().In(jst).Format("150405")
    log.Println(nowStr)
    nowInt, err := strconv.Atoi(nowStr)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    sm := (seedInt + nowInt) % 100000
    log.Println(sm)
    var flag map[string]string

    if sm == 1337 {
        flag = map[string]string{
            "flag": "taskctf{this_is_dummy_flag}",
        }
    } else {
        flag = map[string]string{
            "flag": "You might not have a luck...",
            "sum":  strconv.Itoa(sm),
        }
    }
    res, _ := json.Marshal(flag)
    w.WriteHeader(http.StatusOK)
    _, err = w.Write(res)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

ページを表示するとjsonで以下のような値が返ってきます。
f:id:xrzhev:20201206213357p:plain
ソースコードを見るに、この中のsumを1337にすればフラグが入手できるようです。
このsumを生成している部分ではシードとGMT+9の現在時刻より作られています。
そしてシード値はユーザーのリクエストで自由に指定できるようです。
実際に適当な値を指定してリクエストを送ってみました。
f:id:xrzhev:20201206213833p:plain
だいぶ近似しています。
本当は計算して1337へと当てはめるべきなんすが、値が近かったので勘で解きました。

f:id:xrzhev:20201206214040p:plain
フラグ

この問題はユーザーが選択できるシード以外にサーバーの時刻というファクターがあるため、sumを1337にするためにユーザーの送信するシード値は必ずも一定になりません。
難しいですね…。
フラグはtaskctf{Y0u_h4ve_4_gre4t_luck}

Misc

Welcome

問題文

楽しんでいってね!
flagはNotificationsのページに書かれているよ!

フラグはtaskctf{g00d_luck_h4ve_fun}

guess `?v=`

問題文

?v=t1zPpBwRbAw

何やら見覚えのあるパラメータな気がするな

たまたま別のディスプレイでYoutubeを開いていたのですが、この?v=...というクエリストリングを見つけたので、入れてみました。
f:id:xrzhev:20201206214539p:plain
まさかの正解でした。 ありがとうずとまよ。
フラグはtaskctf{h0w_w4s_it?}

social hacking

問題文

https://www.youtube.com/watch?v=t1zPpBwRbAw

パスワードで暗号化されたzipファイルが渡されます。

guess `?v=` でたどり着いたページが問題文として貼られていました。
動画の内容ですが、このsocial hackingという問題を作問中のtasker氏の肉声と思われる声が入っています。
zipファイルのパスワードですが、動画内の2:50あたりで触れており、「おにぎりとかにするか…で、誕生日を付け加えると。 月と日付だから…」 という発言をもとにzipファイルのパスワードはonigiri1205と推定し、解凍します。
無事解凍でき、フラグの入ったテキストが収取できました。
フラグは taskctf{n0t1ce_soci4l_h4ck1ng}

grass flag

問題文

interesting contributions

.gitディレクトリのみが存在するzipファイルが渡されます。
gitのログやコミットの内容等を精査しましたが、ほぼ空であり、ログの日付が2002年~2003年と到底考えられないものになっていました。
また、リモートリポジトリは削除されていたようで、詳細なチェックもできませんでした。
しかし、問題名から「草…?」と思い、2002~2003年のtasker氏のgithubの草を見てみるとフラグが。

f:id:xrzhev:20201206215449p:plain
見つけた時草生えた

読みやすいように編集すると以下のようになります。
f:id:xrzhev:20201206215539p:plain
フラグはtaskctf{lmao}

OSINT 2

問題文

友人が迷ってよく分からない駅で下車してしまったらしい。 駅前の画像を送ってくれたから, どこの駅前か特定してほしい。 駅名は全て漢字です。

画像 f:id:xrzhev:20201206215753j:plain

大仏の顔をクロップして画像検索にかけると大船駅であることが判明。 フラグはtaskctf{大船駅}

OSINT 3

問題文

友人が奇抜なTシャツを着てきた。
そもそもこれってどこで売られてるんだ......?
調べて教えて欲しい!

フラグの形式: taskctf{ショップ名}

画像 f:id:xrzhev:20201206215922j:plain

f:id:xrzhev:20201206215933j:plain
これは後から追加された画像だそうです。 1枚目の画像だけで解くのは相当難しいと思います。

2枚目の画像の右下の緑のタグにご注目。
白い文字で絵 か の 広場という文字があるように見えます。 「絵 か の 広場 Tシャツ」などで検索するとあるお店がヒットします。
f:id:xrzhev:20201206220206p:plain
原宿パリジャンのページを見ると同じような緑のタグが付いた手作りTシャツを確認できます。
フラグはtaskctf{原宿パリジャン}

おわりに

CTFやってて初めての全問解答ができました。
1時間半程度でサクッとできたのが非常に良かったです。
gitの草アートの問題は笑ってしまったので、来年も楽しみに待ってようと思います。
もっと修行するぞ~~!