Comprobando rangos de IPs Paraguayas por CVE-2018-14847

Disclaimer: Sólo quiero aclarar que ningún sistema fue comprometido y ninguna intrusión fuera del margen legal ha sido cometida en relación a este experimento. Este post es para fines educacionales. El autor no asume ningún tipo de responsabilidad en relación al uso del material expuesto.

Hace poco se descubrió una vulnerabilidad (CVE-2018-14847) en RouterOS, el firmware de los routers de la marca Mikrotik.

La vulnerabilidad consiste en un “authentication bypass.” Básicamente es tan simple que es ridículo, no debería hacer pasado pero, suelen suceder este tipo de cosas en la informática.

Funciona de esta manera. Mikrotik usa una aplicación llamada Winbox para que los administradores de red puedan conectarse a los routers para configurarlos. La conexión se establece vía el puerto 8291. El admin debe ingresar la IP, un nombre de usuario y password para poder conectarse.

Ahora la parte interesante, normalmente en la criptografía, después de la autenticación se establece una sesión que funciona con funciones altamente complejas, por ejemplo enviando un string largo de números aleatorios, Ejemplo: ED4CD270FDC3F828C87CBD7A1C9D7427CF470A7E11681CFA7F4E7795FDF077C2

Ahora el problema, mikrotik usaba un ID de sesión vulnerable. Cambiando solo 1 byte cada vez que se intercambia información entre el router y el cliente autenticado. Aquí un artículo detallado sobre el tema.

El bypass funciona de forma en que simplemente se cambia un sólo byte en cada request y así podemos leer archivos arbitrarios del router, por ejemplo el archivo que contiene a los usuarios.

Sólo ejecuta esto en tus propios equipos!

Encontré una implementación en Python que funcionó a la perfección.

Entonces pensé, cuántos routers de Paraguay será que están vulnerables? Mikrotik es una marca cada vez más usada. Es conocida como una alternativa mucho más barata a cisco, y con un sistema operativo más potente. RouterOS realmente es muy versátil. Hasta ahora no encontré un caso de uso de ruteo que no pude implementar en RouterOS.

Tenía al exploit y tenía una serie de rangos de todas las IPs Paraguayas. Era hora de hacer un nmap! Quien hizo nmap sabe que no es el proceso más rápido. En promedio, un mapeo de una sola IP puede durar 30 segundos. Entonces cómo se supone que puedo hacer un escaneo de millones de IPs? Nmap es super potente y tiene varias fases en un escaneo regular. Lo que hice fue crear un comando que saltaba todos los pasos innecesarios.

Para empezar, lo único que me interesó fue si los puertos de Winbox estaban abiertos. Entonces éste es el comando que creé.

nmap -p 8291 -v -n --max-rtt-timeout 1 --max-retries 1 -Pn

Lo que hace es verificar directamente si el puerto 8291 está activo, con un timeout de 1 segundos y un solo intento. Esto me da un performance muy bueno. Por supuesto hay que pasar una lista de IPs en conjunto.

Si el puerto de winbox está accesible desde Internet, esto ya es una mala práctica de seguridad. Debería estar bloqueado por el firewall. Si estás administrando un mikrotik asegúrate de tener una regla similar a esta, dependiendo de tu configuración.

add action=drop chain=input comment=\
    "Bloquear acceso desde Internet" \
    in-interface=Internet_interface

El nmap scan duró varios días aunque podría haberlo paralelizado más. Ahora tenía otro problema. Varios txt de cientos de MB y millones de líneas de nmap output. Los txt eran tan grandes que Notepad++ y VSCode se quedaban colgados al tratar de manipularlos. Pero necesitaba procesar al formato para filtrar sólo a las IPs con el puerto abierto. Como estaba usando windows en el momento, usé Cygwin para poder usar grep. Grep es una de esas herramientas tan útil y versátil de linux. Permite buscar patrones en texto.

cat nmap_scan.txt | grep -B4 open | egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}" > ips_con_puertos_abiertos.txt

Lo que hace el comando es imprimir a todo el texto primero, luego lo pasa el resultado a grep. Grep busca a las líneas que contienen la palabra “open” y imprime a las 4 líneas anteriores a esa linea X, luego pasa el resultado a egrep. Egrep usa una expresión regular que selecciona a cualquier número de IP contenido en el texto. El resultado es una conversión como la vemos abajo.

TXT original de nmap
PORT STATE SERVICE
8291/tcp filtered unknown
Nmap scan report for 2xx.xx.xx.xxx
Host is up.
PORT     STATE    SERVICE
8291/tcp open unknown
Nmap scan report for 2xx.xx.xx.xxx
Host is up (0.010s latency).
PORT     STATE  SERVICE
8291/tcp closed unknown
Nmap scan report for 1xx.xx.xx.xxx
Host is up.
PORT     STATE    SERVICE
8291/tcp open unknown
> Resultado del grep
2xx.xx.xx.xxx
1xx.xx.xx.xxx

Sólo 2 IPs resultantes en este ejemplo, porque sólo 2 puertos están abiertos.

Ahora solo queda proceder a verificar cuáles de los Mikrotik aún tienen el firmware vulnerable. Pero tengo una lista de 217.660 IPs. Eso tomaría mucho tiempo. Menos mal no todas las IPs corresponden a routers físicos. No tengo manera fácil de identificar los routers físicos (no quiero hacer fingerprints en nmap eso tomaría demasiado tiempo) pero haré una simplificación. Divido a la lista en subnets agarrando todas las IPs que terminan en XXX.XXX.XXX.1. Eso reducirá mucho el tamaño de mi lista.

cat ips_con_puertos_abiertos.txt | egrep -o “([0-9]{1,3}\.){3}[1]{1}$” > subnets_con_puertos_abiertos.txt

La lista que me sobra ahora contiene 848 IPs, un número mucho más manejable.

The final step. The actual exploit

Finalmente llegué al punto en donde puedo hacer tests de la vulnerabilidad. Ya existe una herramienta llamada WinBoxPoC. Lo que haré ahora es modificarla para que funcione con una lista de IPs. Version modificada.

Y ahora la sorpresa, las IPs ya no parecen estar vulnerables. Hice el escaneo de Nmap hace unas semanas atrás, será que ahora todos actualizaron RouterOS? Es una posibilidad.

Haré más experimentos pronto pero por ahora dejo esto como un ejercicio de investigación para tí… NOT (es ilegal comprometer sistemas)!

Espero que aprendiste algo nuevo. Si sos administrador de un Mikrotik, asegurate de configurarlo bien.

Hasta pronto