jueves, 30 de agosto de 2012

Explotando CVE-2012-4681 (Java 0-day)

Como ya sabréis, el pasado domingo se publicaba en el blog de FireEye la existencia de un exploit 0-day para Java que estaba siendo utilizado para infectar a los usuarios que navegaran por las webs controladas por los atacantes. Este tema ha sido ampliamente tratado en otros blogs durante estos días, tanto de habla Inglesa como Española (y entiendo que en todos los idiomas): SecurityByDefault, S21sec, Immunity, Hexale, Hispasec, Snort, AlienVault, etc (sin ningún orden concreto, tal y como los tengo en las pestañas del navegador).

En alguno de estos blogs mencionan la publicación del código fuente del exploit en Pastie.Org como si fuera el código fuente original, pero a mi me da la sensación de que es una PoC creada por jduck que posteriormente se ha convertido en un módulo para Metasploit.

Como ya conocéis todos mi debilidad por este framework, vamos a pegar un vistazo al módulo que han creado los chicos de Rapid7 para Metasploit, que podemos encontrar en "modules/exploits/multi/browser/java_jre17_exec.rb":


No sé si muchos de vosotros lo sabéis, pero no todos los exploits de Metasploit se encuentran 100% programados en Ruby. Algunos de ellos se encuentran programados aparte, y el módulo de Metasploit lo que hace es modificar el binario para añadir el Payload que elegimos desde el framework. Estos exploits programados aparte se encuentran en el directorio "data/exploits/". Concretamente, en éste módulo podemos ver como genera el payload que haya elegido el usuario, se codifica como un JAR y se "mezcla" con los ficheros existentes en "data/exploits/CVE-2012-XXXX/".

En este directorio tenemos un fichero "Exploit.class" que por supuesto podríamos decompilar y estudiar su contenido, pero es más inmediato ir al directorio donde Metasploit se guarda los códigos fuente de las partes que lleva compiladas (Meterpreter, elevación de privilegios o, como en este caso, Java): "external/source/".

En este directorio, dentro de "exploits/CVE-2012-XXXX/" podemos encontrar un fichero "Exploit.java" que es el código fuente del class del que hablamos antes. Si le pegamos un vistazo encontramos que realiza una única llamada a una función "disableSecurity()", que es la que lleva toda la chicha y otorga permisos de master del universo a la instancia, para luego ejecutar el payload que se haya elegido. En el código publicado por jduck era una calculadora y aquí lo han cambiado por un payload de Metasploit, pero el resto del código es identico.


Aquí entraríamos al análisis del propio exploit, que vamos a hacer muy por encima, ya que otros blogs se han ocupado de ello. Una de las cosas que vas a leer en otros blogs si decides profundizar más es que hablan mucho de que el exploit hace cosas "por reflexión". Si no eres un programador de Java o una persona que ya haya investigado con anterioridad sobre estos temas, es posible que no entiendas que quiere decir con "Reflexión": La manera habitual de utilizar un objeto es llamar a sus métodos, pero Java permite realizar ciertas acciones sobre ellos como listarlos, llamarlos e incluso cambiarlos, algo que no es posible en otros lenguajes y que recibe el nombre de "Reflexión".

En este caso vamos a optar por una explicación Top-Down. Vamos a suponer que existe una función mágica "SetField" que es capaz de cambiar el contenido de cualquier campo de cualquier objeto a nuestro gusto, y vamos a ver si entendemos que hace "disableSecurity()": No he encontrado documentación sobre el campo "acc", pero se comenta en la información publicada que es un método privado y que en principio no debería ser accesible más que desde el propio objeto, por lo que es posible que no se encuentre documentado. Esta función crea un objeto del tipo AccessControlContext con todos los permisos y se lo asigna a "acc". Al ejecutar ese Statement, el nuevo contexto es aplicado, con lo que a partir de este momento todo lo que se ejecuta lo hace sin ningún tipo de restricciones.

Pero... eso es confiado en la magia de "SetField" ¿cómo lo hará?


Aquí viene el primero de las vulnerabilidades utilizadas en este exploit. Siguiendo la linea de lo que hemos hecho antes, vamos a suponer que el método "GetClass" es un método que nos permite obtener de algún modo cualquiera de las clases que existan, independientemente de sus restricciones. Como podemos ver, se obtiene por reflexión el método "sun.awt.SunToolkit->getField()", que nos va a permitir acceder al campo que queramos del objeto que queramos, aunque sea privado (en este caso, por la llamada anterior, "acc"). Una vez que este campo es accesible, se puede cambiar su contenido con lo que la magia de esta función queda explicada.

