World Wide CTF 2024

Guessy CTF Solver

Web

View on GitHub

Analysis

In this problem we receive the code for an Express.JS API with a single endpoint: /hack. This endpoint received a URL along with paths that will be loaded using the happy-dom library and will be searched for flags following the format PREFIX{...} (by default wwf{...}).

The API restricts its use to the domain https://fake-easy-chall.wwctf.com, meaning that we would be restricted to investigating paths on this domain. This website also only returns fake flags, whichever the path may be.

Finally, the problem statement gives us the hint that the flag we are looking for is in "/flag.txt". This, we quickly find out, does not refer to a URL path. Leaving us to believe that this is a file on disk.

Solution

The first thing we notice is that the URL to be analyzed is built using the new URL(...) constructor, which takes a path and a base and combines the two. However, if the path is itself a full URL, then the base is ignored. This means that we can send the url parameter of the request as https://fake-easy-chall.wwctf.com, to bypass the system's restriction, but send a full URL as part of our path to make the system investigate whatever URL we want.

Despite being able to investigate any URL, there is no clear location that we should explore. By digging around a bit we can find that the happy-dom extension, used for loading the webpage, recently had an issue created about a RCE vulnerability. We could guess that the server is running a vulnerable version of this library, meaning that we could use this exploit to read the file on disk.

To serve the exploit we can start an HTTP server using Python (python3 -m http.server 8000) and use a tool like ngrok to create a publicly available endpoint to serve the exploit file. The file attempts to make a request to the same server that we are using to serve the exploit file, but appending the result of the RCE to the URL. That means we can exfiltrate content by reading the requests being made to our server.

A last hurdle to overcome is that if we try to execute a command like cat /flag.txt, that will get escaped into cat%20/flag.txt due to URL encoding. If this is executed, we get a Command not found error. To overcome that, we can make use of an environment variable whose value is, by default, a single space: $IFS. Therefore, the command we pass to the RCE is cat$IFS/flag.txt. By reading the log of requests made to the server, we get the flag.

Last Updated in 2025
Halifax, NS
Canada