Zum Inhalt springen
Categoria: Pentest8 Min. Lesezeit

SSRF Entmystifiziert: Cloud Metadata im Lokalen AWS-Lab Ausnutzen

Por Lucas Andrade ·

Ethische SSRF-Reproduktion gegen IMDS mit LocalStack, echten Payloads, simuliertem Credential-Diebstahl und definitiver Absicherung uber IMDSv2.

SSRF Entmystifiziert: Cloud Metadata im Lokalen AWS-Lab Ausnutzen
In diesem Artikel

Der Endpunkt 169.254.169.254 hat mehr SRE-Karrieren verbrannt als jede andere IP in der Cloud-Geschichte. Capital One verlor 2019 rund 100 Millionen Datensatze, weil eine fehlkonfigurierte WAF einer Server-Side Request Forgery erlaubte, den Instance Metadata Service zu erreichen und temporare Credentials aus der EC2-Rolle zu ziehen. Jahre spater erhalten wir noch immer Bug-Bounty-Reports mit demselben Muster: Eine App holt ein Bild von einer nutzergelieferten URL, niemand validiert das Ziel, IMDSv1 bleibt aktiv, Game over. Bauen wir diesen Angriff von Grund auf in einem lokalen AWS-Lab mit LocalStack nach, verstehen wir genau, warum IMDSv2 die Rechnung andert, und schliessen mit einer Hardening-Checkliste, die Sie heute ausrollen konnen. Alles lauft auf Ihrer eigenen Maschine, es gibt also kein Ziel ausser Ihrem eigenen Lab.

Was SSRF ist und was der Metadata Service tut#

Server-Side Request Forgery ist eine Bug-Klasse, bei der ein Angreifer das Ziel einer Anfrage kontrolliert, die der Server in seinem Namen stellt. Die Anwendung ist der Confused Deputy: Sie hat Netzwerkposition und Identitat, die dem Angreifer fehlen, und verbindet sich bereitwillig, wohin er zeigt. In AWS ist das wertvollste interne Ziel der Instance Metadata Service (IMDS) unter 169.254.169.254, eine Link-Local-Adresse, die jede EC2-Instanz erreicht. Er exponiert Instanzdaten und, entscheidend, temporare IAM-Rollen-Credentials unter /latest/meta-data/iam/security-credentials/. Eine SSRF, die ihn erreicht, verwandelt ein harmloses Bild-Fetch in Credential-Diebstahl, weshalb er das folgenreichste Ziel im Cloud-Pentesting ist.

Bedrohungskontext: warum das immer wieder passiert#

Das Muster wiederholt sich, weil der verwundbare Code vernunftig aussieht. Ein Produkt muss ein Nutzer-Avatar holen, eine Linkvorschau rendern oder einen Webhook proxen, also akzeptiert es eine URL und ruft sie server-side auf. Der Entwickler denkt an Bilder, nicht an einen Link-Local-Metadata-Endpunkt, der Cloud-Credentials ausgibt. Zugleich blieb IMDSv1 auf alteren Instanzen jahrelang Standard, sodass der Credential-Tresor eine unvalidierte Anfrage entfernt lag. Dieselbe Form taucht in Pentest von REST und GraphQL APIs: Technische Checkliste fur legales Bug Bounty auf, wann immer Webhook- oder Image-Proxy-Endpunkte interne URLs ohne Allowlist akzeptieren. Das Muster zu verstehen, ist, was Sie es in einem Ziel finden und, wichtiger, in Ihrem eigenen Code toten lasst.

Das Lab mit LocalStack bauen#

Zuerst die Umgebung. Ziehen Sie LocalStack Pro 4.x via docker-compose mit aktivem ec2, iam, sts und s3 hoch, plus einen Flask-Container auf Port 5000 mit einer bewusst verwundbaren Fetch-Image-API. Der verwundbare Code ist etwa achtzehn Zeilen: Er empfangt ?url=, ruft requests.get ohne Validierung auf und gibt den Body zuruck. Um IMDS in LocalStack zu simulieren, nutzen Sie den ec2-Metadata-Mock oder einen dedizierten Mock, an 169.254.169.254 uber eine Network Namespace gebunden. Wer maximale Wiedergabetreue will, nutzt eine echte t3.micro fur ein paar Cent pro Stunde, aber LocalStack deckt rund 95% des Lernens ohne Kreditkarte. Das Basis-Container-Setup, das Sie hier wiederverwenden, ist in Web-Pentest von Null: Ein Sicheres Lab mit DVWA, Juice Shop und Burp Suite Bauen beschrieben.

