Home > Writeups > WHAMazon! Web 5 - Neural Backdoor

WHAMazon! Web 5 - Neural Backdoor

Chaining GitHub source code OSINT to discover a hidden SSRF endpoint, then using it to proxy requests to an internally-restricted AI core API.

Neural Backdoor

Challenge Description

The AI's core is isolated from external networks. But sometimes, the AI needs to look outside. And sometimes, it can be convinced to look somewhere else entirely.

Flag: Raptor{flag5_s3rv3r_s1d3_r3qu3st_f0rg3ry_ssrf}


Following Prior Recon

"AI's core" was another immediate callback to Web 1: /api/internal/ai-core was listed in robots.txt. Visiting it directly:

{
  "message": "AI Core access restricted to internal network only.",
  "hint": "This endpoint is only accessible from within the WHAMazon infrastructure."
}

The endpoint validates the request origin and only responds to internal traffic. We need to make the server call it on our behalf, that's SSRF.


First SSRF Attempt

Web 3 showed us that the /seller product form accepts an image URL. If the server fetches that URL server-side, it might be possible to point it at localhost instead. Submitted a new product listing with:

http://localhost:5000/api/internal/ai-core

as the image URL and checked the browser console: NS_ERROR_CONNECTION_REFUSED.

The connection error was coming back client-side, meaning the image URL was being resolved in the browser, not fetched server-side. The product form's image field wasn't the SSRF vector we needed.


Finding the Real Endpoint via GitHub OSINT

Fuzzing /api, /api/internal, and /api/seller with ffuf came up empty, no new endpoints surfacing. Back to OSINT.

Web 2 already pointed us to the challenge author's public GitHub repo. This time instead of seed scripts, I dug into the server routing code. Pulling up /server/routes.ts and searching for /api/seller revealed a route that hadn't shown up in any fuzzing:

/api/seller/preview-image

With a comment flagging it as an SSRF concern. That's the one.


Exploitation

With the correct endpoint identified, I crafted a fetch call from the browser console to use the server as a proxy:

fetch('/api/seller/preview-image', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({url: 'http://localhost:5000/api/internal/ai-core'})
})
.then(r => r.json())
.then(d => console.log(d))

The server made the request on our behalf from inside the infrastructure, bypassing the IP restriction. The response came back including the flag:

{
  "emergency_shutdown": "Raptor{flag5_s3rv3r_s1d3_r3qu3st_f0rg3ry_ssrf}"
}

Why This Works

SSRF (Server-Side Request Forgery) tricks the server into making outbound HTTP requests to destinations specified by the attacker. Because the request originates from the server itself, it bypasses controls that rely on the source IP like the internal network only check on /api/internal/ai-core.

The key difference from the failed Web 3 attempt: the product form's image field rendered the URL client-side in the browser. The /api/seller/preview-image endpoint actually fetched the URL server-side, which is what made SSRF possible.

In a real-world scenario this kind of endpoint can be used to reach cloud metadata services (http://169.254.169.254/), internal databases, admin panels, or any other service bound to localhost or a private network.


Key Takeaways

This challenge is a good example of how recon compounds across a CTF. The path here was:

  • Web 1robots.txt reveals /api/internal/ai-core exists
  • Web 2 → GitHub OSINT establishes the repo as a reliable source of hidden routes
  • Web 3 → Identifies the /seller form accepts URLs (wrong vector, but right track)
  • Web 5 → GitHub OSINT again surfaces /api/seller/preview-image, the actual SSRF vector

None of these challenges existed in isolation. Keeping notes and revisiting prior recon is often what separates a stuck solve from a clean one.

For SSRF mitigations: validate and allowlist outbound request destinations server-side, block requests to loopback addresses and private IP ranges, and avoid exposing URL-fetching functionality to unauthenticated users where possible.

< Back to All Writeups