
Advisory für CVE-2026-51385. Musste es veröffentlichen, da GRAPHIFY das Advisory weder erkannt noch veröffentlicht hat, und MITRE CVE-2026-51385 zugewiesen hat, dies ist das Advisory dafür.
Sicherheitshinweis für CVE-2026-51385. Notwendig, es zu veröffentlichen, da GRAPHIFY den Advisory weder erkannt noch veröffentlicht hat, und MITRE CVE-2026-51385 zugewiesen hat; dies ist der Advisory dafür.
ES: Dies war mein erstes CVE. Um ehrlich zu sein, fand ich einen Weg, die Logik in der ANTI-SSRF-Funktion zu durchbrechen, und ich wollte unbedingt mein erstes CVE veröffentlichen. Also überlegte ich, wie es die Sicherheit beeinträchtigen könnte, um die Auswirkungen zu demonstrieren, obwohl die Ausführung komplex war (es ist kompliziert, dass dies in einer realen Instanz passiert, aber möglich, daher hat es 'complexity high'). Ich habe es an MITRE gesendet und sie haben es akzeptiert. Dies ist der Advisory.
EN: Dies war mein erstes CVE. Um ehrlich zu sein, fand ich selbst den Weg, die Logik in der Anti-SSRF-Funktion zu umgehen, und ich wollte das CVE unbedingt veröffentlichen. Also überlegte ich, wie es die Sicherheit beeinträchtigen könnte, und fand eine Rechtfertigung, sendete es an MITRE und sie akzeptierten es. Dies ist der Advisory.
Beachten Sie, dass der Bericht teilweise mit KI erstellt, aber von einem Menschen überwacht wurde
SSRF durch DNS-Rebinding (TOCTOU) in graphify.
Paket: graphify (PyPI: graphifyy), Repo Graphify-Labs/graphify
Betroffene Komponente: der URL-Erfassungspfad, graphify add <url>
(Commit , PRs #591 / #592)
8.3 (Hoch),
(SSRF), (TOCTOU-Wettlauf)
Arturo Melgarejo Galindo, unabhängiger Sicherheitsforscher ()
>=0.3.2, <=0.4.290.5.4CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:Hgraphify add <url> versucht, sich vor SSRF zu schützen, wie es viele Fetch-Programme tun: es löst den Hostnamen auf, prüft die resultierende IP gegen eine Blockliste (Loopback, RFC1918, Link-Local, reserved) und ruft nur ab, wenn diese Prüfung bestanden wird.
Das Problem ist, dass die IP, die validiert wurde, nicht die IP ist, mit der verbunden wird. Die Validierung führt eine DNS-Abfrage durch, und dann führt requests.get(hostname) eine zweite, unabhängige Abfrage durch. Wenn Sie die DNS-Zone für den Hostnamen besitzen und einen sehr niedrigen TTL mit zwei A-Einträgen zurückgeben (einen öffentlichen und einen internen), kann der Resolver bei jeder Abfrage legal eine andere Antwort geben. Die erste Antwort besteht die Blockliste. Die zweite Antwort ist diejenige, an die der Socket tatsächlich geht. Das ist der ganze Fehler. Es handelt sich um den klassischen Rebinding-Umgehungsangriff gegen die Logik "prüfe die IP, dann verbinde über den Namen", und die Behebung besteht darin, die validierte IP an die Verbindung zu binden, was 0.5.4 tut.
Ich möchte ehrlich sein, denn für sich genommen sieht es schwächer aus, als es ist.
Wenn ein Mensch sich hinsetzt und eine URL, der er bereits vertraut, in graphify add eingibt, ist dies nahezu wertlos. Diese Person kann graphify bereits auf ihren eigenen 127.0.0.1 verweisen, wenn sie möchte. Sie braucht dafür keinen Rebinding-Trick, und in diesem Szenario gibt es keinen Angreifer.
Es wird zu einer echten Schwachstelle, sobald graphify mit einer URL ausgeführt wird, die der Betreiber nicht gewählt hat. Und für dieses Tool ist das kein Randfall, sondern die normale Nutzung. graphify erstellt Wissensgraphen, die von KI-Assistenten genutzt werden. Der realistische Ablauf ist also, dass ein Prozess graphify add in Ihrem Namen aufruft: ein Agent, ein CI-Job, ein Skript, das eine Liste von URLs aus einer README durchläuft, oder eine URL, die direkt aus der Ausgabe eines anderen Modells stammt. In all diesen Fällen kontrolliert der Angreifer die Eingabezeichenkette und der Mensch hat sie nie überprüft.
Das ist der relevante Fall. Sobald die Eingabe nicht vertrauenswürdig ist und der Rebinding-Wettlauf gewonnen wird, landet der Fetch auf einer internen Adresse statt auf der öffentlichen, die validiert wurde. Konkret kann er Folgendes erreichen:
127.0.0.1 und alles, was an Loopback gebunden ist,169.254.169.254 (Cloud-Instanz-Metadaten),100.64.0.0/10, der von der Blockliste überhaupt nicht abgedeckt wird – dieser benötigt nicht einmal den Wettlauf, ein einfacher A-Eintrag, der darauf zeigt, reicht aus.Und das Erreichen dieser Adressen führt nur zu Schaden, weil dort etwas vorhanden ist. Viele interne und Entwicklungsdienste bieten GET-Endpunkte an, die entweder Daten zurückgeben oder den Zustand bei einem bloßen GET ändern. Ein graphify-Fetch, der auf einem von ihnen landet, mit dem falschen Pfad und der falschen Query-String, ist also nicht nur ein Lesezugriff. Wenn das interne Ziel ein Jenkins-scriptText, ein Flask/Django-Debugger im --debug-Modus, ein Admin-Panel oder ein Metadaten-Endpunkt ist, dann ist dieser fehlerhafte GET der Angreifer, der innerhalb des Perimeters handelt. graphify ist der Stellvertreter, der die Anfrage für ihn stellt.
Ich behaupte nicht, dass dies eine RCE liefert. Für sich genommen tut es das nicht. Aber ein vollständiger SSRF, der von einem automatisierten Erfassungspfad aus auf Loopback, IMDS, RFC1918 und CGN gerichtet werden kann, ist genau die Grundlage, auf der diese Angriffe aufbauen, und das ist der Zweck der Meldung.
Ich habe Tavis Ormandys öffentliches rbndr.us-System verwendet, das einen Hostnamen bereitstellt, der bei jeder Auflösung zwischen zwei IPs wechselt. 7f000001.08080808.rbndr.us wechselt zwischen 8.8.8.8 und 127.0.0.1.
Starten Sie etwas auf dem internen Ziel (hier Loopback, für die Demo):
sudo python3 -m http.server 80
Lösen Sie dann die Erfassung aus und wiederholen Sie den Vorgang, bis der Wettlauf erfolgreich ist. Es trifft etwa bei 1 von 4 oder 5 Versuchen zu, und eine triviale Schleife bringt das weit über 99%:
for i in {1..20}; do
graphify add http://7f000001.08080808.rbndr.us/ && break
sleep 1
done
Bei einem erfolgreichen Versuch erfasst graphify das, was der lokale Server auf 127.0.0.1:80 zurückgegeben hat, obwohl der Hostname zuvor die IP-Blockliste bestanden hat.
0.5.4 (dd86271) bereitgestellt, 8 Tage später.Arturo Melgarejo Galindo, unabhängiger Sicherheitsforscher.