Files
ctf/2026/kalmar/web/handout/bot/bot.js
2026-04-15 01:05:54 +02:00

74 lines
1.8 KiB
JavaScript

const express = require('express');
const puppeteer = require('puppeteer');
const app = express();
const FLAG = process.env.FLAG || 'kalmar{test_flag}';
const CHALLENGE_DOMAIN = process.env.CHALLENGE_DOMAIN || 'http://web:5000/';
app.use(express.json());
function sleep(ms) {
return new Promise(res => setTimeout(res, ms));
}
async function visitUrl(url) {
const browser = await puppeteer.launch({
headless: true,
args: [
// this is not a pwn challenge, please don't rce us
'--disable-extensions',
'--disable-gpu',
'--disable-software-rasterizer',
'--js-flags=--noexpose_wasm,--jitless',
'--no-sandbox',
]
});
try {
const page = await browser.newPage();
await page.goto(CHALLENGE_DOMAIN, {
waitUntil: 'networkidle0',
});
// Flag is stored in localStorage
await page.evaluate((flag) => {
localStorage.setItem("flag", flag);
}, FLAG);
await sleep(1000);
await page.close()
// now visit reported page
const page2 = await browser.newPage();
await page2.goto(url, {waitUntil: []});
await sleep(5000);
} catch (err) {
console.error('Error visiting page:', err);
} finally {
await browser.close();
}
}
app.post('/report', async (req, res) => {
const { url } = req.body;
if (!url || typeof url !== 'string' || !url.startsWith(CHALLENGE_DOMAIN + '?')) {
return res.status(400).json({ error: `Invalid URL. Url should be a string and start with ${CHALLENGE_DOMAIN + '?'}` });
}
try {
await visitUrl(url);
res.json({ success: true });
} catch (err) {
console.error('Error on /report', err);
res.status(500).json({ error: 'Failed to visit URL' });
}
});
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Bot listening on port ${PORT}`);
});