Bug Remoto: Demostración Ilustrada de Uno de

Anuncio
Bug Remoto: Demostración Ilustrada de Uno de los Beneficios de un Microkernel vs
Kernel Monolítico
Alejandro Hernández (@nitr0usmx)
http://www.brainoverflow.org
Día a día, la mayoría de nosotros los mortales usamos sistemas operativos con núcleos
monolíticos, es decir, la mayoría de las operaciones de interacción directa con el hardware radican
en modo privilegiado, es decir en modo kernel, a diferencia del modelo de micronúcleo, donde su
nombre lo dice, el núcleo es muy pequeño. En este esquema, solamente las operaciones más
básicas trabajan en modo kernel, mientras las demás, incluyendo la pila TCP/IP, residen en modo
usuario:
Tomada de: http://en.wikipedia.org/wiki/Monolithic_kernel
Ahora bien, ¿cuál es mejor?, pues esta interminable discusión, como la interminable de VIM vs
Emacs, ya ha sido abordada y discutida por muchos investigadores y expertos en ciencias de la
computación, entre ellos, Linus Torvalds y Andrew S. Tanenbaum [1] [2]. Sin embargo, entre los
varios pros y contras, el motivo de este artículo es para sencillamente demostrar uno de los
beneficios de un microkernel ante un fallo de seguridad en su pila de red, la cual como he
mencionado antes, trabaja en modo usuario y por lo tanto, un fallo grave en esta, no dejaría al
sistema operativo inservible por completo (kernel panic) a diferencia de los otros con núcleo
monolítico (Linux, Free/Net/OpenBSD, AIX, HP-UX, Solaris). Fallos famosos en núcleos monolíticos
van desde el infame Ping de la Muerte que afectaba a sistemas Windows, hasta encabezados IP
malformados que tiran al sistema operativo más seguro del Mundo (OpenBSD).
Para dicha demostración, es importante recalcar y observar a nivel conceptual, que la pila de red
trabaja en modo no privilegiado, y regularmente, es posible interactuar con ella a través de IPC
(comunicación entre procesos). Como se observa en la siguiente figura, si esta falla, las demás
aplicaciones y servicios del sistema operativo residentes en modo usuario continuarán con su
operación normal sin afectar a otras partes del núcleo:
Tomada de: http://www.eecs.harvard.edu/~mdw/course/cs161/notes/osstructure.pdf
Recientemente he estado ‘jugando’ con MINIX 3, creado por Andrew S. Tanenbaum, el cual está
basado en un micronúcleo y es el sistema operativo por excelencia para fines educativos, aunque
últimamente el mismo Andrew ha apostado por el mercado de dispositivos embebidos [3]. Hace un
par de días estaba leyendo partes del código de fuente, y viendo una cabecera en específico,
minix/include/net/gen/tcp_hdr.h, me di cuenta de algunas macros definidas con el nombre
TCP_OPT_* referentes a opciones TCP [4], las cuales no son muy comunes en comunicaciones
normales y por lo tanto, algunos programas fallan al procesar dichos bytes extra, como en este
caso. Para ello, decidí fuzzear dichos bytes al final de la cabecera TCP para finalmente descubrir
un bug en la pila TCP/IP de MINIX 3 que a continuación describo.
Paréntesis importante: hoy en día existen muchísimos “expertos en seguridad” que jamás han
creado/analizado paquetes TCP/IP artesanalmente, es decir, campo por campo; byte a byte;
calculando checksums; y la mayoría de los que lo ha hecho es con la ayuda de herramientas como
hping o nemesis, lo cual no es malo, al contrario, para qué rehacer la rueda si estos programas nos
facilitan la vida, sin embargo, considero que es sumamente importante tener conocimientos del
penúltimo nivel de abstracción (diría que el último es a nivel bits y hardware) para mayor
entendimiento de protocolos más arriba, y menos abstractos, de la capa OSI. Para esto,
recomiendo muchísimo leer tutoriales de creación de raw sockets como el bien conocido “Beej's
Guide to Network Programming - Using Internet Sockets” [5] o el tutorial de Mixter [6], reconocido
hacker creador de famosas herramientas como “Tribe Flood Network” y “Six/Four System” de cDc
(Cult of the Dead Cow).
Volviendo al tema. El fallo descubierto fue en el código en minix/net/inet/generic/tcp_lib.c que
analiza las opciones TCP, el cual entra en un loop infinito al enviar un cero en el segundo byte de
los últimos cuatro después del encabezado TCP, el cual corresponde a la longitud de las opciones
TCP, por ejemplo: [IP][TCP]["\xff\x00\x00\x00"]. Para que la pila TCP/IP no descartara paquetes sin
checksum, o checksum erróneo, y considerara estos bytes extra, fue necesario decirle que la
longitud del encabezado son 24 bytes, en vez de 20 como normalmente es, y además, calcular el
checksum correcto [7] con estos cuatro bytes incluidos. Después de crear el código de concepto y
poder reproducir dicho bug, decidí reportarlo a los programadores de MINIX, quienes en menos de
24 horas corrigieron el fallo (aplausos!): “MINIX 3.3.0 Remote TCP/IP Stack Denial of Service
(malformed TCP options)”.
Mucha boca y poco arte… Vamos directo a la prueba de concepto utilizando el siguiente código
para explotar este fallo: http://www.exploit-db.com/exploits/35302/. Las partes más importantes,
además del payload (“\xff\x00\x00\x00”), son TCP->th_off y los checksums calculados con
la función _checksum(), ya que si estos valores son incorrectos, al llegar a la pila TCP/IP estos
paquetes son descartados por el sistema operativo automáticamente sin continuar con su análisis:
Desde un Linux es muy sencillo compilar y ejecutar dicho código:
En otra ventana es posible observar claramente que los pings ya no son respondidos justo después
de que el paquete malformado ha sido recibido y procesado por MINIX 3:
Finalmente podemos constatar en la consola de MINIX 3 que a pesar de que la pila de red quedó
en un ciclo infinito sin poder procesar ninguna petición de red más, es posible seguir realizando
otras tareas y usar otras aplicaciones, excepto todas las que tengan qué interactuar con la red
(como ifconfig):
Y bueno, “esa”, es una de las GRANDES ventajas de un microkernel.
Así como MINIX, hay muchos sistemas operativos allá afuera que están realizando operaciones
críticas, recibiendo y enviando paquetes TCP, y los cuales posiblemente no han llegado a las
manos de hackers que descubran sus vulnerabilidades para remediarlas y por ende hacer de ellos
mejores sistemas operativos. También, qué decir de los muchos sistemas operativos en sistemas
embebidos y de los más caros y avanzados RTOS (Real Time Operating System) que no están a
disposición de cualquiera con 20 dólares en la bolsa, como por ejemplo, VxWorks, que está ahora
en robots y naves espaciales a miles de kilómetros del Punto Azul Pálido. Con su kernel monolítico,
¿quién puede asegurarnos que ha sido probado ampliamente para minimizar al máximo el número
de posibles fallas? ¿y si no? ¿y si alguien (autorizado) desde la Tierra manda paquetes
malformados a un robot con este SO al espacio?.
Para concluir, si ustedes tienen acceso a PLCs (comúnmente usados en plantas industriales e
infraestructura crítica [ICS / SCADA]) u otros sistemas operativos en dispositivos embebidos o
RTOS, no sería mala idea fuzzearlos en un entorno controlado y autorizado para descubrir
vulnerabilidades y remediarlas antes de que los malos lo hagan. Pueden hacerlo utilizando el
código de concepto mostrado arriba, haciendo combinaciones de los últimos cuatro bytes de forma
aleatoria quizás. Si encuentran algo, no duden en compartírnoslo por aquí.
Gracias por su lectura.
Alejandro Hernández
@nitr0usmx
Referencias:
[1] LINUX is obsolete
https://groups.google.com/forum/#!topic/comp.os.minix/wlhw16QWltI[1-25-false]
[2] Tanenbaum-Torvalds Debate: Part II
http://www.cs.vu.nl/~ast/reliable-os/
[3] MINIX 3 at the Embedded World Exhibition in Nuremberg
https://www.youtube.com/watch?feature=player_detailpage&v=vlOsy0PZZyc#t=38
[4] TCP Option Kind Numbers
http://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-parameters-1
[5] Beej's Guide to Network Programming - Using Internet Sockets
http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html
[6] A brief programming tutorial in C for raw sockets
http://gonullyourself.org/library/A%20brief%20programming%20tutorial%20in%20C%20for%20raw%
20sockets.txt
[7] TCP Checksum Calculation and the TCP "Pseudo Header"
http://www.tcpipguide.com/free/t_TCPChecksumCalculationandtheTCPPseudoHeader-2.htm
Descargar