Server-Side Request Forgery (SSRF) ist eine Schwachstelle, bei der ein Angreifer den Server dazu bringt, eine von ihm kontrollierte URL abzurufen. Der Server wird so zum Stellvertreter: Er erreicht interne Dienste, Datenbank-Admin-Oberflächen oder die Metadaten-API des Cloud-Providers, die von außen unerreichbar wären. MITRE führt die Schwachstelle als CWE-918.
Die CWE-Definition bringt es auf einen Satz: Der Webserver erhält eine URL von einer vorgelagerten Komponente, ruft deren Inhalt ab und stellt nicht ausreichend sicher, dass die Anfrage an das erwartete Ziel geht. Das Problem ist nicht der Abruf selbst. Das Problem ist, dass der Server mit seiner eigenen Netzwerkposition und seinen eigenen Rechten abruft.
Genau diese Position macht SSRF in Cloud-Umgebungen so gefährlich. Ein Shop-Server steht in einem privaten Netz, spricht mit Redis, Elasticsearch, dem ERP-Connector und dem Metadaten-Dienst seiner Cloud. Nichts davon hat ein Passwort, weil „intern“ lange als Schutz galt. SSRF hebt diesen Schutz auf, ohne eine einzige Firewall-Regel zu brechen.
Wie SSRF funktioniert
Der Ausgangspunkt ist immer eine Funktion, die serverseitig eine URL lädt: ein Bild-Import per Link, ein Webhook-Test-Button, eine Link-Vorschau, ein PDF-Renderer, der externe Stylesheets nachlädt. Die URL kommt vom Client. Wenn der Server sie ungeprüft weiterreicht, entscheidet der Angreifer, wohin die Anfrage geht.
Die naheliegenden Ziele sind interne Adressen: http://localhost:6379 für Redis, http://10.0.0.5:9200 für Elasticsearch, ein Admin-Panel ohne Authentifizierung hinter dem Load-Balancer. Der Server beantwortet die Anfrage, und je nach Implementierung landet die Antwort direkt beim Angreifer, etwa als „Vorschau“ oder als importierte Datei.
Das lohnendste Ziel in der Cloud ist die Metadaten-API unter 169.254.169.254. Bei AWS liefert sie temporäre Zugangsdaten der IAM-Rolle, die der Instanz zugewiesen ist. Wer sie abrufen kann, handelt mit den Rechten des Servers gegenüber S3, Datenbanken und allen anderen Diensten. Deshalb hat AWS mit IMDSv2 ein sitzungsbasiertes Verfahren eingeführt.
IMDSv2 verlangt zuerst einen PUT-Request, der ein Token zurückgibt, und akzeptiert diesen PUT nicht, wenn ein X-Forwarded-For-Header gesetzt ist. Die Antwort trägt standardmäßig ein IP-Hop-Limit von 1, kommt also durch keinen Proxy. Ein einfacher GET per SSRF läuft damit ins Leere. Wer IMDSv1 noch erlaubt, verschenkt diesen Schutz.
DNS-Rebinding und Redirect-Tricks
Naive Prüfungen scheitern an zwei Klassikern. Beim DNS-Rebinding löst die Anwendung den Hostnamen auf, sieht eine öffentliche IP und winkt durch. Der eigentliche HTTP-Client löst den Namen danach noch einmal auf, und jetzt antwortet der Angreifer-DNS mit 127.0.0.1 oder 169.254.169.254. Zwischen Prüfung und Nutzung liegt eine Lücke, MITRE nennt das Muster CWE-367, Time-of-check Time-of-use.
Beim Redirect-Trick zeigt die URL auf eine harmlose Domain des Angreifers, die mit einem 302 auf die interne Adresse weiterleitet. Prüft die Anwendung nur die Start-URL und folgt der HTTP-Client Weiterleitungen automatisch, ist die Prüfung wertlos. Dazu kommen Parser-Tricks wie http://example.com\@evil.com und IP-Schreibweisen in Dezimal-, Oktal- oder Hex-Form, die ein Blocklist-Regex nicht erkennt.
Einordnung in den OWASP Top 10
In der Ausgabe 2021 hatte SSRF eine eigene Kategorie, A10:2021, mit 2,72 Prozent Incidence Rate und 385 zugeordneten CVEs, aufgenommen auf Basis der Community-Umfrage, nicht der Daten. In den OWASP Top 10 2025 ist die Kategorie verschwunden. Die Einleitung des Dokuments formuliert es knapp: SSRF wurde in Broken Access Control eingegliedert.
Das ist konsequent. Auf der Seite zu A01:2025 steht CWE-918 jetzt neben CWE-200 und CWE-352 unter den hervorgehobenen Schwächen, in einer Kategorie mit 40 CWEs, 3,74 Prozent durchschnittlicher Incidence Rate und 1.839.701 Fundstellen. Der Gedanke dahinter: Ein Server, der für fremde Anfragen seine Netzwerkposition hergibt, verletzt eine Zugriffsgrenze. Mehr dazu unter Broken Access Control.
Für die Praxis ändert die Verschiebung nichts an der Priorität. SSRF taucht in Pentest-Berichten und Advisories weiter als eigenständiger Fund auf, und die Gegenmaßnahmen sind spezifisch. Dass die Kategorie im Ranking nicht mehr sichtbar ist, darf nicht dazu führen, dass sie in Checklisten fehlt.
Realbeispiele: Capital One und Shopware
Der Klassiker ist der Capital-One-Vorfall von 2019. Laut der Unternehmensmitteilung fand der Zugriff am 22. und 23. März 2019 statt, entdeckt wurde er am 19. Juli 2019. Betroffen waren rund 100 Millionen Personen in den USA und 6 Millionen in Kanada, darunter etwa 140.000 Sozialversicherungsnummern und 80.000 Kontonummern.
Technisch lief der Angriff über eine fehlkonfigurierte Web Application Firewall auf AWS. Brian Krebs beschrieb damals, wie die WAF per SSRF dazu gebracht wurde, Anfragen an den Metadaten-Dienst weiterzuleiten, der temporäre Zugangsdaten herausgab. Die zugehörige IAM-Rolle durfte alle Buckets auflisten und lesen. SSRF war die Tür, überdimensionierte Rechte machten daraus den Datenabfluss. Die Täterin wurde im Juni 2022 wegen Wire Fraud und Computereinbruchs verurteilt.
Der zweite Fall liegt näher am Shop-Alltag. Am 25. August 2026 veröffentlichte Shopware zwei Advisories zu SSRF per DNS-Rebinding. GHSA-fgjq-45xv-rj8r betrifft den Medien-Import per URL: Ein authentifizierter Admin mit Medienrechten konnte die IP-Prüfung des FileUrlValidator über DNS-Rebinding umgehen und den Server Anfragen an interne Dienste schicken lassen, CVSS 6,3, Klassifizierung CWE-367 und CWE-918.
GHSA-rrc3-p9vx-5373 betrifft das App-System: Webhooks, Payment-, Tax-, Checkout- und Context-Gateways umgingen denselben Validator, CVSS 3,1. Beide Lücken sind in 6.6.10.23 und 6.7.13.1 geschlossen. Shopware empfiehlt als Workaround, ausgehende Verbindungen auf das Nötige zu beschränken und private Ranges, Loopback, Link-Local und Cloud-Metadaten-Adressen zu blockieren. Das Muster passt zu jeder Webhook-Integration, nicht nur zu Shopware.
Bemerkenswert ist, dass Shopware die Prüfung bereits hatte. Die Security-Referenz beschreibt sie: Standardmäßig validiert Shopware beim URL-Upload, dass die Adresse auf eine öffentlich erreichbare Ressource zeigt. Die Option shopware.media.enable_url_validation schaltet diese Prüfung ab, shopware.media.enable_url_upload_feature den Upload per URL komplett. Wer die Validierung deaktiviert hat, weil ein internes DAM nicht erreichbar war, hat sich die Lücke selbst wieder geöffnet.
Typische Stellen in Shops und Backends
SSRF entsteht selten in der Kern-Logik. Sie entsteht in Komfortfunktionen, die niemand als Angriffsfläche einstuft. Die folgende Übersicht zeigt, wo sie in Shop- und Backend-Projekten typischerweise auftaucht und welche Prüfung dort greift.
| Funktion | Warum anfällig | Erste Gegenmaßnahme |
|---|---|---|
| Medien-Upload per URL | Server lädt beliebige URL, Antwort wird gespeichert | Allowlist, Validierung aktiv lassen, Redirects aus |
| Webhook-Tester / Webhook-Ziele | Ziel-URL kommt aus dem Admin oder einer App | Private Ranges sperren, DNS-Pinning |
| Bild-Proxy / Thumbnail-Service | Antwort wird 1:1 an den Client zurückgegeben | Nur Content-Type image/*, keine Rohantwort |
| PDF-Renderer (Headless Chrome, wkhtmltopdf) | Lädt Bilder, Fonts, iframes aus HTML nach | Renderer in isoliertes Netz, Egress-Firewall |
| Link-Vorschau / oEmbed | Nutzer-URL wird serverseitig abgerufen | Resolver prüfen, Timeouts, keine Redirects |
| Import-Jobs (Feeds, ERP-Connectoren) | Quell-URL konfigurierbar, läuft mit Systemrechten | Feste Allowlist, Egress nur zu bekannten Hosts |
Headless-Setups vervielfachen diese Stellen. Ein Storefront-Backend, das Produktbilder vom CMS, Preise vom ERP und Bewertungen von einem SaaS-Dienst holt, hat drei URL-Quellen, die jemand konfiguriert. Jede davon ist ein SSRF-Kandidat, sobald die Konfiguration über die Admin-Oberfläche änderbar ist.
Gegenmaßnahmen, die halten
Das OWASP SSRF Prevention Cheat Sheet unterscheidet zwei Fälle. Fall 1: Die Anwendung muss nur mit bekannten Zielen sprechen. Dann gilt eine strikte Allowlist aus Host, Port und Schema, und die URL wird aus validierten Bausteinen zusammengebaut statt komplett vom Nutzer übernommen. Das ist der Normalfall für ERP-Connectoren und Zahlungsanbieter.
Fall 2: Die Anwendung muss beliebige externe URLs laden, etwa für Link-Vorschauen. Dann bleibt nur die Negativprüfung, und die muss sauber sein: alle A- und AAAA-Records auflösen, jede IP gegen private, Loopback-, Link-Local- und Metadaten-Ranges prüfen, und die Verbindung an die geprüfte IP binden. Dieses Pinning schließt das Rebinding-Fenster. HTTP-Redirects werden im Client deaktiviert und bei Bedarf manuell mit erneuter Prüfung verfolgt.
Auf Netzwerkebene gehört eine Egress-Firewall dazu, die ausgehenden Verkehr des Webservers auf bekannte Ziele beschränkt und den Metadaten-Dienst für Prozesse sperrt, die ihn nicht brauchen. IMDSv2 als Pflicht, kein IMDSv1. Dazu ein Netzsegment für Renderer und Importer, in dem Redis und Datenbank gar nicht erreichbar sind. Und die Rechte der Instanz-Rolle nach dem Least-Privilege-Prinzip schneiden, damit erbeutete Credentials wenig wert sind.
Ein Punkt wird regelmäßig unterschätzt: Logging. OWASP empfiehlt, auf der Firewall akzeptierte und geblockte Flows zu protokollieren. Ein Webserver, der plötzlich 169.254.169.254 anspricht, ist ein eindeutiges Signal, das ohne Logging niemand sieht.
Beispiel: URL-Allowlist-Prüfung in NestJS
In NestJS entsteht SSRF typischerweise dort, wo ein Controller eine URL aus dem Request entgegennimmt und per HttpService abruft. Die folgende Prüfung für Fall 1 erzwingt Schema, Host und Port, löst den Hostnamen auf und lehnt private Adressen ab. Die aufgelöste IP wird anschließend per lookup-Option an den HTTP-Client gepinnt.
import { BadRequestException, Injectable } from '@nestjs/common';
import { lookup } from 'node:dns/promises';
import ipaddr from 'ipaddr.js';
const ALLOWED_HOSTS = new Set(['cdn.example-partner.de', 'api.erp.example.com']);
@Injectable()
export class SafeUrlService {
async validate(raw: string): Promise<{ url: URL; ip: string }> {
const url = new URL(raw);
if (url.protocol !== 'https:') throw new BadRequestException('Nur https erlaubt');
if (!ALLOWED_HOSTS.has(url.hostname)) throw new BadRequestException('Host nicht freigegeben');
if (url.port && url.port !== '443') throw new BadRequestException('Port nicht erlaubt');
// Alle Adressen auflösen und gegen private Ranges prüfen
const records = await lookup(url.hostname, { all: true });
for (const { address } of records) {
const range = ipaddr.process(address).range();
if (range !== 'unicast') throw new BadRequestException('Ziel nicht öffentlich');
}
// Die geprüfte IP wird später per lookup-Option gepinnt (kein zweites DNS)
return { url, ip: records[0].address };
}
}
Der Aufruf selbst läuft dann mit maxRedirects: 0 und einem Agent, dessen lookup-Funktion die geprüfte IP zurückgibt. Wer stattdessen nur url.hostname gegen einen Regex prüft, hat die beiden Shopware-Lücken nachgebaut.
Abgrenzung
SSRF wird oft mit CSRF verwechselt, dabei sind die Richtungen entgegengesetzt. Bei Cross-Site Request Forgery nutzt der Angreifer den Browser eines eingeloggten Opfers, um Anfragen an eine Anwendung zu schicken. Bei SSRF nutzt er den Server der Anwendung, um Anfragen an Dritte zu schicken. CSRF braucht ein Opfer mit Session, SSRF braucht einen Server mit Netzwerkzugang.
Ein Open Redirect ist eine Weiterleitung, die ein Angreifer auf eine fremde Domain lenken kann, typischerweise für Phishing. Der Server ruft dabei nichts ab, er antwortet nur mit einem Location-Header. Open Redirects werden aber zum Werkzeug für SSRF, wenn ein verwundbarer Abruf-Endpunkt Weiterleitungen folgt.
XXE (XML External Entity) ist eine Injection in XML-Parser, bei der externe Entities Dateien oder URLs laden. XXE kann SSRF als Folge haben, weil der Parser serverseitig Ressourcen nachlädt. Die Ursache ist aber ein falsch konfigurierter Parser, nicht ein Endpunkt, der URLs entgegennimmt. Beide teilen sich die Abhilfe auf Netzwerkebene: Egress-Firewall und Segmentierung.
Supply-Chain-Angriffe liegen noch eine Ebene weiter. Eine kompromittierte App, die über das App-System Webhooks registriert, bringt ihre SSRF-Möglichkeiten mit, siehe Software Supply Chain Attack. Beim Bau von Backends mit vielen Integrationen ist Egress deshalb eine Architekturentscheidung und keine Nachbesserung; in der Enterprise-Software-Entwicklung werden Netzwerkgrenzen deshalb zuerst gezeichnet.
Häufige Fragen
Reicht es, private IP-Ranges zu blockieren?
Nein. Eine Blocklist scheitert an DNS-Rebinding, an Redirects und an alternativen IP-Schreibweisen. Sie ist nur dann vertretbar, wenn die Anwendung wirklich beliebige externe URLs laden muss, und auch dann nur mit vollständiger Auflösung aller Records, Pinning der geprüften IP und deaktivierten Redirects. Wo eine Allowlist möglich ist, ist sie die bessere Wahl.
Ist SSRF in einer On-Premise-Umgebung ohne Cloud-Metadaten harmlos?
Weniger spektakulär, aber nicht harmlos. Ohne Metadaten-API fehlt der direkte Weg zu Cloud-Credentials. Interne Dienste wie Redis, Elasticsearch, Jenkins oder ein Admin-Panel ohne Login sind trotzdem erreichbar, und Port-Scans über den Server bleiben möglich. Die Shopware-Advisories vom August 2026 nennen ausdrücklich interne Netzwerkdienste als Ziel, unabhängig vom Hosting.
Wie finde ich SSRF in einem bestehenden Shopware- oder NestJS-Projekt?
Suche nach jedem Codepfad, der eine URL aus Request, Datenbank oder Admin-Konfiguration liest und abruft: HttpService, fetch, axios, in Shopware der FileUrlValidator und alles, was ihn umgeht. Prüfe dann, ob die Validierung aktiv ist, ob Redirects verfolgt werden und ob die aufgelöste IP gepinnt wird. Ergänze einen Pentest mit einem eigenen DNS-Server, der Rebinding simuliert, und protokolliere ausgehende Verbindungen des Webservers eine Woche lang. Was dort an interne Adressen geht, gehört auf die Liste.