11 Min. Lesezeit
Mittel
Von

CVE-2026-48736: SSRF-Bypass in Symfonys NoPrivateNetworkHttpClient — wenn die IPv6-Übergangsformen nicht auf der Blockliste stehen

31. Mai 2026. Symfony hat am 27. Mai mit CVE-2026-48736 eine SSRF-Bypass-Lücke in der HTTP-Client- und HTTP-Foundation-Komponente geschlossen. Der NoPrivateNetworkHttpClient ist als Decorator dokumentiert, der Requests in private Netze blockiert — aber die Blockliste IpUtils::PRIVATE_SUBNETS führte RFC1918, Loopback, Link-Local und IPv4-mapped IPv6 auf, ließ aber die übrigen IPv6-Übergangsformen aus, in die sich eine private IPv4-Adresse einbetten lässt: 6to4, Teredo, NAT64 und IPv4-compatible. Ein Angreifer mit Kontrolle über die Ziel-URL schreibt 127.0.0.1 dann als [2002:7f00:1::] (6to4) oder [64:ff9b::7f00:1] (NAT64), IpUtils::isPrivateIp() liefert false und der Client dispatcht. Für jeden Symfony-/Sylius-Stack, der Server-seitig auf nutzerbeeinflusste URLs zugreift (Webhooks, Link-Previews, Importer, Avatar-Fetcher), ist der Befund relevant; Fix-Stände sind 5.4.53, 6.4.41, 7.4.13 und 8.0.13.

TL;DR — die 90-Sekunden-Zusammenfassung

Was wurde veröffentlicht?

CVE-2026-48736 (Symfony-Security-Advisory 27.05.2026). Klasse: SSRF-Schutz-Bypass (Server-Side Request Forgery). Mechanismus: NoPrivateNetworkHttpClient blockiert Requests in private Netze anhand der Subnetz-Liste IpUtils::PRIVATE_SUBNETS. Diese Liste enthielt RFC1918, Loopback, Link-Local und IPv4-mapped IPv6 (::ffff:0:0/96), aber nicht die IPv6-Übergangsformen 6to4 (2002::/16), Teredo (2001::/32), NAT64 (64:ff9b::/96 und 64:ff9b:1::/48) und IPv4-compatible (::/96). IpUtils::checkIp6() ist ein reiner bitweiser CIDR-Vergleich und extrahiert das eingebettete IPv4 nie.

Wie schwer?

Mittel (operative Einschätzung — Symfony vergibt keinen CVSS, NVD Stand 31.05. noch RESERVED). Reichweite: Umgehung der Private-Network-Schutzlinie eines Decorators, der genau dafür existiert. Eintrittsschwelle: (a) die App nutzt NoPrivateNetworkHttpClient und (b) ein Angreifer kann die Ziel-URL beeinflussen. Die reale Erreichbarkeit des eingebetteten IPv4-Ziels hängt vom IPv6-Routing des Deployments ab — die Schutzgrenze wird aber unabhängig davon überschritten.

Welche Symfony-Versionen sind betroffen?

HTTP-Client- und HTTP-Foundation-Komponente >=6.4 <6.4.41, >=7.0 <7.4.13 und >=8.0 <8.0.13 (auf 5.4 lag die Liste als private Konstante im NoPrivateNetworkHttpClient). Behoben in 5.4.53, 6.4.41, 7.4.13 und 8.0.13.

Bin ich als Moselwal-Kunde betroffen?

Betroffen sind Sie, wenn auf einer Ihrer Symfony-/Sylius-Plattformen NoPrivateNetworkHttpClient eingesetzt wird, um Server-seitige Requests auf vom Nutzer gelieferte URLs abzusichern — typische Stellen: Webhook-Ziele, Link-/URL-Previews, Bild-/Avatar-Fetcher, RSS-/Feed-Importer, „URL importieren“-Funktionen. Wer keine vom Nutzer beeinflussbaren Server-seitigen Fetches hat oder den Decorator nicht nutzt, ist über diesen Pfad nicht betroffen.

Sofort-Mitigation?

Zwei Schritte. Erstens, prüfen, ob die App NoPrivateNetworkHttpClient verwendet (grep -rn "NoPrivateNetworkHttpClient" src/ config/). Wenn nein: dieser Pfad ist nicht relevant. Zweitens, wenn ja: auf den Fix-Stand heben (5.4.53 / 6.4.41 / 7.4.13 / 8.0.13). Defense-in-Depth: ausgehende Requests zusätzlich auf Netzwerk-/Egress-Ebene gegen private Ziele filtern, nicht allein auf die Anwendungs-Blockliste vertrauen.

