Zum Inhalt springen

Server-Side Request Forgery (SSRF)

CWE-918OWASP A10:2021Aktualisiert 29. August 20266 Min. Lesezeit

Server-Side Request Forgery (SSRF) ist eine Schwachstelle, bei der ein Angreifer Ihren Server zwingt, Anfragen an beliebige Adressen zu senden. So erreicht er interne Systeme und Cloud-Dienste, die aus dem Internet niemals erreichbar sein dürften.

Server-Side Request Forgery, kurz SSRF, gehört zu den heimtückischsten Web-Schwachstellen: Der Angreifer steuert nicht Ihren Browser, sondern Ihren eigenen Server. Dieser Beitrag erklärt, was SSRF ist, wie ein solcher Angriff in der Praxis abläuft, was ein Angreifer damit erreichen kann und wie Sie Ihre Anwendung dagegen absichern.

Was ist Server-Side Request Forgery?

Server-Side Request Forgery (SSRF) ist eine Schwachstelle, bei der ein Angreifer Ihren Server dazu bringt, in seinem Auftrag Verbindungen zu einer Adresse aufzubauen, die er selbst wählt. Die Anwendung glaubt, eine legitime Anfrage zu stellen, wirkt in Wahrheit aber als Vermittler zu Orten, die der Angreifer direkt niemals hätte erreichen können.

Stellen Sie sich einen Pförtner vor, der jede Telefonnummer wählt, die ein Besucher auf einen Zettel schreibt. Der Besucher steht draußen und kommt nicht ins Gebäude, doch der Pförtner sitzt drinnen, und kann somit auch interne Nebenstellen anrufen. Bittet der Besucher um “Nebenstelle 1234, den Tresorraum”, so wählt der Pförtner das brav, denn es steht ja auf dem Zettel. Genau diese Vertrauensstellung des Servers im Netzwerk nutzt SSRF aus.

Wie funktioniert ein SSRF-Angriff?

SSRF entsteht überall dort, wo eine Anwendung eine URL oder Adresse aus Benutzereingaben übernimmt und anschließend selbst abruft: ein Webhook, eine “Import per URL”-Funktion, eine Link-Vorschau, ein PDF-Generator oder ein Bild-Proxy. Solange diese Eingabe nicht geprüft wird, bestimmt der Nutzer, zu welcher Adresse der Server eine Verbindung aufbaut.

Verwundbar:

// Bild-Proxy, der jede übergebene Adresse ungeprüft abruft
app.get('/fetch', async (req, res) => {
  const url = req.query.url;
  const response = await fetch(url);
  const body = await response.text();
  res.send(body);
});

Dieser Proxy ruft jede Adresse ab, die im Query-Parameter steht. Ruft ein Angreifer /fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ auf, so fragt der Server den Metadaten-Endpunkt des Cloud-Anbieters ab und liefert die temporären Zugangsschlüssel in der Antwort zurück. Eine Adresse wie http://localhost:6379 öffnet ebenso mühelos die interne Redis-Datenbank, und file:///etc/passwd liest bei Bedarf lokale Dateien aus.

Sicher:

import dns from 'node:dns/promises';

const ALLOWED_HOSTS = new Set(['images.example.com', 'cdn.example.com']);

function isPrivate(ip) {
  return /^(10\.|127\.|169\.254\.|192\.168\.|::1|fc00:|fe80:)/.test(ip)
    || /^172\.(1[6-9]|2\d|3[01])\./.test(ip);
}

app.get('/fetch', async (req, res) => {
  let target;
  try { target = new URL(req.query.url); }
  catch { return res.status(400).send('Ungültige URL'); }

  if (target.protocol !== 'https:') return res.status(400).send('Nur https');
  if (!ALLOWED_HOSTS.has(target.hostname)) return res.status(403).send('Host nicht erlaubt');

  const { address } = await dns.lookup(target.hostname);
  if (isPrivate(address)) return res.status(403).send('Blockiert');

  const response = await fetch(target, { redirect: 'error' });
  res.send(await response.text());
});

Die sichere Variante dreht drei Hähne zugleich zu. Zuerst wird die Eingabe als echte URL geparst und auf https beschränkt. Danach muss der Hostname auf einer ausdrücklichen Allowlist stehen: nur was Sie vorab freigeben, kommt durch. Zuletzt wird der Hostname zu einer IP-Adresse aufgelöst und gegen private sowie Link-Local-Bereiche geprüft, sodass ein freigegebener Name, der heimlich auf 127.0.0.1 oder 169.254.169.254 zeigt, trotzdem abgewiesen wird. Indem Sie Weiterleitungen verbieten, verhindern Sie, dass ein externer Server Sie im zweiten Schritt doch nach innen lenkt.

