16 mayo 2014

Llevo tiempo con ganas de profundizar en la creación de módulos de Metasploit, e inspirado por los artículos (primera, segunda, tercera y cuarta parte de la serie) de Alberto García Illera me decidí a realizar una prueba de concepto orientada a la explotación de una vulnerabilidad detectada realizando reversing de una aplicación en arquitectura x86.

El caso es que por el camino encontré una dificultad basada en las rutas de ejecución que me ha parecido interesante comentar como capítulo previo a escribir el módulo de Metasploit.

El código vulnerable


Para la prueba de concepto he partido de un código típico vulnerable a stack based buffer overflow (enlace a Pastebin), y como el objetivo era llegar a escribir el módulo de Metasploit, vamos a ponernos las cosas más fáciles desactivando el ASLR y algunos mecanismos de protección durante la compilación del código:


Algunos detalles sobre el código:

  • Con idea de centrarme en el problema que nos ocupa, no entraré en los detalles de la explotación de este código. Veréis que es muy simple y además disponéis de artículos que os mostrarán con todo lujo de detalles esta técnica, como por ejemplo este de exploit-db.
  • Identificaréis que hay una función sleep para detener la ejecución durante 1 segundo, más adelante la necesitaremos.


Explotación


Una vez compilado el código, logramos realizar una explotación desde GDB a través de la siguiente entrada:


La sorpresa aparece cuando intentamos lograr el mismo resultado con la misma entrada fuera de GDB:


¿Por qué obtenemos un segmentation fault en este caso?
La respuesta la encontramos si prestamos atención a cómo ha ejecutado GDB nuestra aplicación: ha ejecutado el binario utilizando la ruta absoluta en lugar de una relativa como he hecho yo. Probemos entonces con la ruta absoluta:


Esta vez hemos logramos la explotación, entonces ¿qué es lo que está pasando?.

Analizando el problema


Para acercarnos a la raíz del problema podemos utilizar el siguiente código (enlace a Pastebin).
Si lo ejecutamos nos mostrará las variables de entorno y nos permitirá identificar las diferencias, de modo que si enfrentamos las salidas entre ejecutar el código con la ruta relativa (parte izquierda de la siguiente imagen) y ejecutarlo con la ruta absoluta (parte derecha), veremos como la ruta nos afecta a la ejecución:


Tenéis una buena explicación en este enlace a stackoverflow, pero en resumen y en este caso en particular el problema es que argv[0] contiene la ruta a la aplicación ejecutada, y al ser un parámetro recibido por la aplicación se empujará a la pila, suponiendo un desplazamiento en las direcciones de memoria y provocando un SIGSEGV si no se ejecuta en igualdad de condiciones.

Reinventando la rueda


Tenemos claro que el problema se resuelve utilizando la ruta absoluta, pero si somos un poco persistentes podemos lograr que funcione también desde su ruta relativa además de conocer otra herramienta interesante:

Botox es una herramienta para facilitar la captura y depuración de procesos de corta duración. Detectará cuando un proceso entra en ejecución (observando el directorio /proc), lo pausará y después lo enviará a gdbserver para realizar su depuración.

Lo preparamos para su ejecución:

  • Descarga desde su repositorio: svn checkout http://botox.googlecode.com/svn/trunk/ botox-read-only
  • Accedemos al directorio:   cd botox-read-only/src
  • Compilamos el código descargado:  ./configure && make

Ponemos botox a la escucha:


Y ejecutamos el binario a analizar:


Iniciamos GDB contra nuestro programa. nos conectamos a la depuración en remoto y establecemos nuestros breakpoints:


Recuperamos la ejecución del proceso pausado:


Ya podemos continuar la depuración desde GDB y realizar el análisis como lo haríamos de forma habitual:


Dejándonos ver como el shellcode cae en la dirección de memoria 0xbffff4b0 cuando se ejecuta la aplicación utilizando la ruta relativa y permitiéndonos explotar la vulneabilidad desde esta:




Conocida esta diferencia puedo volver a lo que me ocupaba desde el principio: en el siguiente artículo escribiremos un módulo de Metasploit para realizar la explotación sobre este ejemplo.

Artículo cortesía de Miguel Ángel García
Twitter: @nodoraiz

4 comments :

Stacked dijo...

Tengo una duda, ¿para que es la variable de entorno "_" que es la que cambia de uno a otro?


Un saludo.

anteladuda dijo...

Lo he leído por encima y a lo mejor estoy diciendo una chorrada... pero hay algo que no me terminar de quedar claro: ¿por qué quieres retornar a la dirección exacta en vez de colocar unos NOPs? O en caso de tratarse de un buffer pequeño, ¿por qué no usas una variable de entorno para colocar NOPs+ SHELLCODE y desbordas el buffer con el retaddrr de la variable que controlas?

Miguel Ángel García dijo...

Hola!,
Desde luego las preguntas que planteas son opciones a tener en cuenta durante la explotación, pero el objetivo del artículo no era saltar a la dirección exacta, era sólo un medio para explicar cómo cuando hacemos reversing nos vemos afectados por factores externos a la propia ejecución del código.

Miguel Ángel García dijo...

Es justo lo que nos muestra en ambos casos: cuando en una shell se ejecuta un comando externo, se define esa variable en el proceso creado almacenando la ruta a ese comando.