
Lauffähiger Docker-Proof-of-Concept für CVE-2026-71569, eine Umgehung der SSRF-Absicherung in der Webhook-Validierung von Apache Camel camel-a2a, mit Probes und Fix-Verifikation.
Lauffähiger Proof-of-Concept-Reproduzierer für die Apache-Camel-Schwachstelle, bei der WebhookUrlValidator
einen Push-Notification-Webhook-Host an zwei Stellen klassifizierte, die nicht übereinstimmten:
fc00::/7 benennen ("fc", "fd");isLoopbackAddress,
isAnyLocalAddress, isLinkLocalAddress und isSiteLocalAddress klassifiziert.Diese Prädikate decken nicht denselben Bereich ab: isSiteLocalAddress meldet den veralteten fec0::/10-Block,
nicht die fc00::/7-Unique-Local-Adressen, die ihn ersetzt haben, und das JDK enthält überhaupt kein Prädikat
für diese. Dieselbe Adresse wurde daher je nach Schreibweise akzeptiert oder abgelehnt.
| Laufzeitumgebung | Verzeichnis | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-a2a 4.22.1 |
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.39.0 (Quarkus 3.39.0, Camel 4.22.0) |
Der Hostname muss sich in fc00::/7 auflösen, was die Compose-Datei mit einem extra_hosts-Eintrag
arrangiert (Docker schreibt ihn beim Start in die /etc/hosts des Containers) — führen Sie dies daher über Docker aus, nicht mit einem
bloßen java -jar:
cd camel-spring-boot # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
until curl -sf http://localhost:8080/exploit/ready >/dev/null; do sleep 1; done
curl -s http://localhost:8080/exploit/attack
docker compose down
Auf einem betroffenen Build (identisch auf beiden Runtimes):
Resolution in this environment: internal-service.example -> fd00:0:0:0:0:0:0:1
1) The unique local address as an IP LITERAL
url: https://[fd00::1]/push-notification
verdict: REFUSED - Webhook URL must not point to private/internal IPv6 ranges (SSRF protection): [fd00::1]
2) The SAME address reached through a host name
url: https://internal-service.example/push-notification
verdict: ACCEPTED, resolved to fd00:0:0:0:0:0:0:1
3) A legitimate host name that merely BEGINS with "fc" (the bug's other direction)
url: https://fcm.googleapis.com/push-notification
verdict: REFUSED - Webhook URL must not point to private/internal IPv6 ranges (SSRF protection): fcm.googleapis.com
4) CONTROL - an IPv4 private address, which isSiteLocalAddress does cover
verdict: REFUSED - ... site-local/private address ...
5) CONTROL - a link-local IPv6 literal
verdict: REFUSED - ... private/internal IPv6 ranges ...
>>> PROVEN: ...
Die Probes 1 und 2 sind dieselbe Adresse, und die Urteile widersprechen sich. Probe 3 ist dieselbe Inkonsistenz in der
anderen Richtung: Die String-Vorprüfung stimmte mit dem rohen Host überein, ohne zuvor festzustellen, dass es sich um ein IP-Literal
handelte, sodass jeder Name, der lediglich mit fc oder fd beginnt, rundheraus abgelehnt wurde — fcm.googleapis.com, ein
völlig gewöhnlicher Push-Endpunkt, unter anderem. Die Probes 4 und 5 sind Kontrollen, die zeigen, dass die Schutzmaßnahme dort funktioniert, wo sie
korrekt implementiert wurde.
Jede Probe übergibt allowLocal=false, was der Standardwert ist (allowLocalWebhookUrls=false) und die
Konfiguration, in der die Schutzmaßnahme greifen soll.
Die Webhook-URL kommt als TaskPushNotificationConfig.url vom Aufrufer, der die Push-
Benachrichtigung registriert, ist also angreifergesteuert. PushNotificationDispatcher sendet dann die Push-
Benachrichtigung an diese Adresse, zusammen mit jedem Authorization-Header, der in derselben Konfiguration mitgeführt wird —
dessen Schema und Anmeldedaten der registrierende Aufrufer liefert.
Die Antwort wird nicht an diesen Aufrufer zurückgeleitet, sodass das Ergebnis eine blinde ausgehende HTTPS-
Anfrage vom Camel-Prozess an eine interne Adresse ist, die die Schutzmaßnahme eigentlich ablehnen sollte. Um auf diesem Weg einen Dienst zu erreichen,
ist zusätzlich erforderlich, dass der Name in der Zielumgebung in fc00::/7 auflöst, dass ein
HTTPS-Dienst auf dieser Adresse lauscht und dass der TLS-Handshake für den angeforderten Namen erfolgreich ist —
weshalb die Schwere als mittel eingestuft wird.
| Eigenschaft | Wert |
|---|---|
| Komponente | camel-a2a (WebhookUrlValidator) |
| CWE | CWE-918 (Server-Side Request Forgery) |
| Schweregrad | Mittel |
| Angriffsvektor | Eine Push-Benachrichtigungs-Webhook-URL, deren Host-Name in fc00::/7 auflöst |
| Auswirkung | Eine blinde ausgehende HTTPS-Anfrage mit dem konfigurierten Authorization-Header an eine interne Adresse, die die Schutzmaßnahme hätte ablehnen sollen |
| Betroffene Versionen | Ab 4.21.0 vor 4.22.2 |
| Behobene Versionen | 4.22.2, 4.23.0 |
| JIRA | CAMEL-24371 |
| Danksagung | 2122295973 at qq dot com, gemeldet über das ASF Security Team |
Advisory: https://camel.apache.org/security/CVE-2026-71569.html
Beide Pfade laufen nun über InetAddress.getByName, das ein in Klammern gesetztes IPv6-Literal ohne DNS-Zugriff
parst, und klassifizieren die resultierende Adresse anhand ihrer Rohbytes mit einem gemeinsamen Klassifizierer —
sodass ein Host nach der Adresse beurteilt wird, die er bezeichnet, und nicht danach, wie er geschrieben wurde. Dieser Klassifizierer erkennt fc00::/7
und den gemeinsam genutzten Adressraum 100.64.0.0/10 sowie IPv4-kompatible, NAT64- (64:ff9b::/96) und 6to4-
(2002::/16) Adressen, deren eingebettete IPv4-Adresse nicht global routbar ist.
Behoben auf main in apache/camel#25406 (54041cce), zurückportiert
auf camel-4.22.x in #26583 (c4a5c5fc).
Setzen Sie camel.version auf 4.22.2 und führen Sie es erneut aus. Verifiziert gegen 4.22.1 → 4.22.2:
1) The unique local address as an IP LITERAL
verdict: REFUSED - Webhook URL must not point to a unique local address (SSRF protection): [fd00::1]
2) The SAME address reached through a host name
verdict: REFUSED - Webhook URL must not point to a unique local address (SSRF protection): internal-service.example
3) A legitimate host name that merely BEGINS with "fc"
verdict: ACCEPTED, resolved to 216.239.38.55
Beide Schreibweisen erhalten jetzt dasselbe Urteil, mit derselben Meldung, und der Fehlalarm in Probe 3 ist ebenfalls beseitigt.
Platzieren Sie eine Authentifizierung vor dem Konfigurationspfad für A2A-Push-Benachrichtigungen, damit die Webhook-URL nicht von einem nicht vertrauenswürdigen Aufrufer stammt, und blockieren Sie auf Netzwerkebene ausgehenden Datenverkehr vom Camel-Prozess zu fc00::/7. Wenn die Bereitstellung kein IPv6 benötigt, entfernt der Start der JVM mit -Djava.net.preferIPv4Stack=true die Adressklasse, auf der die Lücke beruht. Beachten Sie, dass allowLocalWebhookUrls=false bereits der Standard ist und die Lücke nicht für sich allein schließt — Probe 2 oben läuft damit.
Dieses Repository wird zu Bildungs- und Verteidigungszwecken veröffentlicht: um Apache-Camel-Nutzern zu helfen, die Schwachstelle zu verstehen, zu prüfen, ob sie betroffen sind, und zu bestätigen, dass ein Upgrade sie behebt. Verwenden Sie dieses Material nicht gegen Systeme, die Ihnen nicht gehören oder die Sie nicht betreiben.