Eine Blockliste “verbotener” Adressen lässt sich fast immer umgehen: durch alternative IP-Schreibweisen, IPv6 oder eine Domain, die ihren DNS-Wert erst nach Ihrer Prüfung ändert (DNS Rebinding). Setzen Sie deshalb auf eine Allowlist und prüfen Sie die IP-Adresse, mit der Sie tatsächlich verbinden.

Welche Auswirkungen hat SSRF?

Der Schweregrad von SSRF schwankt erheblich, was die Spanne von medium bis kritisch erklärt. In einer abgeschotteten Umgebung ohne interessante interne Dienste bleibt es womöglich beim Abtasten von Ports. In einer typischen Cloud-Umgebung ist die Beute jedoch groß: Der Metadaten-Endpunkt (169.254.169.254) gibt temporäre Zugangsdaten preis, und mit diesen Schlüsseln kann ein Angreifer oft die gesamte Cloud-Umgebung übernehmen.

Dass gerade dieser Endpunkt so ergiebig ist, liegt an seiner Bauweise. In der ersten Fassung, IMDSv1, genügt eine schlichte GET-Anfrage ohne Header und ohne jede Authentifizierung, und genau das ist die Kernfähigkeit eines SSRF. IMDSv2 verlangt dagegen zuerst eine PUT-Anfrage für ein kurzlebiges Token, das jede weitere Abfrage im Header mitführen muss; Azure und Google Cloud verlangen ebenfalls einen zusätzlichen Header. Wie viel ein erbeuteter Schlüssel wert ist, entscheidet die Rolle der Instanz: Darf sie Objektspeicher lesen oder Secrets abrufen, darf der Angreifer das ebenfalls. Und weil solche Zugangsdaten meist mehrere Stunden gültig bleiben, verwendet er sie danach bequem von seiner eigenen Infrastruktur aus, also weit außerhalb Ihrer Netzwerküberwachung.

Technisch öffnet SSRF die Tür zu allem, was der Server intern erreicht: Admin-Oberflächen ohne externen Zugang, interne APIs, Datenbanken, die Kubernetes-API oder eine Nachrichten-Warteschlange. Der Angreifer kann das interne Netzwerk kartieren, sensible Daten abgreifen und ein SSRF mitunter zu vollständiger Remote Code Execution ausbauen. Für das Unternehmen bedeutet das Datenlecks, auf Ihre Rechnung missbrauchte Cloud-Dienste und einen Angreifer, der sich von einem einzigen schwachen Endpunkt aus lateral durch die Infrastruktur bewegt. Ein bekanntes Beispiel ist das Datenleck bei Capital One im Jahr 2019, bei dem ein SSRF-Angriff den AWS-Metadatendienst erreichte und die Daten von über hundert Millionen Kunden offenlegte.

Wie spürt man SSRF auf?

Bei einem manuellen Test gibt ein Pentester in jedes Feld, das eine URL oder einen Host zu akzeptieren scheint, eine Adresse ein, die auf einen Server unter eigener Kontrolle zeigt, und achtet dann auf den Callback. Trifft eine DNS- oder HTTP-Anfrage ein, ruft die Anwendung die Adresse also tatsächlich ab. Selbst ohne sichtbare Antwort, das sogenannte blinde SSRF, verrät diese ausgehende Anfrage die Schwachstelle. Zusätzlich werden Metadaten-Endpunkte, alternative IP-Schreibweisen und Weiterleitungen erprobt, um Filter zu umgehen.

Damit sich die Callbacks eindeutig zuordnen lassen, vergibt ein Pentester pro geprüftem Feld eine eigene Subdomain; trifft eine Auflösung von feld7.test.example.net ein, ist sofort klar, welche Eingabe sie ausgelöst hat. Aufschlussreich ist auch, ob nur eine DNS-Abfrage oder eine vollständige HTTP-Verbindung eingeht, denn eine reine Namensauflösung kann ebenso von einem Proxy oder einer Security-Appliance stammen. Bleibt jeder Callback aus, helfen Seitenkanäle: Ein geschlossener interner Port wird sofort abgewiesen, ein gefilterter läuft in den Timeout, ein offener antwortet zügig. Aus diesen Laufzeiten und aus abweichenden Statuscodes lässt sich das interne Netzwerk kartieren, obwohl die Anwendung inhaltlich nichts preisgibt.

Ebenso wichtig ist, wo überhaupt gesucht wird, denn nicht jede verwundbare Eingabe heißt url. Zieladressen verstecken sich in Webhook-Konfigurationen, in XML-Dokumenten mit externen Entitäten, in hochgeladenen SVG-Dateien, die ein Konverter serverseitig rendert, und in Headern wie Referer. Häufig erfolgt der Abruf zudem zeitversetzt durch einen Hintergrundjob, sodass ein zu früh abgeschalteter Listener genau diese Fälle übersieht.