Kritikalität?

Hero-Badge medium (operative Einschätzung, kein offizieller CVSS). Aktive Ausnutzung Stand 31.05. nicht öffentlich dokumentiert, keine CISA-KEV-Aufnahme. SSRF-Schutz-Bypässe dieser Art sind ein bekanntes Muster (vgl. Chromium/Mozilla Private Network Access) — die Klasse ist gut verstanden, der konkrete Hebel deployment-abhängig.

 

Was ist passiert

Symfony hat am 27. Mai 2026 ein Security-Advisory zu CVE-2026-48736 veröffentlicht — einem SSRF-Bypass im NoPrivateNetworkHttpClient. Dieser Decorator ist genau für einen Zweck da: Requests in private Netze zu blockieren, damit eine Anwendung, die Server-seitig auf vom Nutzer gelieferte URLs zugreift, nicht dazu missbraucht werden kann, interne Dienste, Loopback-Endpunkte oder Cloud-Metadata-Services anzusprechen. Genau dieser Schutz hatte eine Lücke.

Die Blockliste der privaten Subnetze — Symfony\Component\HttpFoundation\IpUtils::PRIVATE_SUBNETS ab 6.4, eine private Konstante im NoPrivateNetworkHttpClient auf 5.4 — zählte RFC1918, Loopback, Link-Local und IPv4-mapped IPv6 (::ffff:0:0/96) auf. Sie ließ aber die übrigen IPv6-Übergangsformen aus, in die sich ein privates IPv4-Ziel einbetten lässt: 6to4 (2002::/16, RFC 3056), Teredo (2001::/32, RFC 4380), NAT64 (64:ff9b::/96, RFC 6052 und 64:ff9b:1::/48, RFC 8215) sowie IPv4-compatible IPv6 (::/96, RFC 4291 §2.5.5.1).

Der eigentliche Bug sitzt in der Prüflogik: IpUtils::checkIp6() ist ein reiner bitweiser CIDR-Vergleich gegen die Konstanten-Liste und extrahiert die eingebettete IPv4-Adresse nie. Ein Angreifer, der eine URL liefern kann, schreibt das Loopback-/RFC1918-Ziel deshalb in einer der nicht gelisteten Übergangsformen — etwa [2002:7f00:1::] (6to4 → 127.0.0.1), [64:ff9b::7f00:1] (NAT64 → 127.0.0.1), [::7f00:1] (IPv4-compatible → 127.0.0.1) oder [2001::1] (Teredo). IpUtils::isPrivateIp() liefert false, und der NoPrivateNetworkHttpClient dispatcht den Request.

Wichtig für die nüchterne Einordnung: ob das eingebettete IPv4-Ziel am Ende tatsächlich erreicht wird, hängt vom IPv6-Routing des konkreten Deployments ab — vom 6to4-Tunnel-Interface, von einem vorgelagerten NAT64-Gateway, von der Kernel-Behandlung IPv4-compatible Adressen. Die Schutzgrenze, die der Decorator verspricht — die Dispatch-Entscheidung —, wird aber überschritten, unabhängig davon, wo das Paket landet. Der Fix nimmt ::/96, 2002::/16, 2001::/32, 64:ff9b::/96 und 64:ff9b:1::/48 in die Blockliste auf. Symfony begründet das Blanket-Blocking dieser Präfixe damit, dass es der Policy von Chromium und Mozillas Private Network Access entspricht: Server-seitige HTTPS-APIs werden auf diesen Präfixen nicht legitim veröffentlicht.

Technische Einordnung

Strukturell ist CVE-2026-48736 ein klassischer Allowlist-vs-Blocklist-Befund — und ein Lehrstück über die Schwäche von Blocklisten bei einem Adressraum mit vielen äquivalenten Schreibweisen. IPv6 kann dieselbe logische IPv4-Adresse in mehreren Übergangsformen ausdrücken. Eine Blockliste, die nicht alle Formen kennt, ist per Konstruktion unvollständig, sobald eine neue Form auftaucht oder eine bekannte vergessen wird. Genau das ist passiert: IPv4-mapped (::ffff:0:0/96) war drauf, die anderen vier nicht. Die saubere Lehre lautet: bei Adress-Filtern, die eine private Ziel-Klasse blocken sollen, ist die kanonische Normalisierung vor dem Vergleich der robustere Ansatz — die eingebettete IPv4 extrahieren und dann gegen die IPv4-Blockliste prüfen — statt jede IPv6-Einbettungsform einzeln zu enumerieren. Symfony hat sich (pragmatisch und in Abstimmung mit der Browser-Policy) für das Blanket-Blocking der Präfixe entschieden; das ist hier korrekt, weil auf diesen Präfixen keine legitimen öffentlichen Server liegen.

