flawopen.com/Incidents/capital-one-ssrf-imds-july-2019
Capital One: SSRF und AWS-IMDSv1-Zugangsdaten
Laut Bundesbeschwerde ermöglichte eine falsch konfigurierte WAF SSRF bis zu AWS IMDSv1 und legte temporäre Rollen-Zugangsdaten sowie S3-Daten von etwa 106 Mio. Menschen offen. Tokens verlangen und Rollen begrenzen.[10], [2]
Die DOJ-Strafanzeige behauptete eine solche Kette: Stellen Sie sich eine Empfangskraft vor, die Dokumente von den Adressen holt, die Sie nennen. Eine Anforderungsweiterleitung kann dazu führen, dass jemand sie in ein internes Büro schickt. Dort kann sie einen zeitlich begrenzten Zugangsausweis für die Workload erhalten; der Ausweis öffnet nur die Räume, die der zugehörigen Rolle erlaubt sind. Der Fehler war die Annahme, nur Beschäftigte könnten das Büro erreichen, obwohl sich die Empfangskraft dorthin lenken ließ.[10], [8]
Kernkonzepte & Begriffe
SSRF- Server-Side Request Forgery (
CWE-918): einen Server dazu bringen, eine vom Angreifer gewählte Anfrage zu senden, die dann die Netzwerkposition und das Vertrauen des Servers mitbringt.[9] Web Application Firewall- Ein Filter vor einer Webanwendung. Die Strafanzeige behauptete, die falsch konfigurierte Capital-One-WAF habe Anfragen an interne Adressen weitergeleitet.[10]
IMDSv1- Wenn IMDSv1 aktiviert ist, benötigen Metadatenanfragen kein Token. Der Pfad für die Sicherheitszugangsdaten einer IAM-Rolle gibt temporäre Zugangsdaten dieser Rolle zurück.[7], [8]
IMDSv2- IMDSv2 verwendet ein Sitzungstoken, das per PUT-Anfrage abgerufen wird. Setzen Sie
HttpTokens=required, damit tokenlose IMDSv1-Anfragen abgewiesen werden; das blockiert viele SSRF-Relays, die nur ein einfaches GET senden können, ist aber kein vollständiger SSRF-Schutz.[7], [6] IAM-Rollen-Zugangsdaten- Temporäre AWS-Schlüssel, die einer Instanz ausgestellt werden. Was die Rolle darf, darf jeder, der die Schlüssel besitzt, bis sie ablaufen.[8]
Framework-Zuordnungen
- CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-918
- D3-OTF Filterung des ausgehenden Datenverkehrs — Die in diesem Leitfaden beschriebene Beschränkung des ausgehenden Netzwerkverkehrs begrenzt die für den Dienst oder Host erreichbaren Ziele.
Vorfall-Zeitstrahl
Ein externer Forscher meldet die offengelegten Daten über Capital Ones Programm für verantwortungsvolle Offenlegung.[2]
Capital One gibt den Vorfall bekannt, und das FBI nimmt in Seattle eine Verdächtige fest.[1]
Schritt-für-Schritt Angriffsablauf
Die Firewall leitet eine präparierte Anfrage weiter
Die Strafanzeige behauptet, die falsch konfigurierte WAF habe sich dazu bringen lassen, Anfragen an vom Angreifer gewählte Adressen zu senden, auch an interne.[10]
Die Daten fließen massenhaft ab
Kopiert wurden Daten aus Kreditkartenanträgen von 2005 bis Anfang 2019: rund 100 Millionen Menschen in den USA und 6 Millionen in Kanada, darunter etwa 140.000 US-Sozialversicherungsnummern und 80.000 verknüpfte Bankkontonummern.[2]
Quellcode: Verwundbar vs. Sicher
Illustrativer Flask-Code, nicht die Konfiguration von Capital One. Die Host-Allowlist ist die primäre Anwendungskontrolle. Der erforderliche Egress-Proxy muss die Richtlinie zur Verbindungszeit auf die aufgelöste Adresse anwenden, private und Link-Local-Bereiche einschließlich des Metadatendienstes sperren und die Prüfungen für jede Anfrage und Wiederholung erneut anwenden; prüfen Sie dieses Verhalten in der Proxy-Konfiguration. Weiterleitungen werden nicht verfolgt. Eine getrennte Auflösung vor dem Verbindungsaufbau ließe ein DNS-Rebinding-Rennen offen.[9], [5], [6]
import requests
from flask import Flask, request
app = Flask(__name__)
@app.get("/fetch")
def fetch():
# Der Server ruft jede vom Aufrufer angegebene URL ab.
url = request.args["target"]
resp = requests.get(url, timeout=5)
return resp.text
from urllib.parse import urlsplit
import requests
from flask import Flask, abort, request
app = Flask(__name__)
ALLOWED_HOSTS = {"images.example-cdn.com", "api.partner.example"}
EGRESS_PROXY = "http://egress-proxy.internal:3128"
# Dieser Proxy muss die Zielrichtlinie nach der DNS-Auflösung durchsetzen.
@app.get("/fetch")
def fetch():
parts = urlsplit(request.args.get("target", ""))
if parts.scheme != "https" or parts.hostname not in ALLOWED_HOSTS:
abort(400, "destination not allowed")
if parts.port not in (None, 443) or parts.username or parts.password:
abort(400, "destination not allowed")
resp = requests.get(parts.geturl(), timeout=(2, 5), allow_redirects=False, proxies={"https": EGRESS_PROXY}, trust_env=False)
if resp.is_redirect:
abort(502, "upstream redirect refused")
return resp.text
Checkliste für Engineering & Systemsicherheit
- ✓Leiten Sie URL-Abrufe über einen Egress-Proxy und setzen Sie Host-Allowlist und IP-Bereichsrichtlinie an der Verbindungsgrenze durch: Verbinden Sie nur mit der geprüften Adresse und wenden Sie die Richtlinie auch auf Wiederholungen an. Deaktivieren Sie Weiterleitungen oder prüfen Sie jeden Hop erneut; nur den Text 169.254.169.254 zu sperren reicht nicht.[9], [4]
- ✓Setzen Sie
HttpTokens=requiredfür jede betroffene Instanz und prüfen Sie bestehende Instanzen, da Kontostandardwerte nicht automatisch jede Instanz aktualisieren. Wählen SieHttpPutResponseHopLimitpassend zum Netzwerkpfad der Workload; AWS warnt, dass der Wert 1 in Containern Probleme verursachen kann. Die Tokenpflicht weist IMDSv1-Anfragen ab; das Hop-Limit ist eine separate Netzwerkeinstellung und blockiert nicht selbst ein tokenloses GET.[6], [7] - ✓Laut Strafanzeige legte der SSRF-Pfad die Instanzrolle offen. Beschränken Sie diese Rolle auf die für die Workload nötigen Aktionen und Ressourcen, damit offengelegte Zugangsdaten keinen sachfremden S3-Zugriff erlauben.[10], [8]
- ✓FlawOpen-Erkennungshinweis: Alarmieren Sie bei Verwendung temporärer Rollen-Zugangsdaten außerhalb des Instanznetzes und untersuchen Sie den Workload- und Cloud-Audit-Kontext.
- ✓Behandeln Sie im Code-Review jeden Pfad, in dem Nutzer eine vom Server abgerufene URL beeinflussen, wie einen, in dem sie eine SQL-Abfrage beeinflussen, und verlangen Sie einen Allowlist-Test dafür.[9], [5]
Quellen
- US-Justizministerium — Tech-Beschäftigte in Seattle wegen Datendiebstahls bei großem Finanzdienstleister festgenommen (29. Juli 2019)
- Capital One — Informationen zum Cybersicherheitsvorfall 2019
- OCC — Zivilstrafe gegen Capital One wegen des Vorfalls 2019 (August 2020)
- Warum ist SSRF in Cloud-Umgebungen so gefährlich?
- Kann fetch() eine SSRF verursachen?
- AWS — Configure the Instance Metadata Service options
- AWS — Use the Instance Metadata Service to access instance metadata
- AWS — Retrieve security credentials from instance metadata
- OWASP — Server Side Request Forgery Prevention Cheat Sheet
- DOJ — United States v. Paige Thompson, criminal complaint (29 July 2019)