Automatische Scanner markieren verdächtige URL-Parameter, übersehen aber häufig genau die blinden Fälle. AssistSec berücksichtigt SSRF standardmäßig in einem Penetrationstest und prüft gezielt diese blinden Varianten.

Wie verhindert man SSRF?

Eine einzelne Maßnahme genügt hier selten. Wirksam ist erst die Kette aus strenger Prüfung in der Anwendung, einem eng geschnittenen Netzwerk und einer sparsamen Cloud-Konfiguration.

  • Nehmen Sie nach Möglichkeit gar keine freie URL entgegen: Lassen Sie den Nutzer aus vorab hinterlegten Zielen wählen und übernehmen Sie nur deren Kennung.
  • Setzen Sie auf eine Allowlist erlaubter Hosts, Domains und Protokolle und weisen Sie alles andere ab. Prüfen Sie dabei die geparste URL, nie die rohe Zeichenkette, und lehnen Sie eingebettete Zugangsdaten und unübliche Ports ab.
  • Erlauben Sie nur http und https und blockieren Sie Schemata wie file, gopher, ftp und dict.
  • Lösen Sie den Hostnamen zu einer IP-Adresse auf und blockieren Sie private, Loopback- und Link-Local-Bereiche, inklusive IPv6 und 169.254.169.254.
  • Verbinden Sie sich anschließend mit genau der geprüften IP-Adresse und reichen Sie den Hostnamen nur noch über Host-Header und SNI weiter; das schließt die Lücke, die DNS Rebinding ausnutzt.
  • Verbieten Sie Weiterleitungen oder validieren Sie jede Weiterleitung erneut nach denselben Regeln. Begrenzen Sie die Zahl der Sprünge und behandeln Sie jeden wie eine neue, unbekannte Eingabe.
  • Leiten Sie den ausgehenden Verkehr über einen Forward-Proxy, der die Allowlist zentral durchsetzt, damit nicht jede neue Funktion dieselben Prüfungen nachbauen muss.
  • Betreiben Sie die Abruffunktion mit minimalen Rechten in einem eigenen, abgeschotteten Netzwerksegment.
  • Deaktivieren Sie Cloud-Metadaten oder erzwingen Sie IMDSv2 mit Token und einem Hop-Limit von 1, damit eine einzige simple GET-Anfrage keine Schlüssel preisgibt. Weisen Sie jeder Arbeitslast eine eigene, minimal berechtigte Rolle zu.
  • Geben Sie den abgerufenen Inhalt nicht ungefiltert zurück, begrenzen Sie Größe und zulässigen Inhaltstyp und antworten Sie bei Fehlern einheitlich, damit weder Statuscode noch Antwortzeit etwas verraten.
  • Überwachen Sie Ihren ausgehenden Verkehr auf unerwartete Ziele und alarmieren Sie bei Verbindungsversuchen in Loopback-, Link-Local- und private Bereiche.

Quellen

Häufige Fragen

Was ist der Unterschied zwischen SSRF und CSRF?

Bei CSRF missbraucht ein Angreifer den Browser eines angemeldeten Nutzers, um unerwünschte Aktionen auszuführen. Bei SSRF missbraucht er den Server selbst, um Anfragen an interne Adressen zu senden. CSRF findet auf der Clientseite statt, SSRF auf der Serverseite.

Ist blindes SSRF gefährlich, wenn ich keine Antwort erhalte?

Ja. Auch ohne sichtbare Antwort kann ein Angreifer interne Ports abtasten, Dienste auslösen, die auf eine Anfrage reagieren, oder die Lücke als Sprungbrett für weitere Angriffe nutzen. Schon die ausgehende DNS- oder HTTP-Anfrage verrät die Schwachstelle.

Schützt eine Firewall vor SSRF?

Nicht von allein. Der Server stellt die Verbindung aus dem internen Netzwerk her, oft also hinter der Firewall. Segmentierung begrenzt den Schaden, doch die eigentliche Verteidigung ist die Eingabevalidierung in der Anwendung.

Warum reicht eine Blockliste gegen SSRF nicht aus?

Blocklisten lassen sich fast immer umgehen, etwa mit alternativen IP-Schreibweisen, IPv6-Adressen, Weiterleitungen oder DNS, das seinen Wert erst nach Ihrer Prüfung ändert (DNS Rebinding). Eine Allowlist samt IP-Validierung ist deutlich zuverlässiger.

Verwandte Artikel

Zum Suchen / drücken · Esc