IMDSv1 ausnutzen, Schritt fur Schritt#

Mit dem laufenden Lab ist der klassische IMDSv1-Payload buchstablich ein GET. Fangen Sie in Burp die App-Anfrage ab und tauschen Sie den Parameter url gegen http://169.254.169.254/latest/meta-data/iam/security-credentials/. Die Antwort leakt den angehangten Rollennamen, sagen wir app-server-role. Dann fragen Sie http://169.254.169.254/latest/meta-data/iam/security-credentials/app-server-role ab und erhalten JSON mit AccessKeyId, SecretAccessKey und Token. Exportieren Sie diese als Umgebungsvariablen, fuhren Sie aws sts get-caller-identity --endpoint-url http://localhost:4566 aus, und Sie sind als die Anwendung authentifiziert. Das ist der Moment, in dem Blue Teams wahrend der Demo von den Stuhlen springen, weil ein einziger unvalidierter Parameter gerade zur vollen Rollenidentitat wurde.

Eskalation mit gestohlenen Credentials#

Die Eskalation hangt davon ab, was die Rolle darf. In unserem Lab hangen wir eine bewusst permissive Policy mit s3:* und iam:ListRoles an. Mit den gestohlenen Creds enthullt aws s3 ls einen Bucket backups-prod-2026, aws s3 cp s3://backups-prod-2026/db.dump . zieht den Dump, und aws iam list-attached-role-policies mappt den Pfad zur Privilege Escalation via PassRole. Tools wie Pacu, ScoutSuite und cloudfox automatisieren diese Post-Compromise-Enumeration, sodass Sie den Blast Radius schnell sehen. Zeitstempeln Sie jedes Kommando, denn ein Bug-Bounty-Report ohne reproduzierbaren Proof of Concept zahlt null, und eine saubere Timeline verwandelt einen Fund in einen triagierten, bezahlten Report. Wer nach dem Credential-Grab ins interne Pivoting will, findet in Pivoting mit Chisel und Ligolo-ng: Segmentierte Netze im Pentest-Lab die nachste Station.

Warum IMDSv2 den Angriff bricht#

IMDSv2 bricht den klassischen Angriff, indem es eine Token-Session verlangt. Der korrekte Ablauf ist ein PUT an http://169.254.169.254/latest/api/token mit Header X-aws-ec2-metadata-token-ttl-seconds: 21600, dann ein GET mit Header X-aws-ec2-metadata-token. Eine SSRF, die nur ein GET macht, ohne Kontrolle uber Methode oder Header, bleibt einfach stehen: Sie kann kein Token holen, also keine Credentials lesen. Erzwingen Sie IMDSv2 mit aws ec2 modify-instance-metadata-options --http-tokens required --http-put-response-hop-limit 1. Der Hop-Limit von 1 ist entscheidend: Er hindert Bridge-Network-Container daran, IMDS uber das Host-NAT zu erreichen, und schliesst einen haufigen Container-zu-Metadata-Pfad. Kombinieren Sie das mit einem Egress-Block von 169.254.0.0/16 in der Security Group, und die App verliert jede Route zum magischen Endpunkt.

Defense in Depth jenseits von IMDS#

Die Verteidigung endet nicht bei IMDS. Validieren Sie URLs in der Anwendung und weisen Sie 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 und fd00::/8 ab, und losen Sie den Hostnamen vor der Anfrage auf, um DNS-Rebinding zu schlagen, dann pinnen Sie diese aufgeloste IP fur die eigentliche Verbindung. Nutzen Sie eine gepruftte Library wie ssrf-protect oder implementieren Sie es mit getaddrinfo plus Per-Family-IP-Checks; eine naive String-Blocklist wird mit Dezimal-IPs, IPv6-mapped-Adressen oder Redirects trivial umgangen. Trimmen Sie Rollenrechte auf das Minimum, bevorzugen Sie IRSA auf EKS, sodass Pods scoped kurzlebige Credentials bekommen, aktivieren Sie GuardDuty fur anomale Credential-Nutzung und fahren Sie Scanner wie Prowler regelmassig. 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.

Detektion und Monitoring#

Nehmen Sie an, dass die Pravention gelegentlich versagt, und instrumentieren Sie fur Detektion. Credential-Diebstahl via IMDS hat ein Verraterzeichen: dieselbe IAM-Rolle authentifiziert sich plotzlich von einer IP ausserhalb Ihrer Infrastruktur. GuardDutys Finding UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration ist genau dafur gebaut, also aktivieren Sie es und leiten Sie es an einen On-Call-Kanal. Auf Anwendungsebene loggen Sie jede ausgehende URL, die der Fetcher auflost, und alarmieren bei jeder Anfrage, deren Ziel in einem privaten oder Link-Local-Bereich landet, denn ein legitimes Avatar-Fetch zielt nie auf 169.254.169.254. Fuhren Sie diese Logs in dieselbe Pipeline wie Ihre anderen Detections, sodass ein SSRF-Versuch zu einem gepageten Alarm wird statt zu einer Zeile, die niemand liest.