Der zweite methodische Punkt ist die Schicht-Trennung der Verantwortung. NoPrivateNetworkHttpClient ist eine Anwendungs-Schicht-Mitigation gegen SSRF. Solche Mitigationen sind wertvoll, aber sie sind nicht die einzige Linie. Eine ausgehende Egress-Firewall oder eine Netzwerk-Policy, die Requests aus dem Anwendungs-Pod/Container auf private Ziele unterbindet, fängt genau die Fälle ab, in denen die Anwendungs-Blockliste eine Lücke hat — und umgekehrt. Wer SSRF-Schutz ausschließlich auf der Anwendungs-Schicht implementiert, hat genau eine Linie; fällt sie durch einen Listen-Gap aus, ist der Schutz weg. Das ist dieselbe Defense-in-Depth-Logik wie bei der Firewall-Lücke aus dem Schwester-Post (CVE-2026-48489): eine Schutzschicht ist gut, zwei unabhängige Schichten sind belastbar.

Drittens, die Reichweiten-Frage verdient Nüchternheit. Anders als bei einer RCE ist der konkrete Impact hier stark vom Deployment abhängig. In einem reinen IPv4-Stack ohne 6to4/NAT64-Routing landet das Paket oft nirgends. In einem Deployment mit NAT64-Gateway (zunehmend verbreitet in IPv6-only-Cluster-Netzen) oder mit aktivem 6to4-Tunnel kann die eingebettete IPv4 sehr wohl erreicht werden — und dann ist das Ziel typischerweise Loopback (interne Admin-APIs), RFC1918 (interne Dienste) oder, in Cloud-Umgebungen, der Metadata-Endpunkt. Genau in modernen Kubernetes-/OpenShift-Cluster-Netzen mit IPv6-/Dual-Stack-Routing ist die Wahrscheinlichkeit der Erreichbarkeit höher als im klassischen IPv4-only-VPS. Die Triage muss deshalb beide Fragen stellen: nutzt die App den Decorator, und wie sieht das IPv6-Routing des Deployments aus.

Viertens, die Einordnung in die Symfony-Mai-2026-Release-Welle. CVE-2026-48736 ist Teil desselben koordinierten Release-Stands (5.4.53 / 6.4.41 / 7.4.13 / 8.0.13) wie CVE-2026-48489 (Firewall-Bypass über failure_forward). Der Patch-Pfad ist geteilt: ein einziges Update auf den Fix-Stand schließt beide Symfony-Core-Lücken. Wer ohnehin wegen des Firewall-Befunds patcht, nimmt diesen mit.

Wer ist betroffen

Betroffen / RisikoNicht betroffen / geringeres RisikoBedingung
Symfony-Apps mit HTTP-Client/HTTP-Foundation <5.4.53 / <6.4.41 / <7.4.13 / <8.0.13Apps auf den Fix-Ständen 5.4.53 / 6.4.41 / 7.4.13 / 8.0.13 und höherVersionsstand der symfony/http-client- und symfony/http-foundation-Komponenten
Apps, die NoPrivateNetworkHttpClient einsetzen und vom Nutzer beeinflussbare Ziel-URLs verarbeitenApps ohne diesen Decorator oder ohne nutzerbeeinflusste Server-seitige FetchesEinsatz des Decorators + Angreifer-Kontrolle über die URL
Deployments mit 6to4-Tunnel, NAT64-Gateway oder IPv6-/Dual-Stack-Cluster-Routing (eingebettetes IPv4 erreichbar)Reine IPv4-only-Deployments ohne Übergangs-Routing (eingebettetes IPv4 oft nicht erreichbar — Schutzgrenze trotzdem überschritten)IPv6-Routing des Deployments
Webhook-Ziele, Link-Previews, Avatar-/Bild-Fetcher, Feed-Importer, „URL importieren“-FunktionenServer-seitige Fetches ausschließlich auf fest verdrahtete, interne Allowlist-ZieleQuelle der Ziel-URL: nutzergeliefert vs. fest konfiguriert

