SSRF Entmystifiziert: Cloud Metadata im Lokalen AWS-Lab Ausnutzen
Ethische SSRF-Reproduktion gegen IMDS mit LocalStack, echten Payloads, simuliertem Credential-Diebstahl und definitiver Absicherung uber IMDSv2.
Der Endpunkt 169.254.169.254 hat mehr SRE-Karrieren verbrannt als jede andere IP in der Cloud-Geschichte. Capital One verlor 2019 100 Millionen Datensatze, weil eine fehlkonfigurierte WAF eine SSRF zum Instance Metadata Service durchliess, die temporare Credentials der EC2-Role abgriff. Sieben Jahre spater sehen wir immer noch Bug-Bounty-Reports mit demselben Muster: App ladt ein Bild von einer user-supplied URL, niemand validiert das Ziel, IMDSv1 bleibt aktiv, Spiel vorbei. Reproduzieren wir den Angriff von Null in einem lokalen AWS-Lab mit LocalStack, verstehen warum IMDSv2 die Spielregeln andert, und schliessen mit einer Hardening-Checkliste die du heute ausrollst.
Erst die Umgebung. Starte LocalStack Pro 4.x via docker-compose mit aktiven Services ec2, iam, sts und s3, plus einen Flask-Container auf Port 5000 mit einer verwundbaren fetch-image API. Der Code hat achtzehn Zeilen: empfangt ?url=, ruft requests.get ohne Validierung auf, gibt den Body zuruck. Um IMDS innerhalb von LocalStack zu simulieren brauchst du das Plugin localstack-ec2-metadata-mock oder einen dedizierten Mock auf 169.254.169.254 via netns. Wer maximale Treue will nutzt ein echtes t3.micro Lab fur zwei Cent pro Stunde, aber LocalStack deckt 95% der Lernkurve ohne Kreditkarte ab. Web-Pentest von Null: Ein Sicheres Lab mit DVWA, Juice Shop und Burp Suite Bauen beschreibt das Basis-Setup verwundbarer Container das du hier wiederverwendest.
Lab steht, der klassische IMDSv1-Payload ist buchstablich ein GET. Aus Burp heraus die App-Request abfangen und den url-Parameter durch http://169.254.169.254/latest/meta-data/iam/security-credentials/ ersetzen. Die Antwort leakt den Namen der angehangten Role, sagen wir app-server-role. Dann liefert GET http://169.254.169.254/latest/meta-data/iam/security-credentials/app-server-role ein JSON mit AccessKeyId, SecretAccessKey und Token. Als Umgebungsvariablen exportieren, aws sts get-caller-identity --endpoint-url http://localhost:4566 laufen lassen, und du bist als die Anwendung authentifiziert. Genau der Moment in dem Blue Teams in der Demo aus dem Stuhl springen.
Die Eskalation hangt von den Berechtigungen der Role ab. Im Lab habe ich absichtlich eine permissive Policy mit s3:* und iam:ListRoles angehangt. Mit gestohlenen Creds: aws s3 ls offenbart ein backups-prod-2026 Bucket, aws s3 cp s3://backups-prod-2026/db.dump zieht den Dump, und aws iam list-attached-role-policies kartiert den Pfad zur Privilege Escalation via PassRole. Tools wie Pacu, ScoutSuite und cloudfox automatisieren diese Post-Compromise-Enumeration. Ahnliche Muster zeigen sich in Pentest von REST und GraphQL APIs: Technische Checkliste fur legales Bug Bounty wenn Webhook- oder Image-Proxy-Endpunkte interne URLs ohne Allowlist akzeptieren. Versehe jedes Kommando mit Zeitstempel, denn ein Bug-Bounty-Report ohne reproduzierbaren PoC zahlt null.
IMDSv2 bricht den Angriff durch eine Token-Session. Der korrekte Ablauf ist PUT http://169.254.169.254/latest/api/token mit Header X-aws-ec2-metadata-token-ttl-seconds: 21600, danach GET mit Header X-aws-ec2-metadata-token. Eine SSRF die nur GET kann, ohne Kontrolle uber Header oder Methode, lauft schlicht ins Leere. Erzwinge IMDSv2 mit aws ec2 modify-instance-metadata-options --http-tokens required --http-put-response-hop-limit 1. Hop-Limit 1 ist entscheidend: es verhindert dass Bridge-Netzwerk-Container IMDS uber das Host-NAT erreichen. Kombiniere mit Egress-Block 169.254.0.0/16 in der Security Group und die App verliert jeden Weg zum magischen Endpunkt.
Defense in Depth endet nicht bei IMDS. Validiere URLs in der App und lehne 169.254.0.0/16, 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fd00::/8 ab und lose den Hostname vor der Anfrage auf um DNS Rebinding zu vereiteln. Nutze eine Library wie ssrf-protect oder implementiere es mit getaddrinfo plus Prufung je IP-Familie. Reduziere Role-Berechtigungen auf das Notwendigste, bevorzuge IRSA auf EKS, aktiviere GuardDuty fur anomale Credential-Nutzung und lasse Scanner wie Prowler regelmassig laufen. Verwandte Web-Techniken finden sich in SQL Injection in der Praxis: Ausnutzen, Erkennen und Mitigieren im Kontrollierten Lab und Modernes XSS: DOM, Stored und Reflected mit Beispielen aus dem Testlabor, die zusammen mit SSRF das haufigste Trio im Corporate Bug Bounty bilden. Wer nach gestohlenen Credentials tiefer in internes Pivoting will, findet in Pivoting mit Chisel und Ligolo-ng: Segmentierte Netze im Pentest-Lab den nachsten Schritt.
Praktischer Takeaway: fuhre aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,MetadataOptions.HttpTokens]' uber dein Inventar JETZT aus. Jede Instanz die optional zuruckgibt ist klassischer SSRF ausgesetzt. Erzwinge required massenhaft via SSM Automation Document, auditiere Roles mit *:* Policies und richte einen E2E-Test im CI ein der versucht 169.254.169.254 aus dem App-Container zu erreichen und bei einer 200-Antwort den Build bricht. Es brauchte siebzehn Minuten um Capital One im Lab zu reproduzieren. Es braucht dieselben siebzehn Minuten um das Loch in Produktion zu schliessen.