Haufige Fallstricke#

Die wiederkehrenden Fehler verdienen Namen. Teams blockieren den Literal-String 169.254.169.254 und verpassen 2852039166, seine Dezimalform, oder einen angreiferkontrollierten Hostnamen, der darauf auflost. Sie validieren die URL einmal, folgen dann Redirects, die direkt zuruck auf den Metadata Service zeigen. Sie erzwingen IMDSv2 auf neuen Instanzen, lassen aber einen langen Schwanz alter auf optional. Sie setzen Hop-Limit, vergessen aber die Egress-Regel, oder umgekehrt. Und sie geben der Instanzrolle weit mehr, als sie braucht, sodass selbst ein kurzer Credential-Leak zur vollen Konto-Kompromittierung wird. Defense in Depth existiert genau deshalb, weil jeder einzelne dieser Punkte irgendwann versagt.

Hardening-Checkliste#

Rollen Sie das heute aus: Fuhren Sie aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,MetadataOptions.HttpTokens]' uber Ihr Inventar aus, und jede Instanz, die optional zuruckgibt, ist der klassischen SSRF ausgesetzt; erzwingen Sie required massenhaft via SSM Automation Document; setzen Sie Hop-Limit auf 1; fugen Sie einen Egress-Block fur 169.254.0.0/16 hinzu, wo machbar; auditieren Sie Rollen auf *:*-Policies und trimmen Sie sie; validieren und pinnen Sie ausgehende URLs in der App mit einer gepruftten Library; aktivieren Sie GuardDuty und leiten Sie das Exfiltration-Finding an On-Call; und fugen Sie einen E2E-Test in CI hinzu, der versucht, 169.254.169.254 vom App-Container zu erreichen, und den Build bei einer 200-Antwort fehlschlagen lasst.

FAQ: Reicht IMDSv2 allein, um SSRF zu stoppen?#

IMDSv2 schlagt den spezifischen SSRF-zu-Credential-Diebstahl-Pfad, wenn die SSRF auf einfache GETs beschrankt ist, was die grosse Mehrheit realer Falle abdeckt. Es ist kein vollstandiger SSRF-Fix. Ein Angreifer, der Methoden und Header kontrollieren kann oder zu anderen internen Diensten ausser IMDS pivotiert, hat weiter Spielraum. Behandeln Sie IMDSv2 als verpflichtende, hochwertige Kontrolle und fugen Sie URL-Validierung, Least-Privilege-Rollen und Egress-Restriktionen hinzu, damit der Metadata Service nicht Ihre einzige Verteidigungslinie ist.

FAQ: Kann ich das gefahrlos ohne AWS-Rechnung uben?#

Ja. LocalStack Pro gibt Ihnen EC2, IAM, STS und S3 plus einen Metadata-Mock, was rund 95% des Lernens ohne Cloud-Ausgaben und ohne Risiko reproduziert, etwas anzufassen, das Ihnen nicht gehort. Halten Sie die verwundbare Flask-App und den Metadata-Mock strikt auf einem lokalen Docker-Netz. Wenn Sie irgendwann maximale Wiedergabetreue fur einen speziellen Edge Case wollen, kostet eine echte t3.micro ein paar Cent pro Stunde, aber richten Sie dieses Tooling nie auf Infrastruktur, die Sie nicht testen durfen.

Fazit#

Praktisches Fazit: Es dauert etwa siebzehn Minuten, das Capital-One-Muster im Lab zu reproduzieren, und es dauert dieselben siebzehn Minuten, das Loch in Produktion zu schliessen. Fuhren Sie die Inventar-Query jetzt aus, erzwingen Sie IMDSv2 uberall, trimmen Sie die uberprivilegierten Rollen, validieren Sie ausgehende URLs in Ihren Apps und fugen Sie den CI-Test hinzu, der den Build fehlschlagen lasst, wenn der App-Container 169.254.169.254 erreicht. SSRF gegen Cloud-Metadata ist nicht exotisch; es ist ein Default-Konfigurationsproblem mit einem gut verstandenen Fix. Die Teams, die gebreacht werden, sind nicht die ohne Wissen, sondern die, die nie die Query gefahren haben.

Related posts

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly