sábado, 6 de diciembre de 2014

TCP Initial Window Size Fingerprinting with Zmap

¿Qué pasa cuando juntas una interesante técnica de fingerprinting con uno de los más rápidos scanners de Internet? Veamos... }:))

TCP Initial Window Size Fingerprinting

Esta es una de las técnicas explicadas por Fyodor en un paper titulado "Remote OS detection via TCP/IP Stack FingerPrinting":

Paper: http://nmap.org/nmap-fingerprinting-article.txt
Traducción: http://nmap.org/nmap-fingerprinting-article-mx.html

El Window Size es un campo de la cabecera TCP que se emplea para indicar la cantidad máxima de datos que un host está dispuesto a aceptar en el próximo envío. Esta cantidad límite se relaciona con el espacio disponible en un buffer de memoria reservado para la conexión TCP. Es precisamente en ese buffer donde se almacenaran los datos recibidos. Puesto que el RFC del protocolo TCP no dice cual debería ser el tamaño del buffer, cada sistema operativo es libre de implementar en su pila TCP/IP el tamaño de buffer que considere adecuado y por supuesto no todos emplean el mismo valor. Luego, si conocemos el tamaño del buffer podemos tener una idea del tipo de sistema operativo que se encuentra al otro lado de la conexión.

Fig. 1 - TCP Window Size por sistema operativo (fuente: www.netresec.com)

Para ello debemos observar el valor del campo Window Size al inicio de la conexión TCP. Esto es precisamente durante el three-way handshake en el SYN-ACK que responde el host remoto. Al ser una conexión nueva se supone que el buffer está completamente vacío y el valor del Window Size debe reflejar ello.

Podemos hacer un experimento para ver el Initial Window Size usando Scapy:

>>> pkt = IP(dst='TARGET_IP')/TCP(dport=80,sport=12368,flags='S')
>>> sr1(pkt).show()

Fig. 2 - Ver el Initial Window Size con Scapy

Zmap: Fast Internet-Wide Scanning

Teóricamente Zmap es capaz de barrer todo el rango de direcciones IPv4 en 5 minutos empleando una interfaz de red ethernet de 10 Gb. Para lograr semejante hazaña Zmap usa su propia implementación optimizada de la pila de protocolos. De esta manera aprovecha al máximo el ancho de banda disponible. Sin embargo, en la práctica, suele demorar mucho más generalmente porque el ancho de banda disponible es menor. En cualquier caso, Zmap es uno de los más rápidos scanners de Internet.

La técnica de escaneo que por defecto emplea Zmap es el archi-conocido TCP SYN Scan o también llamado Half Open. Esta técnica consiste en enviar un segmento TCP con el flag SYN activado al puerto objetivo. Si se obtiene como respuesta un SYN-ACK sabremos que el puerto está abierto y si por el contrario se obtiene un RST (reset), que está cerrado.

Una funcionalidad de Zmap que nos va a ser muy útil es la de poder extraer ciertos valores o "fields" del paquete de respuesta recibido. Entre estos valores, el que nos interesa por ahora es el Window Size.

La lista completa de "fields" que se pueden obtener con Zmap se puede consultar en su documentación:

https://zmap.io/documentation.html#outputfields

Entonces podemos usar Zmap para barrer un amplio rango de direcciones IPv4 e ir registrando el Window Size recibido de cada una de ellas.

Practice 0: Hack the Planet your ISP

Hora de jugar...

Para el juego de hoy vamos a recordar una vulnerabilidad publicada hace ya buen tiempo en este mismo blog: la CVE-2014-0329

http://blog.alguien.at/2014/02/hackeando-el-router-zte-zxv10-w300-v21.html

El router ZTE ZXV10 W300 v2.1 tiene credenciales hardcodeadas que permiten acceder al servicio telnet en el puerto 23. Nuestra actividad lúdica consiste en conseguir una lista de IPs con mayor probabilidad de ser vulnerables a este fallo.

Primero vamos a conseguir un rango de IPs a escanear, podría ser todo Internet, pero voy a limitarlo únicamente al rango de direcciones de mi ISP.

Usamos el comando "whois" sobre nuestra IP pública para ver el "ownerid" de nuestro ISP:

# whois 190.xxx.xxx.xxx
[Preguntando whois.lacnic.net]
[whois.lacnic.net]
...
inetnum:     190.xxx.xxx/xx
status:      reallocated
owner:       PE-XXX-XXX
ownerid:     PE-XXXXX-LACNIC
responsible: La Innombrable


Luego repetimos el comando whois pero esta vez sobre el ownerid:

# whois PE-XXXX-LACNIC
[Preguntando whois.lacnic.net]
[whois.lacnic.net]
...
owner:       PE-XXX-XXX
ownerid:     PE-XXXXX-LACNIC
responsible: La Innombrable
...

inetnum:     181.XX/XX
inetnum:     181.XY/XX

inetnum:     181.XZ/XX
inetnum:     190.XX/XX
inetnum:     190.XY/XX
inetnum:     190.XZ/XX

...

En los campos "inetnum" aparecen todos los rangos que le pertenecen a tu ISP. No te sientas mal por hacer esto, es información pública xD Ahora guarda la lista de rangos en un fichero con un nombre creativo, como por ejemplo "rangos.txt" :P

El siguiente paso es lanzar el escaneo con Zmap:

# zmap -w rangos.txt -p 23 -O csv -f classification,saddr,window -o scan.txt

  • -w rangos.txt: Sirve para especificar un "white list" de direcciones IP. Solo va a escanear las IP que estén en el fichero "rangos.txt". Esta opción acepta la notación CIDR.
  • -p 23: Indica el puerto a escanear. Solo se puede escanear un puerto a la vez.
  • -O csv: El formato de salida será CSV (campos separados por comas).
  • -f classification,saddr,window: Lista de campos (fields) que se mostrarán en la salida.
  • -o scan.txt: Para guardar los resultados del escaneo en el fichero "scan.txt" 

*** ADVERTENCIA ***
Los comandos mostrados en este post han sido ejecutados bajo un entorno controlado por monos con mameluco entrenados. NO INTENTE HACER ESTO EN CASA si no es un mono entrenado y/o no viste mameluco. Además es casi seguro que el ancho de banda de su conexión ADSL no soporte el volumen de tráfico generado por Zmap. No nos hacemos responsables por los daños ocasionados de forma directa o indirecta. Se recomienda discreción.

Una vez obtenidos los resultados del escaneo procedemos a filtrarlos. El formato de salida es el siguiente:

classification, saddr, window
rst,190.xxx.xxx.xxx,0
synack,200.xxx.xxx.xxx,8192
rst,190.xxx.xxx.xxy,0
rst,190.xxx.xxx.xxz,65535
synack,190.xxx.xxx.xyx,5840
synack,200.xxx.xxx.xxy,4128

...

Usando el comando grep vamos a filtrar aquellos con clasificación "synack" (osea, que el puerto está abierto).

# cat scan.txt | grep "synack" > open.txt

Luego de hacer algunas pruebas con routers "ZTE ZXV10 W300 v2.1" observé que estos responden con un Window Size igual a 8192. Así que puedo usar ese valor para filtrar nuevamente con grep y extraer solo las IPs con el comando cut.

# cat open.txt | grep "8192" | cut -d , -f 2 | sort -u > ips.txt

Et voilà! En el archivo "ips.txt" me queda una lista de IPs que además de tener el puerto 23 abierto respondieron con un Window Size igual a 8192. Seguramente no todos los hosts de la lista sean routers vulnerables, pero sí muchos de ellos.

Por último podemos pasar la lista de IPs obtenida como input a nuestro scanner favorito Nmap y usando un script NSE explotar de forma masiva estos equipos }:))

Exploit NSE para CVE-2014-0329: https://github.com/alguien-gh/scripts/blob/master/exploits/nse/airocon.nse

Conclusión

Podemos usar Zmap y fingerprinting por Window Size para barrer amplios rangos de direcciones IP en muy poco tiempo (unos cuantos minutos) e ir identificando dispositivos que responden con un Window Size en particular. En el supuesto de que fueramos a lanzar un ataque masivo sobre Internet, esto nos permite reducir el número de objetivos y enfocar nuestros recursos en aquellos que tienen mayor probabilidad de ser vulnerables. Por tanto es una forma de optimizar el ataque.

Un saludo.

1 comentario: