Ilustración abstracta de formas geométricas superpuestas en morado, turquesa, blanco y rojo

Vulnerabilidades y Ataques Informaticos

BoF y los "egg hunter" en Kolibri v2.0 HTTP Server

Hoy, vamos a ver uno de los ejercicios de ciberseguridad [https://ciberseguridad.blog/] del curso que tiene CORELAN [https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/] . Vamos con el ejercicio 3, el servidor versión Kolibri v 2.0 : Creamos una página inicial “index.htm” con el contenido que más le guste a uno y le cambiamos la ruta, donde se encuentre ese index. Y comprobamos que al darle al botón “Start”, y que inicia correctamente, se ve en nu

Hoy, vamos a ver uno de los ejercicios de ciberseguridad del curso que tiene CORELAN. Vamos con el ejercicio 3, el servidor versión Kolibri v 2.0 :

Ventana Acerca de Kolibri mostrando la versión 2.0 del servidor web

Creamos una página inicial “index.htm” con el contenido que más le guste a uno y le cambiamos la ruta, donde se encuentre ese index.

Kolibri WebServer y Notepad++ mostrando el código HTML index.htm y la página demo

Y comprobamos que al darle al botón “Start”, y que inicia correctamente, se ve en nuestro navegador, por ejemplo el Google Chrome.

Como tampoco queremos reinventar la rueda y sabemos que es vulnerable, buscamos por donde irán los tiros…

Página de exploit-db sobre el desbordamiento de búfer HEAD del servidor Kolibri 2.0

Vale así que el método HEAD tiene problemas, jeje. Vamos que peta por algún sitio.

Detalle del módulo Metasploit exploit/windows/http/kolibri_http para el desbordamiento de Kolibri

Y además hay publicado un exploit para el metasploit:

Código Ruby del exploit Metasploit generando un egg hunter para el payload

Vale, pero ¿queremos ir a tiro hecho? ¡¡¡Claro que no!!! Nos gusta complicarnos y encontrar donde peta. ¿Y cómo buscarlo? Fuzzeando que es gerundio :P

Creo un sencillo script en Perl, ya sabéis que me encanta y para estas cosas es lo más rápido (para mí :P), pero en la máquina de Corelan no está el Active Perl instalado. Como no quiero tocarla mucho, utilizo un programa mío para redireccionar las peticiones desde mi PC host a la virtual de Corelan, ya que este servicio corre en la dirección localhost:

Iconos de Fuzzing_Kolibri.pl y HTTPTunnel.exe junto a la ventana de uso de HTTP Tunnel
Consola de Windows con netstat mostrando el puerto 8080 en escucha junto a HTTP Tunnel

Cambiamos el adaptador de red:

Configuración de red de VirtualBox con reglas de reenvío del puerto TCP 8081

Y abrimos una regla para que en el puerto 8081 de nuestra máquina vaya hacia el de la virtual.

$ nmap -sT -p8081 localhost

Starting Nmap 6.47 ( http://nmap.org ) at 2015-06-10 10:13 CESTNmap scan report for localhost (127.0.0.1)Host is up (0.000028s latency).PORT     STATE SERVICE8081/tcp open  blackice-icecap

Nmap done: 1 IP address (1 host up) scanned in 0.03 seconds

Bien, parece que funciona:

Navegador mostrando la página Demo de Exploiting en localhost puerto 8081

A lo que iba, creo el script en Perl sencillito, sin hilos ni nada:

Código Perl del script Fuzzing_Kolibri.pl enviando peticiones HEAD con cadenas de A

Este es el aspecto que tendría una vez se está ejecutando el script:

Terminal con errores 404 repetidos junto al registro del servidor Kolibri WebServer

Y catapum!

Explorador de Windows con el icono Kolibri.exe y el diálogo de fallo del programa

Veamos los detalles:

Ventana de detalles del informe de error de Kolibri.exe con la dirección de memoria del fallo
Bloc de notas con el archivo sd85_appcompat.txt y el diálogo de error de Kolibri.exe superpuesto

Bueno, de esta forma poca cosa, ¿qué nos dirá el debugger?

Parece que el fallo viene cuando le pasas unas 215 ó 216 A…. seguramente el primero, así que lo compruebo.

Terminal mostrando errores 404 seguidos del mensaje Error 500 read timeout que provoca el fallo

Lo comprobamos:

Editor con las pestañas Fuzzing_Kolibri.pl y Fuzzing_Kolibri_215A.pl mostrando el valor fijo 215

Y efectivamente, peta al enviarle 215 A con el método HEAD, pero con ese tamaño no controlamos el EIP ni nada….

Terminal ejecutando Fuzzing_Kolibri_215A.pl junto al diálogo de fallo de Kolibri WebServer

Lo abrimos con el Inmunity:

Immunity Debugger adjunto al proceso Kolibri.exe junto a la ventana de Kolibri WebServer

configuramos mona.py:

Registro de Immunity Debugger con los módulos cargados y el comando mona config workingfolder

Creo este otro script y lo lanzo:

Editor con tres versiones del script Perl mostrando patrones de bytes A, B y C
Immunity Debugger mostrando una violación de acceso tras enviar el patrón de fuzzing AAAABBBBCCCC

Vale, así que el EIP lo controlaré gracias a la zona en donde metí las C (43434343).

A mí el moma este no me guarda lo que necesito :P así que voy a explotarlo como antaño, jeje.

Creo el script con un patrón creado con el patter_create:

Script Perl con el patrón único generado por mona.py asignado a la variable pattern

Y lo mismo:

Immunity Debugger muestra un fallo de escritura en Kolibri.exe durante el fuzzing con Perl

Pufff! Ese EIP parece una dirección de memoria, no algo que yo le haya metido en ese string… así que parece que aquí el tamaño importa…. Lo voy a acortar, lo dejaré en unos 600 en total.

Terminal muestra error 404 y patrón cíclico causando una violación de acceso al ejecutar EIP

El EIP es: 32724131 -> 2rA1 -> Little Endian -> 1Ar2

Cuadro de diálogo Buscar en Immunity Debugger localizando el patrón cíclico 1Ar2
Notepad++ con el patrón cíclico completo y la subcadena 1Ar2 resaltada

Vale, nosotros controlamos el servidor… pero ¿y si no tuviésemos ese control?

Nos la tenemos que jugar y jugar significa utilizar direcciones estándar para un Sistema Operativo concreto, en este caso un Windows XP SP3 (de la máquina Virtual de Análisis de Malware, no la de Corelan). Como veremos en el ejercicio 2, localicé un JMP ESP en kernel32 y utilizaré la misma:

Consola cmd ejecutando findjmp sobre kernel32.dll y hallando tres direcciones jmp esp

Vale, entonces nuestro primer exploit para ejecutar la calculadora de Windows y que utilicé en el ejercicio 2 sería:

Editor de código Perl del exploit_Kolibri_byRafa.pl con shellcode y petición HTTP a Kolibri

Vamos muy parecido la forma de explotarlo en remoto, de esta forma pero creo que no funcionará…

Terminal con la respuesta 404 y el shellcode NOP en hexadecimal devuelto por Kolibri

Pero esto qué es!!! Normal, hay que modificar el script original. Lo sé, juega con el “pack”, blah, blah, blah! Pero yo soy de la opinión de si algo no te gusta, cámbialo! No vayas hasta el final con algo que no te gusta sólo porque sí, cámbialo, mejóralo!

Código Perl del exploit usando IO::Socket::INET para conectar y enviar la petición GET

Lo probamos, no hay nada como usar sockets :P

Immunity Debugger muestra los registros sobrescritos con la cadena de A tras el exploit

Pero no hace nada… cachis. Voy a ver la dirección de memoria que puse… pues no está L Normal, no tiene porqué tener las mismas direcciones en máquinas distintas, ese es uno de los problemas más comunes a la hora de programar un exploit en la que no calculas la dirección en el mismo. Primer zas en toda la boca, como decía alguno! jeje

Consola cmd con findjmp escaneando ntdll.dll y listando cuatro direcciones jmp o push esp-ret

La modifico por una de las existentes:

Código Perl con la dirección EIP del jmp esp hallada con findjmp anotada en rojo
Immunity Debugger con el registro mostrando la cadena calc.exe tras la ejecución del shellcode

Calc.exe, lo vemos… pero… nop ¿Qué ha pasado?

Ventana de error de Immunity Debugger por memoria no legible en la dirección 77BF93C7

Eh! Esa no era mi dirección… ¿os acordáis lo que conté al principio del tamaño importa?

Además si nos fijamos en los registros:

Panel de registros FPU de Immunity Debugger con la cadena calc.exe en la pila

Estoy saltando a una dirección en la que antes, hay código. Parece que eso no funciona…. Pensemos un poco… parece que podríamos controlar ebp, salta allí….

Vale, si le metemos la salida del pattern_create:

Immunity Debugger con violación de acceso al ejecutar la dirección del patrón cíclico 1Ar2

Así que esto debería funcionar:

Código Perl del exploit con el EIP actualizado y el shellcode antes del control esp

Por más que pruebo no funciona…. No será por esto?

Dependency Walker con la calculadora abierta y la tabla de funciones y puntos de entrada

Nueva shellcode:

Desensamblado construyendo la cadena calc.exe byte a byte antes de la llamada a EBX

Me estoy volviendo loco para calcular como saltar al sitio, estoy desanimado, así que lo dejo para el día siguiente :-D Eso sí, dándole vueltas en la cabeza.

Un poco de ficción: llega la tarde y mi hija me dice….

Hija: papá ponme la peli de los boxtrolls, por favor (Es muy educada)

Yo: Claro, ahora mismo. - Conecto el disco duro y se la pongo –

Al rato…

Hija: has visto, papá, los malos quieren “cazar a Eggs”.

Yo: ¿Cómo? ¿qué has dicho?

Hija: que los malos quieren cazar a Eggs.

Este es Eggs:

Fotograma de la película de animación Los Boxtrolls con el personaje Eggs y varios boxtrolls

Yo: Uhmmmm! Gracias, hija, me has dado una idea :P

Fin del poco de ficción.

Hablemos del mineralismo y de los “eggs hunters”

Ó de esta técnica utilizada por los exploiters…

Supongamos que podemos poner en la memoria un string, como “egg”, “FreeKevin”, o lo que más os guste, pudiésemos buscarlo y al encontrarlo, saber donde ejecutar la shellcode que nosotros hemos puesto a continuación…

Supongamos que como decía que el tamaño importa, solamente podemos poner un trocito de código aquí, otro allí….. que el primero busque el segundo (ahí no tenemos problemas de espacio) y ejecutar lo que queramos….

El flujo de ejecución sería algo similar a esto:

  1. En el primer buffer (limitado) introducimos nuestro cazador de huevos (egg hunter).
  2. Una vez controlamos el EIP (nuestro caso) apuntamos al segmento de memoria anterior para poder ejecutar el egghunter.
  3. El egghunter busca nuestra shellcode en toda la memoria (al ser un proceso proceso cíclico, consumirá recursos en el PC, se quedará como “pensando”, es lo que siempre me dicen cuando parece que el proceso está cuasi colgado :P).
  4. El EIP se sobreescribirá con la nueva dirección de memoria de la shellcode que haya encontrado y la ejecutará.

Sería esto:

Diagrama de diapositiva que explica la implementación del egg hunter con ESP y EIP

Parece parte de la historia de ficción de los boxtrolls, pero no, esto es real al 100% :P

Al lío. Volvemos a calcularlo todo, esta vez con otro pensamiento de explotación en la mente, el ejercicio 3 es diferente, como nosotros, jeje.

Gracias a Alberto, que me envió un tutorial sobre el funcionamiento del Mona :-D

Immunity Debugger con el log de findmsp mostrando el offset del patrón cíclico en ESP

Sacamos el ESP, aunque deberían funcionar cualquiera, a mí me funcionó con la que está subrayada:

Ventana de Immunity Debugger listando módulos con banderas ASLR, Rebase y SafeSEH

Ejecutamos el comando para que nos guarde el “cazador de huevos”, como suena:

Log de mona.py en Immunity Debugger con nota sobre guardar el código del egg hunter
Fichero egghunter.txt de mona.py con la etiqueta w00tw00t que debe buscar el egg hunter

Utiliza NTAccessCheckAndAuditAlarm:

Código ensamblador comentado del egg hunter explicando la búsqueda de la etiqueta página a página

Todo esto viene en los siguientes enlaces explicado:

  1. Egghunt Shellcode
  2. Heap
  3. Heap Only Egg Hunter

Leedlo, si no lo habéis hecho ya :P

Consideraciones para que todo esto funcione:

  • La palabra que busquemos debería ser única (cómo haya repes, como los cromos de fútbol cuando solamente te quedaban unos poco, fallará)
  • Es necesario definir la etiqueta de 4 bytes en el interior del egg hunter, y hacerlo 2 veces (2 veces después de cada uno, en total 8 bytes) antes de nuestra Shellcode que queremos explotar.
  • Hay varias técnicas para buscar en memoria y no todas tienen porqué funcionarte. (NTAccessCheckAndAuditAlarm es la que he utilizado y funciona, viene explicado aquí ).
  • Cada técnica es diferente y requieren un espacio determinado disponible para introducir nuestro código del egg hunter.

Vale, con todo esto ya tendríamos preparado el exploit, solamente hay que comprobar que funciona:

Código del exploit Kolibri en Perl anotado explicando el egg hunter NTAccessCheckAndAuditAlarm

Y el resultado: FUNCIONA !!!

Calculadora de Windows abierta y terminal con la respuesta HTTP 404 tras explotar Kolibri

Así que hemos dado con la forma de explotar la vulnerabilidad en el servidor web Kolibri v2.0.

¿Nos arriesgamos con una Shell? La generamos con Metasploit: Shell_bind_tcp en el puerto 4444

Terminal de Metasploit generando shellcode alfanumérico x86/alpha_mixed con msfpayload para una shell TCP

La copiamos a nuestro exploit:

Editor gedit mostrando el shellcode del egg hunter para una shell en el puerto 4444

Lo ejecutamos y….

Explorador de Windows, panel de configuración de Kolibri WebServer y terminal con error HTTP 404

Shell al canto.

Símbolo del sistema de Windows ejecutando telnet hacia la IP 10.0.3.15 por el puerto 4444

Nos conectamos para ver el resultado:

Sesión telnet mostrando el listado de directorio de Kolibri-2.0-win con kolibri.exe y license.txt

Estamos en el directorio del servidor vulnerable.

Pues nada, espero que os guste, yo me lo he pasado muy bien buscando y explotando la vulnerabilidad ;-)

Temas

No hay comentarios todavía