Hace unos dias vi una vulnerabilidad llamada Microsoft Windows XP/Vista TCP/IP Orphaned Connections Vulnerability. Me parecio re interesante y como nunca he visto exploits sobre vulnerabilidades de este tipo, comence a hacer algo para aprender un poco y queria compartir con ustedes los resultados. Parece que no hay actualizacion disponible a pesar de que hace unos meses que salio.
El problema es en el manejo de las conexiones con zero-window en la implementacion del tcp-ip stack en windows. Para probar esta vulnerabilidad hay que establecer una conexion tcp con tamaño de ventana cero.
Supongamos que apenas se realiza la conexion con el servidor, el mismo desea enviar datos al cliente (por ej. el banner de un server ftp). Como el tamaño de la ventana de la conexion tcp es 0, Windows va a comenzar a enviar "ZeroWindowProbe" (ZWP) para actualizar la ventana y esperar que sea mayor a cero para poder transmitir los datos. La idea de la vulnerabilidad, segun entiendo
, es de reconocer esos ZeroWindowProbes, o sea enviar "ZeroWindowAck" (ZWA). Luego de un tiempo la conexion pasara al estado FIN_WAIT_1 debido a que el server cierra el socket (timeout de la conexion) y luego el kernel continua enviando ZWPs. Dentro de cada ZWP se envia 1 byte de los datos que el servidor deseaba enviarle al cliente, hasta que se agotan. Una vez agotados los datos, la conexion queda colgada en este estado.Ahora, como hacer el exploit?.
Es claro que hay que injectar paquetes, o sea armar la conexion tcp con tamaño de ventana cero y luego reconocer todos los ZWPs con tamaño de ventana cero tambien. En mi caso, utilice libnet para inyectar los paquetes y libpcap para recibir las respuestas. Libnet tiene muchos ejemplos utiles. Y para el uso de libpcap hay tutos muy completos en internet. Con el wireshark miraba todos los paquetes.
Les comento maso los resultados durante el proceso de creacion del exploit.
Primeramente comence por crear el paquete SYN para iniciar la conexion. Uso ubuntu 9.10 como cliente y windows xp sp3 con un servidor ftp corriendo (Cerberus) a fin de probar todo. De ahora en mas distinguire las maquinas como linux y windows simplemente.
Esta fue mi primera prueba de envio de un paquete con el flag SYN activado al puerto 21 desde el puerto 54321.
Código:
1 0.000000 192.168.9.140 192.168.9.1 TCP 54321 > ftp [SYN] Seq=0 Win=32767 Len=0
2 0.001429 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
3 0.001718 192.168.9.140 192.168.9.1 TCP 54321 > ftp [RST] Seq=1 Win=0 Len=0
2 0.001429 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
3 0.001718 192.168.9.140 192.168.9.1 TCP 54321 > ftp [RST] Seq=1 Win=0 Len=0
La maquina 192.168.9.1 (servidor) tiene windows y la 192.168.9.140 (cliente) linux.
Envio el SYN y recibo bien el SYNACK correspondiente, pero al parecer hay un paquete RST que termina la conexion enviada por linux. El problema es que no hay PCB asociado a la conexion (es logico, el paquete fue injectado) y linux se lo comunica en seguida a windows con un RST. Para evitar este tipo de respuestas del kernel, hay que hacer que dropee todo paquete que llega desde windows. Se puede hacer con iptables de la siguiente manera:
Código:
$ sudo iptables -A INPUT -s 192.168.9.1 -j DROP
La segunda prueba me dio como resultado
Código:
1 0.000000 192.168.9.140 192.168.9.1 TCP 54321 > ftp [SYN] Seq=0 Win=32767 Len=0
2 0.000157 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
3 2.992756 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
4 9.028081 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
Ahi se puede ver que no hay mas RST (es decir que linux esta dropeando todo) y windows tratando de establecer la conexion en 2 reenvios de los SYNACK. Despues de 3 seg el primer reenvio y al cabo de 9 el ultimo.2 0.000157 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
3 2.992756 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
4 9.028081 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
Ahora lo siguiente es mandar el ACK para pasar la conexion al estado ESTABLISHED. Aca les muestro los resultados.
Código:
1 0.000000 192.168.9.140 192.168.9.1 TCP 54321 > ftp [SYN] Seq=0 Win=0 Len=0
2 0.000325 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
3 0.000816 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindow] 54321 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
4 3.053175 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
5 8.987873 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
6 21.058454 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
7 44.998464 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
8 74.973699 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
2 0.000325 192.168.9.1 192.168.9.140 TCP ftp > 54321 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
3 0.000816 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindow] 54321 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
4 3.053175 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
5 8.987873 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
6 21.058454 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
7 44.998464 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
8 74.973699 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54321 [ACK] Seq=1 Ack=1 Win=65535 Len=1
Y esto es lo que sucede. Al establecerse la conexion al cabo del ACK (3er paquete) windows comienza a enviar los ZWPs. Esto pasa porque en realidad el servidor ftp Cerberus envia datos luego de establecida la conexion, y como la ventana es cero los datos deben permanecer en el buffer del enviador. Se comienzan a mandar los ZWPs para actualizar el valor de la misma.
En este caso todavia no se estan mandando los ZWAs y se puede ver los retardos de retransmision involucrados.
Si se ejecuta un netstat en windows durante la transmision de los ZWPs se observa lo siguiente
Código:
TCP amsavs:ftp 192.168.9.140:54321 ESTABLISHED
La conexion ha pasado efectivamente al estado ESTABLISHED y 30 segundos despues de haber enviado el paquete nro 8 windows cierra la conexion.Ahora miren lo que pasa cuando se envian los ZWAs.
Código:
1 0.000000 192.168.9.140 192.168.9.1 TCP 54320 > ftp [SYN] Seq=0 Win=0 Len=0
2 0.000084 192.168.9.1 192.168.9.140 TCP ftp > 54320 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
3 0.000435 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
4 3.027498 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
5 3.028039 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
6 9.062778 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
7 9.063243 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
8 21.032757 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
9 21.033604 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
10 45.073267 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
11 45.073731 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
12 75.048460 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
13 75.049237 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
14 105.023637 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
15 105.024110 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
2 0.000084 192.168.9.1 192.168.9.140 TCP ftp > 54320 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
3 0.000435 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
4 3.027498 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
5 3.028039 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
6 9.062778 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
7 9.063243 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
8 21.032757 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
9 21.033604 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
10 45.073267 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
11 45.073731 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
12 75.048460 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
13 75.049237 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
14 105.023637 192.168.9.1 192.168.9.140 TCP [TCP ZeroWindowProbe] ftp > 54320 [ACK] Seq=1 Ack=1 Win=65535 Len=1
15 105.024110 192.168.9.140 192.168.9.1 TCP [TCP ZeroWindowProbeAck] [TCP ZeroWindow] 54320 > ftp [ACK] Seq=1 Ack=1 Win=0 Len=0
Bueno fijense que ahora se envian los ZWAs correspondientes. El esquema de tiempos es muy similar al caso anterior (sin ZWAs). Justo despues de haber enviado el ACK al SYNACK netstat en windows dice lo siguiente:
Código:
TCP amsavs:ftp 192.168.9.140:54321 ESTABLISHED
Luego del paquete nro 14, el server me tira como mensaje un connection time-out y netstat dice:
Código:
TCP amsavs:ftp 192.168.9.140:54321 FIN_WAIT_1
Por lo que efectivamente el estado de la conexion paso a FIN_WAIT_1. Una vez en este estado, los ZWPs se envian cada 30seg.
La longitud de datos de los ZWP es efectivamente 1, y el dato enviado es el "2". Que resulta ser el primer caracter de la respuesta del servidor en conexiones normales.
Lo deje un buen tiempo, mandando ZWAs y siempre recibia como dato de prueba en los ZWPs un "2". Cuando supuestamente deberia recibir byte por byte los datos que el servidor ftp pretendia enviar.
Si se dejan de enviar los ZWAs con la conexion en el estado FIN_WAIT_1, al cabo de 3 ZWPs la conexion pasa a CLOSED.
Todo esto para decir que mi windows no es vulnerable o bien estoy haciendo algo mal en mis tests. Si alguien tiene ganas de ponerse a probar un rato me gustaria que me comentaran sus resultados, mas abajo paso el codigo fuente.
Probando conexiones de zero-window descubri que si se establece una conexion zero-window al puerto 135, la misma permanece en ESTABLISHED indefinidamente!. No hay ZWPs porq deberia enviarle algunos datos para hacer que el servicio responda y se bloquee (lo probare mas adelante y posteare resultados).
Aca les dejo el codigo que hize para realizar estas pruebas.
zerowin.c
Libnet la pueden encontrar en el siguiente link:
Libnet
Para libpcap pueden hacer un sudo apt-get install y libpthread la deberian tener.
Para compilarlo una vez que estan todas las lib instaladas,
Código:
gcc zerowin.c -lpcap -lpthread -lnet -o zerowin
Mirando el codigo van a ver comentarios en ingles y en español
. Bue, los efectos del copy&paste
. En fin, la idea era de tener algo como para hacer estas pruebas. Mas adelante comentare el codigo para explicar maso como arme los paquetes y el sniffer (si alguno sabe de alguna tool, pls pasenla).Bueno eso, queria mostrar algunos de los resultados que obtuve en el analisis de esta vulnerabilidad y lo que encontre por jugar con otras cosas
.Saludos.










Autor



En línea


jaja. Bue, entonces el codigo serviria como exploit. Como habia dicho, conectando al 135 con zero-window la conexion queda indefinidamente en ESTABLISHED. Tocando el codigo lo puse para que cree la conexion nomas y con un script:
. Alguien sabe donde encontrar el limite de conexiones en ESTABLISHED en windows?.
.
. Busque por todos lados pero no encontre nada de info. O sea, absolutamente nada
. Alguien sabe maso como se explota esto?.
jaja. Bue, no se digo comenzar a buscar un poco y probar. Yo estuve leyendo sobre la opcion timestamp pero no se me ocurre nada como para empezar a probar.