Bedeutung für den Mittelstand

SSRF ist die Lücken-Klasse, die im Mittelstand am häufigsten unterschätzt wird, weil sie selten als „die App wurde gehackt“ auftritt, sondern als „die App wurde benutzt, um etwas anderes zu erreichen“. Die typischen Einfallstore sind harmlose Komfort-Funktionen: ein Webhook, dessen Ziel-URL der Kunde im Backend einträgt; eine Link-Vorschau, die beim Einfügen einer URL serverseitig das Ziel abruft; ein Avatar-Importer, der ein Bild von einer angegebenen URL zieht; ein Feed-Importer. Überall dort fließt eine vom Nutzer gelieferte URL in einen Server-seitigen Request — und genau dafür ist NoPrivateNetworkHttpClient die richtige, empfohlene Mitigation. CVE-2026-48736 zeigt, dass diese Mitigation eine Lücke hatte.

Das eigentliche Risiko liegt im Cloud-Kontext. In modernen Cluster-Netzen — Kubernetes, OpenShift, Dual-Stack-VPC — ist IPv6-/NAT64-Routing keine Seltenheit mehr. Ein erfolgreich durchgereichter Request auf ein eingebettetes Loopback- oder RFC1918-Ziel kann interne Admin-APIs, Service-Mesh-Endpunkte oder — der klassische Worst Case — den Cloud-Metadata-Service ansprechen, der in manchen Konfigurationen kurzlebige Credentials ausliefert. Das ist der Pfad, über den aus „die App ruft eine URL ab“ ein „die App leakt interne Zugangsdaten“ werden kann. Ob dieser Pfad in Ihrem Deployment offen ist, entscheidet das IPv6-Routing — und genau diese Frage stellt sich kaum jemand proaktiv.

Compliance-seitig ist die Achse DSGVO Art. 32 (angemessene technische Maßnahmen) und NIS-2 Art. 21 (Risikomanagement, Dependency-Disziplin) einschlägig, sobald der SSRF-Pfad interne, personenbezogene oder zugangsrelevante Ziele erreichen kann. Eine Rechtseinschätzung nehmen wir nicht vor (wir sind keine Kanzlei); die konkrete Bewertung gehört zu Ihrem DSB und Ihrem Sicherheits-Verantwortlichen.

Operativ ist die Doppel-Triage entscheidend: erstens grep -rn "NoPrivateNetworkHttpClient" src/ config/ über den Bestand, zweitens die Frage an die Infrastruktur, ob das Deployment IPv6-/NAT64-Routing hat. Beides zusammen trennt die Stacks mit echtem Hebel von denen, bei denen der Befund akademisch bleibt — wobei der Patch in beiden Fällen fällig ist.

Bedeutung für die technische Entwicklung

Architektonisch ist CVE-2026-48736 eine Erinnerung an drei Disziplinen.

Erstens, Blocklisten über Adressräume mit äquivalenten Schreibweisen sind fragil. Wer eine „verbotene“ Ziel-Klasse über eine Liste konkreter Präfixe definiert, muss jede mögliche Schreibweise derselben logischen Adresse kennen — und der IPv6-Übergangs-Adressraum bietet davon mehrere. Der robustere Ansatz ist Normalisierung vor dem Vergleich: die eingebettete IPv4 kanonisch extrahieren und dann gegen die (kleinere, vollständige) IPv4-Blockliste prüfen. Wo Normalisierung nicht praktikabel ist, ist das Blanket-Blocking ganzer Übergangs-Präfixe die pragmatische Wahl — was Symfony hier getan hat. Für die eigene Codebase: jede Stelle, die Host-/IP-Strings gegen eine Sicherheits-Liste prüft, gehört auf die Frage „kennt die Liste alle äquivalenten Formen“ auditiert.

Zweitens, SSRF-Schutz gehört auf zwei Schichten. Die Anwendungs-Schicht-Mitigation (NoPrivateNetworkHttpClient) ist richtig und sollte bleiben. Sie ist aber nur belastbar in Kombination mit einer Netzwerk-/Egress-Kontrolle, die ausgehende Requests aus dem Anwendungs-Container auf private Ziele unterbindet. In Kubernetes/OpenShift sind das NetworkPolicies bzw. Egress-Regeln; in klassischen Setups eine ausgehende Firewall-Regel. Diese zweite Schicht fängt genau die Listen-Gaps der ersten auf.

