FlawOpen

flawopen.com/Incidents/capital-one-ssrf-imds-july-2019

● Capital One · CWE-918 · July 2019 · Kritisch
Sicherheitsforschung · FlawOpen

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]

💡 Einfache Erklärung (ELI5)

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

2019-03-22

Laut Strafanzeige nutzte die Beschuldigte am 22. und 23. März SSRF, um die Zugangsdaten der Firewall-Rolle zu erhalten und Capital-One-S3-Daten zu kopieren.[10], [2]

2019-07-17

Ein externer Forscher meldet die offengelegten Daten über Capital Ones Programm für verantwortungsvolle Offenlegung.[2]

2019-07-29

Capital One gibt den Vorfall bekannt, und das FBI nimmt in Seattle eine Verdächtige fest.[1]

Schritt-für-Schritt Angriffsablauf

Schritt 1

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]

Schritt 2

Der Metadatendienst gibt Zugangsdaten heraus

Laut Anzeige erreichte die Weiterleitung den IAM-Rollen-Zugangsdatenpfad des Instanz-Metadatendienstes. Da IMDSv1 kein Sitzungstoken verlangte, konnte die Anfrage temporäre Zugangsdaten der zugeordneten Rolle zurückgeben.[10], [8]

Schritt 3

Die Rolle darf viel zu viel lesen

Laut Anzeige umfassten die Zugangsdaten die Berechtigungen der Rolle, darunter das Auflisten und Lesen von S3-Buckets mit Kundendaten.[10], [8]

Schritt 4

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]

VERWUNDBARE IMPLEMENTIERUNG
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
GEHÄRTETER SICHERHEITS-PATCH
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

Quellen