Según he podido leer, este es el punto que hace que la vulnerabilidad funcione en jre7 pero no en jre6, ya que parece ser que el método getField() no puede ser accedido con esta técnica en jr6.

Pero claro, todo esto suponiendo que podemos acceder a "sun.awt.SunTookit", que como todos los objetos "sun.*" no debería ser accesible desde un Applet. Aquí viene la segunda de las vulnerabilidades. Vamos a ello:


En este caso, se usa una vulnerabilidad en "com.sun.beans.finder.ClassFinder.findClass" pero que se explota a través de una llamada a "forName" para poderse saltarse la restricción que comentábamos anteriormente y poder acceder al objeto "sun.awt.SunToolkit".

Si ahora todo esta magia, juntita y con un poco de Metasploit de por medio y tenemos...


Solo una cosa a tener en cuenta, en este caso no todos los Payloads habituales son compatibles con este exploit (por la forma en que ha sido programado). Si por ejemplo intentais utilizar el Meterpreter "tradicional" no os va a funcionar. Podeis mirar con el comando "show payloads" cuando estéis dentro del módulo cuales son los Payloads compatibles, que veréis que básicamente son un par de los genéricos y los de Java. En mi caso yo he usado el Meterpreter Java. Por supuesto, una vez obtenido el control del sistema, nada os impide subir el Meterpreter nativo.

Si quereis información en más en profundidad, sin desmerecer el gran trabajo que han hecho en otros blogs, a mi me ha gustado particularmente el de Immunity, por el gran detalle a bajo nivel y las referencias a la documentación oficial de Sun. Si por el contrario estás más preocupado de como protegerte, en SecurityByDefault han publicado las formas en las que podemos deshabilitar Java de los principales navegadores. Si trabajas en una empresa y no puedes permitirte deshabilitar Java porque usais aplicaciones internas que emplean applets Java, siempre tenéis la opción de bloquear las páginas con Applets Java en el perímetro, en los proxies o similar.

7 comentarios :

José A. Guasch dijo...

Efectivamente, el código de pastie.org es del propio jduck a modo de poc, En el tweet donde anunció dicho código es dónde adelantó que el módulo de metasploit estaba en camino ;)

Villaveiran dijo...

Excelente artículo, muchas gracias por la explicacion XD

Jose Selvi dijo...

@José A. Guasch: Sí, de hecho eso que comentas, si no recuerdo mal, está en los comentarios del propio PoC, pero en algún sitio leí que alguien decía que era el exploit original, así que no me he querido mojar al respecto, por si acaso :P

Gracias por los comentario!

Francisco Falcon dijo...

El código que publicó jduck *no* es de él. Se trata del código original del exploit, obtenido con un decompiler, al que jduck sólo le modificó qué hacer tras deshabilitar el sandbox.

El exploit original llamaba a un método de una segunda clase, Gondzz, que se descargaba un binario desde un server y lo ejecutaba, mientras que jduck hizo que ejecute una calc a modo de PoC.

Saludos.

Jose Selvi dijo...

@Francisco Falcon: Gracias por el aporte. Como le decía a @José A. Guasch, a mi no me había quedado claro si era el original o no.

Anónimo dijo...

ya tiene parche pero aun funcionaria ?, antes que salga ese exploit , infectaban con javadrive ! aver si me respondes saludos bro

Jose Selvi dijo...

@Anónimo: No lo he probado después de que saliera el parche, pero en principio no debería funcionar, claro :)

Lo que comentas del Javadrive, imagino que te refieres a los Applet firmados ¿no? Los applets firmados funcionan de una forma diferente a los applets sin firmar. Tienen menos restricciones de seguridad, sandbox, etc, porque se supone que son "de confianza". Si un applet está firmado pero no se reconoce al emisor (lo que sucede con estos ataques que comentas) aparece un mensaje de advertencia que los usuarios deben aceptar para ejecutarse.

La ventaja de estos exploits de java que han ido saliendo en estos últimos meses es que son applets normales, así que no pide ningún tipo de permiso al usuario, y luego se salen de la sandbox, así que tenemos el mismo efecto sin hacer tanto ruido.

Espero que esto responda a tu pregunta.
Gracias por el comentario!