Drittens, IPv6-Routing ist Teil des Threat-Models, nicht nur der Infrastruktur. Die Erreichbarkeit eingebetteter IPv4-Ziele hängt vom 6to4-/NAT64-/Dual-Stack-Verhalten des Deployments ab. Das heißt: die Sicherheits-Bewertung einer SSRF-Lücke kann nicht allein im Anwendungscode getroffen werden, sie braucht die Infrastruktur-Sicht. Application-Security und Plattform-Betrieb müssen an dieser Stelle dieselbe Frage gemeinsam beantworten — ein gutes Beispiel dafür, warum „Security closer to the code“ und Plattform-Betrieb zusammengehören.

Konkrete Handlungsempfehlung

Operational Decision Block

In dieser Reihenfolge. Erstens, Doppel-Inventur heute: grep -rn "NoPrivateNetworkHttpClient" src/ config/ über jeden Symfony-/Sylius-Stack, parallel die Frage an die Infrastruktur, ob 6to4/NAT64/Dual-Stack-Routing aktiv ist. Zweitens, Patch-Lauf für die getroffenen Hosts: composer update symfony/http-client symfony/http-foundation (bzw. das symfony/symfony-Meta-Paket) auf 5.4.53 / 6.4.41 / 7.4.13 / 8.0.13, Build neu durchlaufen, deployen; Container-Images neu builden, nicht nur laufende Container patchen. Drittens, Egress-Defense-in-Depth: ausgehende Requests aus den Anwendungs-Pods/Containern per NetworkPolicy bzw. Egress-Firewall gegen private Ziele und den Cloud-Metadata-Endpunkt sperren — das fängt diese und künftige Anwendungs-Listen-Gaps ab. Viertens, Logging-Sweep: ausgehende HTTP-Client-Requests auf IPv6-Ziel-Hosts in den Übergangs-Präfixen (2002:, 2001:, 64:ff9b:, ::) prüfen, insbesondere mit eingebetteten Loopback-/RFC1918-Mustern. Fünftens, mittelfristig: alle Server-seitigen Fetch-Funktionen inventarisieren und prüfen, ob die Ziel-URL aus nutzergelieferten Daten stammt; wo möglich auf feste Allowlist-Ziele umstellen.

Wenn diese Schritte aus eigener Kraft nicht laufen, sprechen Sie mit uns: Moselwal prüft SSRF-Pfade im Architektur-Review, hält Symfony-/Sylius-Plattformen in einem laufenden SBOM- und Patch-Prozess und kombiniert Anwendungs-Mitigation mit Egress-Policies auf Netzwerk-Ebene — Plattformbetrieb statt Beratung-on-paper.

Dieser Beitrag spiegelt unsere technische und strategische Einschätzung. Er ersetzt keine Rechtsberatung und keine Datenschutz-Folgenabschätzung.

Fazit

CVE-2026-48736 ist kein spektakulärer Treffer, sondern ein lehrreicher: eine Sicherheits-Schutzlinie, die genau ihre eine Aufgabe (private Netze blocken) wegen einer unvollständigen Blockliste nicht vollständig erfüllte. Der reale Hebel ist deployment-abhängig — in IPv6-/NAT64-Cluster-Netzen ernst, in reinen IPv4-Stacks oft akademisch —, aber die Schutzgrenze wird in jedem Fall überschritten, und der Patch ist ein normales Composer-Update. Die wichtigste Empfehlung ist die zweite Schicht: SSRF-Schutz gehört nicht nur in die Anwendung, sondern auch auf die Netzwerk-/Egress-Ebene. Wer beide Schichten fährt, ist gegen den nächsten Listen-Gap gewappnet. Risiko nüchtern: mittel, mit klarer Deployment-Abhängigkeit — die Triage trennt die ernsten von den akademischen Fällen, der Patch gilt für beide.

Quellen

Über den Autor

Foto von Kai Ole Hartwig.

Kai Ole Hartwig

Founder · Moselwal Digitalagentur · OnlyOle

Programmiert seit 2002 – autodidaktisch gelernt, 2012 mit KO-Web selbständig gemacht, heute Moselwal. Über 100 Projekte, Fokus auf Security, Performance, Automatisierung und Qualität.