While exploring the scope of a large bug bounty program, I came across a promotional microsite for one of the platform’s shows. The main site appeared to be nothing more than a static FAQ page, so I started with the usual enumeration.

There wasn’t much to see. A few subdomains such as www, staging, and test, but nothing particularly interesting.

Out of curiosity, I decided to take a closer look at the staging environment. Unlike the main site, it exposed a small interactive experience that allowed users to walk through the streets of the city where the series takes place. It was essentially a miniature Google Maps-like environment and, surprisingly, quite well done.

Most of the functionality seemed to be handled entirely client-side through an API hosted on target-api.example.net, which made me think there probably wasn’t much attack surface available.

After wandering around the virtual city for a while, I stumbled upon an interesting feature. Users could leave handwritten notes on a mural for other visitors to read.

Creating a note generated a request to:

POST /items/postits HTTP/2
Host: target-api.example.net
Content-Type: application/json

{"text":"asfffvbcvc"}

The functionality worked as expected. I could create as many notes as I wanted, but there was no option to edit or delete them.

At that point, I started wondering what was actually behind target-api.example.net.

One thing caught my attention immediately. Every response from the server contained the following header:

X-Powered-By: Directus

I had never encountered Directus before, so naturally my next question was:

What exactly is Directus?

As it turns out, Directus is an open-source real-time API and application framework used to manage SQL databases through an admin panel and automatically generated APIs.

Which immediately led to the next question:

Does it have any CVEs?

Of course it did.

At the time, the most recent one was CVE-2023-26492, an SSRF vulnerability affecting Directus.

After confirming that the target was indeed vulnerable, exploitation turned out to be straightforward.

Although the public advisory for CVE-2023-26492 describes exploiting the vulnerability through a DNS rebinding attack, the affected deployment in this case did not require DNS rebinding or authentication. A direct request to the vulnerable endpoint was sufficient to retrieve server-side responses, suggesting the instance was exposed under a more permissive configuration than the scenario described in the advisory.

Technical Details

The vulnerable endpoint was:

POST /files/import

By supplying an arbitrary URL, the server would fetch the resource and store the response inside the publicly accessible /assets/ directory.

Sending the following request caused the server to request the AWS metadata endpoint: The response contained the following filename:

{
    "filename_disk": "900469e9-d9c9-4c1e-a20f-b7e379aced9b.txt"
}

Retrieving /assets/900469e9-d9c9-4c1e-a20f-b7e379aced9b.txt on target-api.example.net revealed the contents returned by the internal request, confirming the SSRF: Besides accessing internal resources such as AWS metadata, this behavior also opened the door to Stored XSS. By importing malicious .svg or .html files, arbitrary JavaScript could be hosted inside the application’s assets directory and served to other users.

Impact

The vulnerability allowed attackers to perform arbitrary server-side requests and read their responses through the public assets directory.

Potential impacts included:

  • Access to internal AWS metadata.
  • Exposure of internal network resources.
  • Interaction with otherwise inaccessible endpoints.
  • Persistent hosting of attacker-controlled files.
  • Stored XSS through malicious HTML or SVG payloads.

Unfortunately for me, the vulnerable API itself was technically out of scope. Nevertheless, the report was accepted and “fixed”.

Rather than patching the vulnerable instance, the affected microsite and API were taken offline.

No bounty this time, but at least I got some points… Until next time!