Skip to main content
Server-Side Request Forgery is one of the most impactful vulnerability classes in modern web CTFs because it weaponizes the server’s own network position against itself. The target application fetches a URL on your behalf — and if you can control that URL, you can reach internal services, cloud metadata APIs, and admin interfaces that are completely invisible from the outside internet. This writeup walks through a realistic SSRF challenge where you escalate from a simple URL parameter to reading an internal flag file, bypassing filter protections along the way.

Challenge Background

The challenge presents a web application at http://target.ctf that offers an “image preview” feature: you supply a URL, and the server fetches the image and displays it on the page. The feature is at /preview?url=. The flag is stored on an internal admin service running on 127.0.0.1:8080 at the path /flag. The application has a basic SSRF filter that blocks naive 127.0.0.1 and localhost inputs — so you’ll need to bypass it. The server also runs on AWS EC2, which means the metadata endpoint 169.254.169.254 is a secondary target of interest.

Attack Flow

1

Identify the SSRF Vector

Start by confirming that the application actually makes server-side requests. Submit your own server’s URL as the url parameter:
Your server receives an incoming request from target.ctf’s IP address — not from your browser. This confirms the server itself is making the request. The vulnerability is real.Also probe other parameters in the application. SSRF hides in any feature that accepts a URL or hostname: webhook endpoints, PDF generators, file import fields, social media preview fetchers, and XML parsers (via XXE). Don’t limit your search to the most obvious input.
2

Probe Internal Services

With SSRF confirmed, point the server at localhost to discover internal services. Start with common ports:
The naive 127.0.0.1 and localhost attempts return an error: “Blocked: internal addresses are not allowed.” The filter is active. Move on to bypass techniques.While the filter is blocking localhost, test whether other private ranges are accessible:
Note response size differences. A response with content is a live service.
3

Read the AWS Metadata Endpoint

Since the challenge runs on EC2, the metadata service at 169.254.169.254 is a high-value target. It exposes IAM credentials, instance identity, and sometimes secrets injected at launch time.
The application fetches the metadata endpoint and returns the response body in the page. You see:
Follow the iam/ path to enumerate attached roles and extract temporary credentials. Even if the flag isn’t in the metadata directly, IAM credentials might let you access an S3 bucket or other service where the flag lives.
AWS IMDSv2 (the newer metadata service version) requires a PUT request to first obtain a session token before making GET requests. If your SSRF fetches via GET only, IMDSv2 will block you. However, many CTF challenges deliberately run IMDSv1 for simplicity. Check which version is active by observing whether your initial metadata request succeeds.
4

Bypass the SSRF Filter

The application blocks 127.0.0.1 and localhost by string matching. Use alternative representations that resolve to the same address but evade the filter:
Try each one until the filter doesn’t catch it:
The hex-encoded version http://0x7f000001/flag bypasses the string filter. The server resolves it to 127.0.0.1 at the OS level and fetches the internal admin service. The response body rendered on the page contains:
Flag captured.
5

Chain SSRF With Internal Services

With the filter bypass confirmed, enumerate other paths on the internal service to look for additional attack surface. Reach the admin panel using the same hex-encoded bypass with an explicit port:
The page returns an HTML dashboard. Probe further paths for anything that accepts input you can influence. If you find an endpoint that executes commands or reads arbitrary files, you can chain SSRF with that secondary vulnerability to escalate impact — for example, reading /etc/passwd or other sensitive files on the server:
The SSRF → internal service → secondary vulnerability chain is how straightforward information-disclosure escalates into full server compromise. Enumerate every path on every internal service you reach.

Filter Bypass Techniques Reference

Many SSRF filters perform simple string matching against a blocklist. The same IPv4 address can be represented in multiple formats that all resolve identically at the OS level:
Test all variants systematically. Filters that block 127.0.0.1 and localhost frequently miss hex, octal, and decimal encodings.
DNS rebinding attacks a two-phase filter that first resolves the hostname to check if it’s internal, then makes the actual request. If there’s a delay between the check and the fetch, you can serve a benign external IP during the check and switch your DNS record to 127.0.0.1 for the actual fetch.The attack flow:
  1. Register evil.attacker.com with an extremely short TTL (0 seconds).
  2. Initially resolve evil.attacker.com to your real external IP (passes the filter check).
  3. The server validates the IP, sees it’s external, allows the request.
  4. Between validation and the actual HTTP fetch, flip your DNS to return 127.0.0.1.
  5. The server re-resolves the hostname (TTL expired) and connects to localhost.
Tools like singularity automate DNS rebinding attacks. In CTF contexts, this technique is more commonly described in challenge write-ups than required in practice, but understanding it is essential for harder challenges.
If the filter validates the URL before the request but doesn’t follow redirects carefully, you can use an open redirect on an allowed domain to pivot to an internal address.
Then submit:
The filter sees attacker.com (allowed), but the server follows the 301 redirect to 127.0.0.1. This works when the filter checks the initial URL but not subsequent redirect destinations.
Beyond HTTP, try alternative URL schemes that may be supported by the underlying request library:
Python’s urllib, PHP’s file_get_contents, and curl all support different subsets of URL schemes. The gopher:// scheme is particularly powerful — it lets you send arbitrary TCP payloads to internal services, enabling interaction with Redis, memcached, and even crafting raw HTTP requests with custom headers.

Probing Internal Services Systematically

When you have SSRF but don’t know what’s running internally, scan the common service ports:
Differences in response time (slow = port open but no HTTP), response size, or status code distinguish open ports from closed ones.

Key Takeaways

  • SSRF lives in any URL input. Preview features, webhooks, image fetchers, XML imports — check them all for server-side request behavior by pointing them at your own server first.
  • The metadata endpoint 169.254.169.254 is always your first target on cloud challenges. It requires no filter bypass and frequently contains credentials or secrets.
  • String-matching filters are almost always bypassable. Learn all the IP encoding alternatives and test them systematically.
  • Think about what the server can reach, not what you can reach. SSRF is about the server’s network position — internal services, private subnets, and link-local addresses.
  • Chain SSRF with other vulnerabilities. SSRF reaching an internal service with its own vulnerabilities (command injection, another SQLi, file read) is how you escalate from information disclosure to full compromise.
Last modified on July 23, 2026