Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* [Xinted Service challenge with custom xinetd config](./xinetd-service)
* [Service challenge with auto-generated xinetd config](./service)
* [A bare challenge using docker](./docker-type)
* [Docker compose challenge](./compose-type)

To test any of the above challenges, cd to \_example directory and use the below command:

Expand Down
23 changes: 23 additions & 0 deletions _examples/compose-type/beast.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[author]
name = "contact"
email = "[email protected]"
ssh_key = "ssh-rsa AAAAB3NzaC1y"

[challenge.metadata]
name = "compose-type"
flag = "winterhack{w45_th15_y0ur_f1r5t_4dm1n_b07_ch4ll}"
type = "web"
points = 200

[[challenge.metadata.hints]]
text = "simple_hint_1"
points = 10

[[challenge.metadata.hints]]
text = "simple_hint_2"
points = 20

[challenge.env]
docker_compose = "docker-compose.yml"
web_root = "web"
ports = [10005]
3 changes: 3 additions & 0 deletions _examples/compose-type/bot/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
npm-debug.log
.env
1 change: 1 addition & 0 deletions _examples/compose-type/bot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
28 changes: 28 additions & 0 deletions _examples/compose-type/bot/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
FROM node:16-alpine3.16

ENV LANG="C.UTF-8" \
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true

RUN apk update && apk add --no-cache \
zlib-dev \
udev \
nss \
ca-certificates \
chromium && \
adduser -h /bot -D -u 10086 bot

WORKDIR /bot

COPY package*.json ./

RUN npm ci --only=production && \
npm cache clean --force

COPY . .

RUN chown -R bot:bot /bot


EXPOSE 9000

CMD ["node", "index.js"]
71 changes: 71 additions & 0 deletions _examples/compose-type/bot/bot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const puppeteer = require('puppeteer');
const BASE_URL = process.env.BASE_URL || 'http://0.0.0.0';
const FLAG= process.env.FLAG || 'test{flag}';
const sleep = ms => new Promise(res => setTimeout(res, ms));

const CONFIG = {
APPNAME: process.env['APPNAME'] || "Admin",
APPURL: process.env['BASE_URL'] || "http://127.0.0.1:8000",
APPURLREGEX: process.env['APPURLREGEX'] || "^.*$",
APPFLAG: process.env['FLAG'] || "winterhack{w45_th15_y0ur_f1r5t_4dm1n_b07_ch4ll}",
APPLIMITTIME: Number(process.env['APPLIMITTIME'] || "60"),
APPLIMIT: Number(process.env['APPLIMIT'] || "5"),
}

console.table(CONFIG)

const initBrowser = puppeteer.launch({
executablePath: "/usr/bin/chromium-browser",
headless: 'new',
args: [
'--disable-dev-shm-usage',
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-gpu',
'--no-gpu',
'--disable-default-apps',
'--disable-translate',
'--disable-device-discovery-notifications',
'--disable-software-rasterizer',
'--disable-xss-auditor'
],
ipDataDir: '/home/bot/data/',
ignoreHTTPSErrors: true
});

console.log("Bot started...");

module.exports = {
name: CONFIG.APPNAME,
urlRegex: CONFIG.APPURLREGEX,
rateLimit: {
windowS: CONFIG.APPLIMITTIME,
max: CONFIG.APPLIMIT
},
bot: async (urlToVisit) => {
const browser = await initBrowser;
const context = await browser.createIncognitoBrowserContext()
try {
const page = await context.newPage();
url = BASE_URL ;
await page.setCookie({ name: 'flag', value: FLAG, domain: new URL(url).hostname, httpOnly: false, secure: false });

console.log(`bot visiting ${urlToVisit}`)
await page.goto(urlToVisit, {
timeout: 3000,
waitUntil: 'domcontentloaded'
});

console.log("bot visited")
await sleep(20000)

console.log("browser close...")
await context.close()
return true;
} catch (e) {
console.error(e);
await context.close();
return false;
}
}
}
48 changes: 48 additions & 0 deletions _examples/compose-type/bot/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const express = require("express")
const app = express();
const path = require("path")
const route = express.Router()
const bot = require("./bot")
const rateLimit = require("express-rate-limit")

app.use(express.urlencoded({ extended: false }))
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.set('trust proxy', () => true)

const limit = rateLimit({
...bot,
handler: ((req, res, _next) => {
const timeRemaining = Math.ceil((req.rateLimit.resetTime - Date.now()) / 1000)
res.status(429).json({
error: `Too many requests, please try again later after ${timeRemaining} seconds.`,
});
})
})


route.post("/", limit, async (req, res) => {
var { url } = req.body;
if (!url) {
return res.status(400).send({ error: "Url is missing." });
}
if (!RegExp(bot.urlRegex).test(url)) {
return res.status(422).send({ error: "URL din't match this regex format " + bot.urlRegex })
}
if (await bot.bot(url)) {
return res.send({ success: "Admin successfully visited the URL." });
} else {
return res.status(500).send({ error: "Admin failed to visit the URL." });
}
});

route.get("/", (_, res) => {
const { name } = bot
res.render("index", { name });
});

app.use("/", route)

app.listen(8000, () => {
console.log("Server running at http://localhost:8000");
});
Loading