From 12f47bcf249b353e6bcec34073833e6a94eb2690 Mon Sep 17 00:00:00 2001
From: haby0
Date: Wed, 12 May 2021 12:18:26 +0800
Subject: [PATCH 1/9] Add UnsafeDeserialization
---
.../CWE/CWE-502/UnsafeDeserialization.qhelp | 20 +-
.../CWE/CWE-502/UnsafeDeserialization.ql | 33 ++
.../semmle/code/java/frameworks/Castor.qll | 20 ++
.../semmle/code/java/frameworks/Hessian.qll | 47 +++
.../src/semmle/code/java/frameworks/JYaml.qll | 41 +++
.../semmle/code/java/frameworks/JsonIo.qll | 41 +++
.../semmle/code/java/frameworks/YamlBeans.qll | 20 ++
.../java/security/UnsafeDeserialization.qll | 49 +++
.../test/query-tests/security/CWE-502/C.java | 98 ++++++
.../CWE-502/UnsafeDeserialization.expected | 67 ++++
.../test/query-tests/security/CWE-502/options | 2 +-
.../org/exolab/castor/types/AnyNode.java | 11 +
.../org/exolab/castor/xml/EventProducer.java | 12 +
.../castor/xml/SAX2EventAndErrorProducer.java | 8 +
.../exolab/castor/xml/SAX2EventProducer.java | 11 +
.../org/exolab/castor/xml/Unmarshaller.java | 74 +++++
.../caucho/burlap/io/AbstractBurlapInput.java | 9 +
.../burlap/io/AbstractHessianInput.java | 110 +++++++
.../burlap/io/AbstractSerializerFactory.java | 11 +
.../com/caucho/burlap/io/BurlapInput.java | 274 ++++++++++++++++
.../com/caucho/burlap/io/Deserializer.java | 26 ++
.../burlap/io/HessianProtocolException.java | 24 ++
.../com/caucho/burlap/io/Serializer.java | 8 +
.../caucho/burlap/io/SerializerFactory.java | 12 +
.../hessian/io/AbstractHessianInput.java | 111 +++++++
.../com/caucho/hessian/io/Hessian2Input.java | 297 ++++++++++++++++++
.../com/caucho/hessian/io/HessianInput.java | 229 ++++++++++++++
.../hessian/io/HessianRemoteResolver.java | 8 +
.../caucho/hessian/io/SerializerFactory.java | 5 +
.../com/cedarsoftware/util/io/JsonReader.java | 41 +++
.../stubs/jyaml-1.3/org/ho/yaml/Yaml.java | 77 +++++
.../jyaml-1.3/org/ho/yaml/YamlConfig.java | 122 +++++++
.../jyaml-1.3/org/ho/yaml/YamlDecoder.java | 16 +
.../jyaml-1.3/org/ho/yaml/YamlOperations.java | 63 ++++
.../jyaml-1.3/org/ho/yaml/YamlStream.java | 7 +
.../yamlbeans/YamlConfig.java | 7 +
.../yamlbeans/YamlException.java | 18 ++
.../yamlbeans/YamlReader.java | 28 ++
38 files changed, 2054 insertions(+), 3 deletions(-)
create mode 100644 java/ql/src/semmle/code/java/frameworks/Castor.qll
create mode 100644 java/ql/src/semmle/code/java/frameworks/Hessian.qll
create mode 100644 java/ql/src/semmle/code/java/frameworks/JYaml.qll
create mode 100644 java/ql/src/semmle/code/java/frameworks/JsonIo.qll
create mode 100644 java/ql/src/semmle/code/java/frameworks/YamlBeans.qll
create mode 100644 java/ql/test/query-tests/security/CWE-502/C.java
create mode 100644 java/ql/test/stubs/castor-1.4.1/org/exolab/castor/types/AnyNode.java
create mode 100644 java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/EventProducer.java
create mode 100644 java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/SAX2EventAndErrorProducer.java
create mode 100644 java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/SAX2EventProducer.java
create mode 100644 java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/Unmarshaller.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractBurlapInput.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractHessianInput.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractSerializerFactory.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/BurlapInput.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/Deserializer.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/HessianProtocolException.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/Serializer.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/SerializerFactory.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/AbstractHessianInput.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/Hessian2Input.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/HessianInput.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/HessianRemoteResolver.java
create mode 100644 java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/SerializerFactory.java
create mode 100644 java/ql/test/stubs/json-io-4.10.0/com/cedarsoftware/util/io/JsonReader.java
create mode 100644 java/ql/test/stubs/jyaml-1.3/org/ho/yaml/Yaml.java
create mode 100644 java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlConfig.java
create mode 100644 java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlDecoder.java
create mode 100644 java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlOperations.java
create mode 100644 java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlStream.java
create mode 100644 java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlConfig.java
create mode 100644 java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlException.java
create mode 100644 java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlReader.java
diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp
index 61b50a986e3..ce7f4751800 100644
--- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp
+++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp
@@ -14,8 +14,8 @@ may have unforeseen effects, such as the execution of arbitrary code.
There are many different serialization frameworks. This query currently
-supports Kryo, XmlDecoder, XStream, SnakeYaml, and Java IO serialization through
-ObjectInputStream/ObjectOutputStream.
+supports Kryo, XmlDecoder, XStream, SnakeYaml, Hessian, JsonIO, YAMLBeans, Castor, Burlap,
+and Java IO serialization through ObjectInputStream/ObjectOutputStream.
@@ -75,6 +75,22 @@ Alvaro Muñoz & Christian Schneider, RSAConference 2016:
SnakeYaml documentation on deserialization:
SnakeYaml deserialization.
+
+Hessian deserialization and related gadget chains:
+Hessian deserialization.
+
+
+Castor and Hessian java deserialization vulnerabilities:
+Castor and Hessian deserialization.
+
+
+Remote code execution in JYaml library:
+JYaml deserialization.
+
+
+JsonIO deserialization vulnerabilities:
+JsonIO deserialization.
+
diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql
index bb4df03cd4f..3a77af853cf 100644
--- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql
+++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql
@@ -21,6 +21,39 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink }
+
+ override predicate isAdditionalTaintStep(DataFlow::Node prod, DataFlow::Node succ) {
+ exists(ClassInstanceExpr cie |
+ cie.getConstructor().getDeclaringType() instanceof JsonReader and
+ cie.getArgument(0) = prod.asExpr() and
+ cie = succ.asExpr() and
+ not exists(SafeJsonIo sji | sji.hasFlowToExpr(cie.getArgument(1)))
+ )
+ or
+ exists(ClassInstanceExpr cie |
+ cie.getConstructor().getDeclaringType() instanceof YamlReader and
+ cie.getArgument(0) = prod.asExpr() and
+ cie = succ.asExpr()
+ )
+ or
+ exists(ClassInstanceExpr cie |
+ cie.getConstructor().getDeclaringType() instanceof UnSafeHessianInput and
+ cie.getArgument(0) = prod.asExpr() and
+ cie = succ.asExpr()
+ )
+ or
+ exists(ClassInstanceExpr cie |
+ cie.getConstructor().getDeclaringType() instanceof BurlapInput and
+ cie.getArgument(0) = prod.asExpr() and
+ cie = succ.asExpr()
+ )
+ or
+ exists(MethodAccess ma |
+ ma.getMethod() instanceof BurlapInputInitMethod and
+ ma.getArgument(0) = prod.asExpr() and
+ ma.getQualifier() = succ.asExpr()
+ )
+ }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeDeserializationConfig conf
diff --git a/java/ql/src/semmle/code/java/frameworks/Castor.qll b/java/ql/src/semmle/code/java/frameworks/Castor.qll
new file mode 100644
index 00000000000..76abef7b5fe
--- /dev/null
+++ b/java/ql/src/semmle/code/java/frameworks/Castor.qll
@@ -0,0 +1,20 @@
+/**
+ * Provides classes and predicates for working with the Castor framework.
+ */
+
+import java
+
+/**
+ * The class `org.exolab.castor.xml.Unmarshaller`.
+ */
+class Unmarshaller extends RefType {
+ Unmarshaller() { this.hasQualifiedName("org.exolab.castor.xml", "Unmarshaller") }
+}
+
+/** A method with the name `unmarshal` declared in `org.exolab.castor.xml.Unmarshaller`. */
+class UnmarshalMethod extends Method {
+ UnmarshalMethod() {
+ this.getDeclaringType() instanceof Unmarshaller and
+ this.getName() = "unmarshal"
+ }
+}
diff --git a/java/ql/src/semmle/code/java/frameworks/Hessian.qll b/java/ql/src/semmle/code/java/frameworks/Hessian.qll
new file mode 100644
index 00000000000..78798d2b2fb
--- /dev/null
+++ b/java/ql/src/semmle/code/java/frameworks/Hessian.qll
@@ -0,0 +1,47 @@
+/**
+ * Provides classes and predicates for working with the Hession framework.
+ */
+
+import java
+
+/**
+ * The class `com.caucho.hessian.io.HessianInput` or `com.caucho.hessian.io.Hessian2Input`.
+ */
+class UnSafeHessianInput extends RefType {
+ UnSafeHessianInput() {
+ this.hasQualifiedName("com.caucho.hessian.io", ["HessianInput", "Hessian2Input"])
+ }
+}
+
+/**
+ * A HessianInput readObject method. This is either `HessianInput.readObject` or `Hessian2Input.readObject`.
+ */
+class UnSafeHessianInputReadObjectMethod extends Method {
+ UnSafeHessianInputReadObjectMethod() {
+ this.getDeclaringType() instanceof UnSafeHessianInput and
+ this.getName() = "readObject"
+ }
+}
+
+/**
+ * The class `com.caucho.burlap.io.BurlapInput`.
+ */
+class BurlapInput extends RefType {
+ BurlapInput() { this.hasQualifiedName("com.caucho.burlap.io", "BurlapInput") }
+}
+
+/** A method with the name `readObject` declared in `com.caucho.burlap.io.BurlapInput`. */
+class BurlapInputReadObjectMethod extends Method {
+ BurlapInputReadObjectMethod() {
+ this.getDeclaringType() instanceof BurlapInput and
+ this.getName() = "readObject"
+ }
+}
+
+/** A method with the name `init` declared in `com.caucho.burlap.io.BurlapInput`. */
+class BurlapInputInitMethod extends Method {
+ BurlapInputInitMethod() {
+ this.getDeclaringType() instanceof BurlapInput and
+ this.getName() = "init"
+ }
+}
diff --git a/java/ql/src/semmle/code/java/frameworks/JYaml.qll b/java/ql/src/semmle/code/java/frameworks/JYaml.qll
new file mode 100644
index 00000000000..bf523bec202
--- /dev/null
+++ b/java/ql/src/semmle/code/java/frameworks/JYaml.qll
@@ -0,0 +1,41 @@
+/**
+ * Provides classes and predicates for working with the JYaml framework.
+ */
+
+import java
+
+/**
+ * The class `org.ho.yaml.Yaml`.
+ */
+class JYaml extends RefType {
+ JYaml() { this.hasQualifiedName("org.ho.yaml", "Yaml") }
+}
+
+/**
+ * A JYaml unsafe load method. This is either `YAML.load` or
+ * `YAML.loadType` or `YAML.loadStream` or `YAML.loadStreamOfType`.
+ */
+class JYamlUnSafeLoadMethod extends Method {
+ JYamlUnSafeLoadMethod() {
+ this.getDeclaringType() instanceof JYaml and
+ this.getName() in ["load", "loadType", "loadStream", "loadStreamOfType"]
+ }
+}
+
+/**
+ * The class `org.ho.yaml.YamlConfig`.
+ */
+class JYamlConfig extends RefType {
+ JYamlConfig() { this.hasQualifiedName("org.ho.yaml", "YamlConfig") }
+}
+
+/**
+ * A JYamlConfig unsafe load method. This is either `YamlConfig.load` or
+ * `YAML.loadType` or `YamlConfig.loadStream` or `YamlConfig.loadStreamOfType`.
+ */
+class JYamlConfigUnSafeLoadMethod extends Method {
+ JYamlConfigUnSafeLoadMethod() {
+ this.getDeclaringType() instanceof JYamlConfig and
+ this.getName() in ["load", "loadType", "loadStream", "loadStreamOfType"]
+ }
+}
diff --git a/java/ql/src/semmle/code/java/frameworks/JsonIo.qll b/java/ql/src/semmle/code/java/frameworks/JsonIo.qll
new file mode 100644
index 00000000000..4170488f78d
--- /dev/null
+++ b/java/ql/src/semmle/code/java/frameworks/JsonIo.qll
@@ -0,0 +1,41 @@
+/**
+ * Provides classes and predicates for working with the Json-io framework.
+ */
+
+import java
+import semmle.code.java.Maps
+
+/**
+ * The class `com.cedarsoftware.util.io.JsonReader`.
+ */
+class JsonReader extends RefType {
+ JsonReader() { this.hasQualifiedName("com.cedarsoftware.util.io", "JsonReader") }
+}
+
+/** A method with the name `jsonToJava` declared in `com.cedarsoftware.util.io.JsonReader`. */
+class JsonIoJsonToJavaMethod extends Method {
+ JsonIoJsonToJavaMethod() {
+ this.getDeclaringType() instanceof JsonReader and
+ this.getName() = "jsonToJava"
+ }
+}
+
+/** A method with the name `readObject` declared in `com.cedarsoftware.util.io.JsonReader`. */
+class JsonIoReadObjectMethod extends Method {
+ JsonIoReadObjectMethod() {
+ this.getDeclaringType() instanceof JsonReader and
+ this.getName() = "readObject"
+ }
+}
+
+/**
+ * A call to `Map.put` method, set the value of the `USE_MAPS` key to `true`.
+ */
+class JsonIoSafeOptionalArgs extends MethodAccess {
+ JsonIoSafeOptionalArgs() {
+ this.getMethod().getDeclaringType().getASourceSupertype*() instanceof MapType and
+ this.getMethod().hasName("put") and
+ this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "USE_MAPS" and
+ this.getArgument(1).(CompileTimeConstantExpr).getBooleanValue() = true
+ }
+}
diff --git a/java/ql/src/semmle/code/java/frameworks/YamlBeans.qll b/java/ql/src/semmle/code/java/frameworks/YamlBeans.qll
new file mode 100644
index 00000000000..63c282a80ec
--- /dev/null
+++ b/java/ql/src/semmle/code/java/frameworks/YamlBeans.qll
@@ -0,0 +1,20 @@
+/**
+ * Provides classes and predicates for working with the YamlBeans framework.
+ */
+
+import java
+
+/**
+ * The class `com.esotericsoftware.yamlbeans.YamlReader`.
+ */
+class YamlReader extends RefType {
+ YamlReader() { this.hasQualifiedName("com.esotericsoftware.yamlbeans", "YamlReader") }
+}
+
+/** A method with the name `read` declared in `com.esotericsoftware.yamlbeans.YamlReader`. */
+class YamlReaderReadMethod extends Method {
+ YamlReaderReadMethod() {
+ this.getDeclaringType() instanceof YamlReader and
+ this.getName() = "read"
+ }
+}
diff --git a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
index ab809f07d6d..377303601d4 100644
--- a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
+++ b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
@@ -2,6 +2,11 @@ import semmle.code.java.frameworks.Kryo
import semmle.code.java.frameworks.XStream
import semmle.code.java.frameworks.SnakeYaml
import semmle.code.java.frameworks.FastJson
+import semmle.code.java.frameworks.JYaml
+import semmle.code.java.frameworks.JsonIo
+import semmle.code.java.frameworks.YamlBeans
+import semmle.code.java.frameworks.Hessian
+import semmle.code.java.frameworks.Castor
import semmle.code.java.frameworks.apache.Lang
class ObjectInputStreamReadObjectMethod extends Method {
@@ -50,6 +55,29 @@ class SafeKryo extends DataFlow2::Configuration {
}
}
+class SafeJsonIo extends DataFlow2::Configuration {
+ SafeJsonIo() { this = "UnsafeDeserialization::SafeJsonIo" }
+
+ override predicate isSource(DataFlow::Node src) {
+ exists(MethodAccess ma |
+ ma instanceof JsonIoSafeOptionalArgs and
+ src.asExpr() = ma.getQualifier()
+ )
+ }
+
+ override predicate isSink(DataFlow::Node sink) {
+ exists(MethodAccess ma |
+ ma.getMethod() instanceof JsonIoJsonToJavaMethod and
+ sink.asExpr() = ma.getArgument(1)
+ )
+ or
+ exists(ClassInstanceExpr cie |
+ cie.getConstructor().getDeclaringType() instanceof JsonReader and
+ sink.asExpr() = cie.getArgument(1)
+ )
+ }
+}
+
predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
exists(Method m | m = ma.getMethod() |
m instanceof ObjectInputStreamReadObjectMethod and
@@ -81,6 +109,27 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
ma.getMethod() instanceof FastJsonParseMethod and
not fastJsonLooksSafe() and
sink = ma.getArgument(0)
+ or
+ ma.getMethod() instanceof JYamlUnSafeLoadMethod and
+ sink = ma.getArgument(0)
+ or
+ ma.getMethod() instanceof JYamlConfigUnSafeLoadMethod and
+ sink = ma.getArgument(0)
+ or
+ ma.getMethod() instanceof JsonIoJsonToJavaMethod and
+ sink = ma.getArgument(0) and
+ not exists(SafeJsonIo sji | sji.hasFlowToExpr(ma.getArgument(1)))
+ or
+ ma.getMethod() instanceof JsonIoReadObjectMethod and
+ sink = ma.getQualifier()
+ or
+ ma.getMethod() instanceof YamlReaderReadMethod and sink = ma.getQualifier()
+ or
+ ma.getMethod() instanceof UnSafeHessianInputReadObjectMethod and sink = ma.getQualifier()
+ or
+ ma.getMethod() instanceof UnmarshalMethod and sink = ma.getAnArgument()
+ or
+ ma.getMethod() instanceof BurlapInputReadObjectMethod and sink = ma.getQualifier()
)
}
diff --git a/java/ql/test/query-tests/security/CWE-502/C.java b/java/ql/test/query-tests/security/CWE-502/C.java
new file mode 100644
index 00000000000..ede36d8410b
--- /dev/null
+++ b/java/ql/test/query-tests/security/CWE-502/C.java
@@ -0,0 +1,98 @@
+import java.util.HashMap;
+import java.io.StringReader;
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import com.cedarsoftware.util.io.JsonReader;
+import com.esotericsoftware.yamlbeans.YamlReader;
+import org.ho.yaml.Yaml;
+import org.ho.yaml.YamlConfig;
+import org.exolab.castor.xml.Unmarshaller;
+import com.caucho.hessian.io.Hessian2Input;
+import com.caucho.hessian.io.HessianInput;
+import com.caucho.burlap.io.BurlapInput;
+import com.caucho.hessian.io.Hessian2Input;
+import com.caucho.hessian.io.HessianInput;
+import java.io.ByteArrayInputStream;
+
+@Controller
+public class C {
+
+ @GetMapping(value = "jyaml")
+ public void bad1(HttpServletRequest request) throws Exception {
+ String data = request.getParameter("data");
+ Yaml.load(data); //bad
+ Yaml.loadStream(data); //bad
+ Yaml.loadStreamOfType(data, Object.class); //bad
+ Yaml.loadType(data, Object.class); //bad
+
+ org.ho.yaml.YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.load(data); //bad
+ yamlConfig.loadStream(data); //bad
+ yamlConfig.loadStreamOfType(data, Object.class); //bad
+ yamlConfig.loadType(data, Object.class); //bad
+ }
+
+ @GetMapping(value = "jsonio")
+ public void bad2(HttpServletRequest request) {
+ String data = request.getParameter("data");
+
+ HashMap hashMap = new HashMap();
+ hashMap.put("USE_MAPS", true);
+
+ JsonReader.jsonToJava(data); //bad
+
+ JsonReader.jsonToJava(data, hashMap); //good
+
+ JsonReader jr = new JsonReader(data, null); //bad
+ jr.readObject();
+
+ JsonReader jr1 = new JsonReader(data, hashMap); //good
+ jr1.readObject();
+ }
+
+ @GetMapping(value = "yamlbeans")
+ public void bad3(HttpServletRequest request) throws Exception {
+ String data = request.getParameter("data");
+ YamlReader r = new YamlReader(data);
+ r.read(); //bad
+ r.read(Object.class); //bad
+ r.read(Object.class, Object.class); //bad
+ }
+
+ @GetMapping(value = "hessian")
+ public void bad4(HttpServletRequest request) throws Exception {
+ byte[] bytes = request.getParameter("data").getBytes();
+ ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+ HessianInput hessianInput = new HessianInput(bis);
+ hessianInput.readObject(); //bad
+ hessianInput.readObject(Object.class); //bad
+ }
+
+ @GetMapping(value = "hessian2")
+ public void bad5(HttpServletRequest request) throws Exception {
+ byte[] bytes = request.getParameter("data").getBytes();
+ ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+ Hessian2Input hessianInput = new Hessian2Input(bis);
+ hessianInput.readObject(); //bad
+ hessianInput.readObject(Object.class); //bad
+ }
+
+ @GetMapping(value = "castor")
+ public void bad6(HttpServletRequest request) throws Exception {
+ Unmarshaller unmarshaller = new Unmarshaller();
+ unmarshaller.unmarshal(new StringReader(request.getParameter("data"))); //bad
+ }
+
+ @GetMapping(value = "burlap")
+ public void bad7(HttpServletRequest request) throws Exception {
+ byte[] serializedData = request.getParameter("data").getBytes();
+ ByteArrayInputStream is = new ByteArrayInputStream(serializedData);
+ BurlapInput burlapInput = new BurlapInput(is);
+ burlapInput.readObject(); //bad
+
+ BurlapInput burlapInput1 = new BurlapInput();
+ burlapInput1.init(is);
+ burlapInput1.readObject(); //bad
+ }
+}
diff --git a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
index f575a093d6e..d583caafc9b 100644
--- a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
+++ b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
@@ -25,6 +25,26 @@ edges
| B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:15:23:15:27 | bytes |
| B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:23:29:23:29 | s |
| B.java:27:31:27:51 | getInputStream(...) : InputStream | B.java:31:23:31:23 | s |
+| C.java:23:17:23:44 | getParameter(...) : String | C.java:24:13:24:16 | data |
+| C.java:23:17:23:44 | getParameter(...) : String | C.java:25:19:25:22 | data |
+| C.java:23:17:23:44 | getParameter(...) : String | C.java:26:25:26:28 | data |
+| C.java:23:17:23:44 | getParameter(...) : String | C.java:27:17:27:20 | data |
+| C.java:23:17:23:44 | getParameter(...) : String | C.java:30:19:30:22 | data |
+| C.java:23:17:23:44 | getParameter(...) : String | C.java:31:25:31:28 | data |
+| C.java:23:17:23:44 | getParameter(...) : String | C.java:32:31:32:34 | data |
+| C.java:23:17:23:44 | getParameter(...) : String | C.java:33:23:33:26 | data |
+| C.java:38:17:38:44 | getParameter(...) : String | C.java:43:25:43:28 | data |
+| C.java:38:17:38:44 | getParameter(...) : String | C.java:48:3:48:4 | jr |
+| C.java:56:17:56:44 | getParameter(...) : String | C.java:58:3:58:3 | r |
+| C.java:56:17:56:44 | getParameter(...) : String | C.java:59:3:59:3 | r |
+| C.java:56:17:56:44 | getParameter(...) : String | C.java:60:3:60:3 | r |
+| C.java:65:18:65:45 | getParameter(...) : String | C.java:68:3:68:14 | hessianInput |
+| C.java:65:18:65:45 | getParameter(...) : String | C.java:69:3:69:14 | hessianInput |
+| C.java:74:18:74:45 | getParameter(...) : String | C.java:77:3:77:14 | hessianInput |
+| C.java:74:18:74:45 | getParameter(...) : String | C.java:78:3:78:14 | hessianInput |
+| C.java:84:43:84:70 | getParameter(...) : String | C.java:84:26:84:71 | new StringReader(...) |
+| C.java:89:27:89:54 | getParameter(...) : String | C.java:92:3:92:13 | burlapInput |
+| C.java:89:27:89:54 | getParameter(...) : String | C.java:96:3:96:14 | burlapInput1 |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
nodes
| A.java:13:31:13:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
@@ -65,6 +85,33 @@ nodes
| B.java:23:29:23:29 | s | semmle.label | s |
| B.java:27:31:27:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| B.java:31:23:31:23 | s | semmle.label | s |
+| C.java:23:17:23:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:24:13:24:16 | data | semmle.label | data |
+| C.java:25:19:25:22 | data | semmle.label | data |
+| C.java:26:25:26:28 | data | semmle.label | data |
+| C.java:27:17:27:20 | data | semmle.label | data |
+| C.java:30:19:30:22 | data | semmle.label | data |
+| C.java:31:25:31:28 | data | semmle.label | data |
+| C.java:32:31:32:34 | data | semmle.label | data |
+| C.java:33:23:33:26 | data | semmle.label | data |
+| C.java:38:17:38:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:43:25:43:28 | data | semmle.label | data |
+| C.java:48:3:48:4 | jr | semmle.label | jr |
+| C.java:56:17:56:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:58:3:58:3 | r | semmle.label | r |
+| C.java:59:3:59:3 | r | semmle.label | r |
+| C.java:60:3:60:3 | r | semmle.label | r |
+| C.java:65:18:65:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:68:3:68:14 | hessianInput | semmle.label | hessianInput |
+| C.java:69:3:69:14 | hessianInput | semmle.label | hessianInput |
+| C.java:74:18:74:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:77:3:77:14 | hessianInput | semmle.label | hessianInput |
+| C.java:78:3:78:14 | hessianInput | semmle.label | hessianInput |
+| C.java:84:26:84:71 | new StringReader(...) | semmle.label | new StringReader(...) |
+| C.java:84:43:84:70 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:89:27:89:54 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:92:3:92:13 | burlapInput | semmle.label | burlapInput |
+| C.java:96:3:96:14 | burlapInput1 | semmle.label | burlapInput1 |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | semmle.label | entityStream : InputStream |
| TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | semmle.label | new ObjectInputStream(...) |
#select
@@ -94,4 +141,24 @@ nodes
| B.java:15:12:15:28 | parse(...) | B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:15:23:15:27 | bytes | Unsafe deserialization of $@. | B.java:12:31:12:51 | getInputStream(...) | user input |
| B.java:23:12:23:30 | parseObject(...) | B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:23:29:23:29 | s | Unsafe deserialization of $@. | B.java:19:31:19:51 | getInputStream(...) | user input |
| B.java:31:12:31:24 | parse(...) | B.java:27:31:27:51 | getInputStream(...) : InputStream | B.java:31:23:31:23 | s | Unsafe deserialization of $@. | B.java:27:31:27:51 | getInputStream(...) | user input |
+| C.java:24:3:24:17 | load(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:24:13:24:16 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
+| C.java:25:3:25:23 | loadStream(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:25:19:25:22 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
+| C.java:26:3:26:43 | loadStreamOfType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:26:25:26:28 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
+| C.java:27:3:27:35 | loadType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:27:17:27:20 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
+| C.java:30:3:30:23 | load(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:30:19:30:22 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
+| C.java:31:3:31:29 | loadStream(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:31:25:31:28 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
+| C.java:32:3:32:49 | loadStreamOfType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:32:31:32:34 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
+| C.java:33:3:33:41 | loadType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:33:23:33:26 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
+| C.java:43:3:43:29 | jsonToJava(...) | C.java:38:17:38:44 | getParameter(...) : String | C.java:43:25:43:28 | data | Unsafe deserialization of $@. | C.java:38:17:38:44 | getParameter(...) | user input |
+| C.java:48:3:48:17 | readObject(...) | C.java:38:17:38:44 | getParameter(...) : String | C.java:48:3:48:4 | jr | Unsafe deserialization of $@. | C.java:38:17:38:44 | getParameter(...) | user input |
+| C.java:58:3:58:10 | read(...) | C.java:56:17:56:44 | getParameter(...) : String | C.java:58:3:58:3 | r | Unsafe deserialization of $@. | C.java:56:17:56:44 | getParameter(...) | user input |
+| C.java:59:3:59:22 | read(...) | C.java:56:17:56:44 | getParameter(...) : String | C.java:59:3:59:3 | r | Unsafe deserialization of $@. | C.java:56:17:56:44 | getParameter(...) | user input |
+| C.java:60:3:60:36 | read(...) | C.java:56:17:56:44 | getParameter(...) : String | C.java:60:3:60:3 | r | Unsafe deserialization of $@. | C.java:56:17:56:44 | getParameter(...) | user input |
+| C.java:68:3:68:27 | readObject(...) | C.java:65:18:65:45 | getParameter(...) : String | C.java:68:3:68:14 | hessianInput | Unsafe deserialization of $@. | C.java:65:18:65:45 | getParameter(...) | user input |
+| C.java:69:3:69:39 | readObject(...) | C.java:65:18:65:45 | getParameter(...) : String | C.java:69:3:69:14 | hessianInput | Unsafe deserialization of $@. | C.java:65:18:65:45 | getParameter(...) | user input |
+| C.java:77:3:77:27 | readObject(...) | C.java:74:18:74:45 | getParameter(...) : String | C.java:77:3:77:14 | hessianInput | Unsafe deserialization of $@. | C.java:74:18:74:45 | getParameter(...) | user input |
+| C.java:78:3:78:39 | readObject(...) | C.java:74:18:74:45 | getParameter(...) : String | C.java:78:3:78:14 | hessianInput | Unsafe deserialization of $@. | C.java:74:18:74:45 | getParameter(...) | user input |
+| C.java:84:3:84:72 | unmarshal(...) | C.java:84:43:84:70 | getParameter(...) : String | C.java:84:26:84:71 | new StringReader(...) | Unsafe deserialization of $@. | C.java:84:43:84:70 | getParameter(...) | user input |
+| C.java:92:3:92:26 | readObject(...) | C.java:89:27:89:54 | getParameter(...) : String | C.java:92:3:92:13 | burlapInput | Unsafe deserialization of $@. | C.java:89:27:89:54 | getParameter(...) | user input |
+| C.java:96:3:96:27 | readObject(...) | C.java:89:27:89:54 | getParameter(...) : String | C.java:96:3:96:14 | burlapInput1 | Unsafe deserialization of $@. | C.java:89:27:89:54 | getParameter(...) | user input |
| TestMessageBodyReader.java:22:18:22:65 | readObject(...) | TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | Unsafe deserialization of $@. | TestMessageBodyReader.java:20:55:20:78 | entityStream | user input |
diff --git a/java/ql/test/query-tests/security/CWE-502/options b/java/ql/test/query-tests/security/CWE-502/options
index 6df0c9374c2..ebf1581cc8a 100644
--- a/java/ql/test/query-tests/security/CWE-502/options
+++ b/java/ql/test/query-tests/security/CWE-502/options
@@ -1 +1 @@
-//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1
diff --git a/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/types/AnyNode.java b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/types/AnyNode.java
new file mode 100644
index 00000000000..f29270d2521
--- /dev/null
+++ b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/types/AnyNode.java
@@ -0,0 +1,11 @@
+package org.exolab.castor.types;
+
+import java.io.Serializable;
+
+public final class AnyNode implements Serializable {
+
+ private static final long serialVersionUID = -4104117996051705975L;
+
+ public AnyNode() { }
+}
+
diff --git a/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/EventProducer.java b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/EventProducer.java
new file mode 100644
index 00000000000..08893c95a48
--- /dev/null
+++ b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/EventProducer.java
@@ -0,0 +1,12 @@
+package org.exolab.castor.xml;
+
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.SAXException;
+
+/** @deprecated */
+public interface EventProducer {
+ void setDocumentHandler(DocumentHandler var1);
+
+ void start() throws SAXException;
+}
+
diff --git a/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/SAX2EventAndErrorProducer.java b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/SAX2EventAndErrorProducer.java
new file mode 100644
index 00000000000..77978b53f01
--- /dev/null
+++ b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/SAX2EventAndErrorProducer.java
@@ -0,0 +1,8 @@
+package org.exolab.castor.xml;
+
+import org.xml.sax.ErrorHandler;
+
+public interface SAX2EventAndErrorProducer extends SAX2EventProducer {
+ void setErrorHandler(ErrorHandler var1);
+}
+
diff --git a/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/SAX2EventProducer.java b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/SAX2EventProducer.java
new file mode 100644
index 00000000000..66b2cf8259f
--- /dev/null
+++ b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/SAX2EventProducer.java
@@ -0,0 +1,11 @@
+package org.exolab.castor.xml;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+public interface SAX2EventProducer {
+ void setContentHandler(ContentHandler var1);
+
+ void start() throws SAXException;
+}
+
diff --git a/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/Unmarshaller.java b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/Unmarshaller.java
new file mode 100644
index 00000000000..cc76c2c5e6a
--- /dev/null
+++ b/java/ql/test/stubs/castor-1.4.1/org/exolab/castor/xml/Unmarshaller.java
@@ -0,0 +1,74 @@
+package org.exolab.castor.xml;
+
+import java.io.Reader;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.Source;
+import org.exolab.castor.types.AnyNode;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+public class Unmarshaller {
+
+ public Unmarshaller() { }
+
+ public Object unmarshal(Reader reader) {
+ return null;
+ }
+
+ public Object unmarshal(EventProducer eventProducer) {
+ return null;
+ }
+
+ public Object unmarshal(SAX2EventProducer eventProducer) {
+ return null;
+ }
+
+ public Object unmarshal(AnyNode anyNode) {
+ return null;
+ }
+
+ public Object unmarshal(InputSource source) {
+ return null;
+ }
+
+ public Object unmarshal(Node node) {
+ return null;
+ }
+
+ public Object unmarshal(XMLEventReader eventReader) {
+ return null;
+ }
+
+ public Object unmarshal(XMLStreamReader streamReader) {
+ return null;
+ }
+
+ public Object unmarshal(SAX2EventAndErrorProducer eventProducer) {
+ return null;
+ }
+
+ public Object unmarshal(Source source) {
+ return null;
+ }
+
+ public static Object unmarshal(Class c, Reader reader) {
+ return null;
+ }
+
+ private static Unmarshaller createUnmarshaller(Class clazz) {
+ return null;
+ }
+
+ public static Object unmarshal(Class c, InputSource source) {
+ return null;
+ }
+
+ public static Object unmarshal(Class c, Node node) {
+ return null;
+ }
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractBurlapInput.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractBurlapInput.java
new file mode 100644
index 00000000000..9bf1892ea5b
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractBurlapInput.java
@@ -0,0 +1,9 @@
+package com.caucho.burlap.io;
+
+import com.caucho.hessian.io.AbstractHessianInput;
+
+public abstract class AbstractBurlapInput extends AbstractHessianInput {
+ public AbstractBurlapInput() {
+ }
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractHessianInput.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractHessianInput.java
new file mode 100644
index 00000000000..aff9f533850
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractHessianInput.java
@@ -0,0 +1,110 @@
+package com.caucho.hessian.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import org.w3c.dom.Node;
+
+public abstract class AbstractHessianInput {
+
+ public AbstractHessianInput() {
+ }
+
+ public void init(InputStream is) {
+ }
+
+ public abstract String getMethod();
+
+ public void setSerializerFactory(SerializerFactory ser) {
+ }
+
+ public abstract int readCall() throws IOException;
+
+ public void skipOptionalCall() throws IOException {
+ }
+
+ public abstract String readHeader() throws IOException;
+
+ public abstract String readMethod() throws IOException;
+
+ public int readMethodArgLength() throws IOException {
+ return -1;
+ }
+
+ public abstract void startCall() throws IOException;
+
+ public abstract void completeCall() throws IOException;
+
+ public abstract Object readReply(Class var1) throws Throwable;
+
+ public abstract void startReply() throws Throwable;
+
+ public void startReplyBody() throws Throwable {
+ }
+
+ public abstract void completeReply() throws IOException;
+
+ public abstract boolean readBoolean() throws IOException;
+
+ public abstract void readNull() throws IOException;
+
+ public abstract int readInt() throws IOException;
+
+ public abstract long readLong() throws IOException;
+
+ public abstract double readDouble() throws IOException;
+
+ public abstract long readUTCDate() throws IOException;
+
+ public abstract String readString() throws IOException;
+
+ public Node readNode() throws IOException {
+ return null;
+ }
+
+ public abstract Reader getReader() throws IOException;
+
+ public abstract InputStream readInputStream() throws IOException;
+
+ public boolean readToOutputStream(OutputStream os) throws IOException {
+ return true;
+ }
+
+ public abstract byte[] readBytes() throws IOException;
+
+ public abstract Object readObject(Class var1) throws IOException;
+
+ public abstract Object readObject() throws IOException;
+
+ public abstract Object readRemote() throws IOException;
+
+ public abstract Object readRef() throws IOException;
+
+ public abstract int addRef(Object var1) throws IOException;
+
+ public abstract void setRef(int var1, Object var2) throws IOException;
+
+ public void resetReferences() {
+ }
+
+ public abstract int readListStart() throws IOException;
+
+ public abstract int readLength() throws IOException;
+
+ public abstract int readMapStart() throws IOException;
+
+ public abstract String readType() throws IOException;
+
+ public abstract boolean isEnd() throws IOException;
+
+ public abstract void readEnd() throws IOException;
+
+ public abstract void readMapEnd() throws IOException;
+
+ public abstract void readListEnd() throws IOException;
+
+ public void close() throws IOException {
+ }
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractSerializerFactory.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractSerializerFactory.java
new file mode 100644
index 00000000000..d4bc523ec87
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/AbstractSerializerFactory.java
@@ -0,0 +1,11 @@
+package com.caucho.hessian.io;
+
+public abstract class AbstractSerializerFactory {
+ public AbstractSerializerFactory() {
+ }
+
+ public abstract Serializer getSerializer(Class var1) throws HessianProtocolException;
+
+ public abstract Deserializer getDeserializer(Class var1) throws HessianProtocolException;
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/BurlapInput.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/BurlapInput.java
new file mode 100644
index 00000000000..ec02d2f302b
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/BurlapInput.java
@@ -0,0 +1,274 @@
+package com.caucho.burlap.io;
+
+import com.caucho.hessian.io.SerializerFactory;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.TimeZone;
+import org.w3c.dom.Node;
+
+public class BurlapInput extends AbstractBurlapInput {
+
+ public BurlapInput() { }
+
+ public BurlapInput(InputStream is) { }
+
+ public void setSerializerFactory(SerializerFactory factory) { }
+
+ public SerializerFactory getSerializerFactory() {
+ return null;
+ }
+
+ public void init(InputStream is) { }
+
+ public String getMethod() {
+ return null;
+ }
+
+ public Throwable getReplyFault() {
+ return null;
+ }
+
+ public void startCall() throws IOException { }
+
+ public int readCall() throws IOException {
+ return 1;
+ }
+
+ public String readMethod() throws IOException {
+ return null;
+ }
+
+ public void completeCall() throws IOException { }
+
+ public Object readReply(Class expectedClass) throws Throwable {
+ return null;
+ }
+
+ public void startReply() throws Throwable { }
+
+ private Throwable prepareFault() throws IOException {
+ return null;
+ }
+
+ public void completeReply() throws IOException { }
+
+ public String readHeader() throws IOException {
+ return null;
+ }
+
+ public void readNull() throws IOException { }
+
+ public boolean readBoolean() throws IOException {
+ return true;
+ }
+
+ public byte readByte() throws IOException {
+ return 1;
+ }
+
+ public short readShort() throws IOException {
+ return 1;
+ }
+
+ public int readInt() throws IOException {
+ return 1;
+ }
+
+ public long readLong() throws IOException {
+ return 1L;
+ }
+
+ public float readFloat() throws IOException {
+ return 1.1F;
+ }
+
+ public double readDouble() throws IOException {
+ return 1.1;
+ }
+
+ public long readUTCDate() throws IOException {
+ return 1L;
+ }
+
+ public long readLocalDate() throws IOException {
+ return 1L;
+ }
+
+ public String readString() throws IOException {
+ return null;
+ }
+
+ public Node readNode() throws IOException {
+ return null;
+ }
+
+ public byte[] readBytes() throws IOException {
+ return null;
+ }
+
+ public int readLength() throws IOException {
+ return 1;
+ }
+
+ private HashMap readFault() throws IOException {
+ return null;
+ }
+
+ public Object readObject(Class cl) throws IOException {
+ return null;
+ }
+
+ public Object readObject() throws IOException {
+ return null;
+ }
+
+ public Object readRemote() throws IOException {
+ return null;
+ }
+
+ public Object readRef() throws IOException {
+ return null;
+ }
+
+ public int readListStart() throws IOException {
+ return 1;
+ }
+
+ public int readMapStart() throws IOException {
+ return 1;
+ }
+
+ public boolean isEnd() throws IOException {
+ return true;
+ }
+
+ public void readEnd() throws IOException { }
+
+ public void readMapEnd() throws IOException { }
+
+ public void readListEnd() throws IOException { }
+
+ public int addRef(Object ref) {
+ return 1;
+ }
+
+ public void setRef(int i, Object ref) { }
+
+ public Object resolveRemote(String type, String url) throws IOException {
+ return null;
+ }
+
+ public String readType() throws IOException {
+ return null;
+ }
+
+ private int parseInt() throws IOException {
+ return 1;
+ }
+
+ private long parseLong() throws IOException {
+ return 1L;
+ }
+
+ private double parseDouble() throws IOException {
+ return 1.1;
+ }
+
+ protected long parseDate() throws IOException {
+ return 1L;
+ }
+
+ protected long parseDate(Calendar calendar) throws IOException {
+ return 1L;
+ }
+
+ protected String parseString() throws IOException {
+ return null;
+ }
+
+ protected StringBuffer parseString(StringBuffer sbuf) throws IOException {
+ return null;
+ }
+
+ Node parseXML() throws IOException {
+ return null;
+ }
+
+ int readChar() throws IOException {
+ return 1;
+ }
+
+ protected byte[] parseBytes() throws IOException {
+ return null;
+ }
+
+ protected ByteArrayOutputStream parseBytes(ByteArrayOutputStream bos) throws IOException {
+ return null;
+ }
+
+ public void expectTag(int expectTag) throws IOException { }
+
+ protected int parseTag() throws IOException {
+ return 1;
+ }
+
+ private boolean isTagChar(int ch) {
+ return true;
+ }
+
+ protected int skipWhitespace() throws IOException {
+ return 1;
+ }
+
+ protected boolean isWhitespace(int ch) throws IOException {
+ return true;
+ }
+
+ int read(byte[] buffer, int offset, int length) throws IOException {
+ return 1;
+ }
+
+ int read() throws IOException {
+ return 1;
+ }
+
+ public Reader getReader() {
+ return null;
+ }
+
+ public InputStream readInputStream() {
+ return null;
+ }
+
+ public InputStream getInputStream() {
+ return null;
+ }
+
+ protected IOException expectBeginTag(String expect, String tag) {
+ return null;
+ }
+
+ protected IOException expectedChar(String expect, int ch) {
+ return null;
+ }
+
+ protected IOException expectedTag(String expect, int tag) {
+ return null;
+ }
+
+ protected IOException error(String message) {
+ return null;
+ }
+
+ protected static String tagName(int tag) {
+ return null;
+ }
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/Deserializer.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/Deserializer.java
new file mode 100644
index 00000000000..2a96e53c397
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/Deserializer.java
@@ -0,0 +1,26 @@
+package com.caucho.hessian.io;
+
+import java.io.IOException;
+
+public interface Deserializer {
+ Class> getType();
+
+ boolean isReadResolve();
+
+ Object readObject(AbstractHessianInput var1) throws IOException;
+
+ Object readList(AbstractHessianInput var1, int var2) throws IOException;
+
+ Object readLengthList(AbstractHessianInput var1, int var2) throws IOException;
+
+ Object readMap(AbstractHessianInput var1) throws IOException;
+
+ Object[] createFields(int var1);
+
+ Object createField(String var1);
+
+ Object readObject(AbstractHessianInput var1, Object[] var2) throws IOException;
+
+ Object readObject(AbstractHessianInput var1, String[] var2) throws IOException;
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/HessianProtocolException.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/HessianProtocolException.java
new file mode 100644
index 00000000000..173d5876c03
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/HessianProtocolException.java
@@ -0,0 +1,24 @@
+package com.caucho.hessian.io;
+
+import java.io.IOException;
+
+public class HessianProtocolException extends IOException {
+
+ public HessianProtocolException() {
+ }
+
+ public HessianProtocolException(String message) { }
+
+ public HessianProtocolException(String message, Throwable rootCause) { }
+
+ public HessianProtocolException(Throwable rootCause) { }
+
+ public Throwable getRootCause() {
+ return null;
+ }
+
+ public Throwable getCause() {
+ return null;
+ }
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/Serializer.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/Serializer.java
new file mode 100644
index 00000000000..fbd3f5bc9c8
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/Serializer.java
@@ -0,0 +1,8 @@
+package com.caucho.hessian.io;
+
+import java.io.IOException;
+
+public interface Serializer {
+
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/SerializerFactory.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/SerializerFactory.java
new file mode 100644
index 00000000000..96716eca3ae
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/burlap/io/SerializerFactory.java
@@ -0,0 +1,12 @@
+package com.caucho.hessian.io;
+
+public class SerializerFactory extends AbstractSerializerFactory {
+
+ public Serializer getSerializer(Class cl) throws HessianProtocolException {
+ return null;
+ }
+
+ public Deserializer getDeserializer(Class cl) throws HessianProtocolException {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/AbstractHessianInput.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/AbstractHessianInput.java
new file mode 100644
index 00000000000..4b9d3b7ad44
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/AbstractHessianInput.java
@@ -0,0 +1,111 @@
+package com.caucho.hessian.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+
+public abstract class AbstractHessianInput {
+
+ public AbstractHessianInput() {
+ }
+
+ public void init(InputStream is) {
+ }
+
+ public abstract String getMethod();
+
+ public void setRemoteResolver(HessianRemoteResolver resolver) { }
+
+ public HessianRemoteResolver getRemoteResolver() {
+ return null;
+ }
+
+ public void setSerializerFactory(SerializerFactory ser) {
+ }
+
+ public abstract int readCall() throws IOException;
+
+ public void skipOptionalCall() throws IOException {
+ }
+
+ public abstract String readHeader() throws IOException;
+
+ public abstract String readMethod() throws IOException;
+
+ public int readMethodArgLength() throws IOException {
+ return -1;
+ }
+
+ public abstract void startCall() throws IOException;
+
+ public abstract void completeCall() throws IOException;
+
+ public abstract Object readReply(Class var1) throws Throwable;
+
+ public abstract void startReply() throws Throwable;
+
+ public void startReplyBody() throws Throwable {
+ }
+
+ public abstract void completeReply() throws IOException;
+
+ public abstract boolean readBoolean() throws IOException;
+
+ public abstract void readNull() throws IOException;
+
+ public abstract int readInt() throws IOException;
+
+ public abstract long readLong() throws IOException;
+
+ public abstract double readDouble() throws IOException;
+
+ public abstract long readUTCDate() throws IOException;
+
+ public abstract String readString() throws IOException;
+
+ public abstract Reader getReader() throws IOException;
+
+ public abstract InputStream readInputStream() throws IOException;
+
+ public boolean readToOutputStream(OutputStream os) throws IOException {
+ return true;
+ }
+
+ public abstract byte[] readBytes() throws IOException;
+
+ public abstract Object readObject(Class var1) throws IOException;
+
+ public abstract Object readObject() throws IOException;
+
+ public abstract Object readRemote() throws IOException;
+
+ public abstract Object readRef() throws IOException;
+
+ public abstract int addRef(Object var1) throws IOException;
+
+ public abstract void setRef(int var1, Object var2) throws IOException;
+
+ public void resetReferences() {
+ }
+
+ public abstract int readListStart() throws IOException;
+
+ public abstract int readLength() throws IOException;
+
+ public abstract int readMapStart() throws IOException;
+
+ public abstract String readType() throws IOException;
+
+ public abstract boolean isEnd() throws IOException;
+
+ public abstract void readEnd() throws IOException;
+
+ public abstract void readMapEnd() throws IOException;
+
+ public abstract void readListEnd() throws IOException;
+
+ public void close() throws IOException {
+ }
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/Hessian2Input.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/Hessian2Input.java
new file mode 100644
index 00000000000..1ed011945e1
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/Hessian2Input.java
@@ -0,0 +1,297 @@
+package com.caucho.hessian.io;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class Hessian2Input extends AbstractHessianInput {
+
+ public Hessian2Input() { }
+
+ public Hessian2Input(InputStream is) { }
+
+ public String getMethod() {
+ return null;
+ }
+
+ public Throwable getReplyFault() {
+ return null;
+ }
+
+ public int readCall() throws IOException {
+ return 1;
+ }
+
+ public int readEnvelope() throws IOException {
+ return 1;
+ }
+
+ public void completeEnvelope() throws IOException { }
+
+ public String readMethod() throws IOException {
+ return null;
+ }
+
+ public int readMethodArgLength() throws IOException {
+ return 1;
+ }
+
+ public void startCall() throws IOException { }
+
+ public Object[] readArguments() throws IOException {
+ return null;
+ }
+
+ public void completeCall() throws IOException { }
+
+ public Object readReply(Class expectedClass) throws Throwable {
+ return null;
+ }
+
+ public void startReply() throws Throwable { }
+
+ private Throwable prepareFault(HashMap fault) throws IOException {
+ return null;
+ }
+
+ public void completeReply() throws IOException { }
+
+ public void completeValueReply() throws IOException { }
+
+ public String readHeader() throws IOException {
+ return null;
+ }
+
+ public int startMessage() throws IOException {
+ return 1;
+ }
+
+ public void completeMessage() throws IOException { }
+
+ public void readNull() throws IOException { }
+
+ public boolean readBoolean() throws IOException {
+ return true;
+ }
+
+ public short readShort() throws IOException {
+ return 11111;
+ }
+
+ public final int readInt() throws IOException {
+ return 1;
+ }
+
+ public long readLong() throws IOException {
+ return 1L;
+ }
+
+ public float readFloat() throws IOException {
+ return 1.1F;
+ }
+
+ public double readDouble() throws IOException {
+ return 1.1;
+ }
+
+ public long readUTCDate() throws IOException {
+ return 1L;
+ }
+
+ public int readChar() throws IOException {
+ return 1;
+ }
+
+ public int readString(char[] buffer, int offset, int length) throws IOException {
+ return 1;
+ }
+
+ public String readString() throws IOException {
+ return null;
+ }
+
+ public byte[] readBytes() throws IOException {
+ return null;
+ }
+
+ public int readByte() throws IOException {
+ return 1;
+ }
+
+ public int readBytes(byte[] buffer, int offset, int length) throws IOException {
+ return 1;
+ }
+
+ private HashMap readFault() throws IOException {
+ return null;
+ }
+
+ public Object readObject(Class cl) throws IOException {
+ return null;
+ }
+
+ public Object readObject() throws IOException {
+ return null;
+ }
+
+ private void readObjectDefinition(Class> cl) throws IOException { }
+
+ private Object readObjectInstance(Class> cl, Hessian2Input.ObjectDefinition def) throws IOException {
+ return null;
+ }
+
+ public Object readRemote() throws IOException {
+ return null;
+ }
+
+ public Object readRef() throws IOException {
+ return null;
+ }
+
+ public int readListStart() throws IOException {
+ return 1;
+ }
+
+ public int readMapStart() throws IOException {
+ return 1;
+ }
+
+ public boolean isEnd() throws IOException {
+ return true;
+ }
+
+ public void readEnd() throws IOException { }
+
+ public void readMapEnd() throws IOException { }
+
+ public void readListEnd() throws IOException { }
+
+ public int addRef(Object ref) {
+ return 1;
+ }
+
+ public void setRef(int i, Object ref) { }
+
+ public void resetReferences() { }
+
+ public void reset() { }
+
+ public void resetBuffer() { }
+
+ public Object readStreamingObject() throws IOException {
+ return null;
+ }
+
+ public Object resolveRemote(String type, String url) throws IOException {
+ return null;
+ }
+
+ public String readType() throws IOException {
+ return null;
+ }
+
+ public int readLength() throws IOException {
+ return 1;
+ }
+
+ private int parseInt() throws IOException {
+ return 1;
+ }
+
+ private long parseLong() throws IOException {
+ return 1L;
+ }
+
+ private double parseDouble() throws IOException {
+ return 1.1;
+ }
+
+ private void parseString(StringBuilder sbuf) throws IOException { }
+
+ private int parseChar() throws IOException {
+ return 1;
+ }
+
+ private boolean parseChunkLength() throws IOException {
+ return true;
+ }
+
+ private int parseUTF8Char() throws IOException {
+ return 1;
+ }
+
+ private int parseByte() throws IOException {
+ return 1;
+ }
+
+ public InputStream readInputStream() throws IOException {
+ return null;
+ }
+
+ int read(byte[] buffer, int offset, int length) throws IOException {
+ return 1;
+ }
+
+ public final int read() throws IOException {
+ return 1;
+ }
+
+ protected void unread() { }
+
+ private final boolean readBuffer() throws IOException {
+ return true;
+ }
+
+ public Reader getReader() {
+ return null;
+ }
+
+ protected IOException expect(String expect, int ch) throws IOException {
+ return null;
+ }
+
+ private String buildDebugContext(byte[] buffer, int offset, int length, int errorOffset) {
+ return null;
+ }
+
+ private void addDebugChar(StringBuilder sb, int ch) { }
+
+ protected String codeName(int ch) {
+ return null;
+ }
+
+ protected IOException error(String message) {
+ return null;
+ }
+
+ public void free() { }
+
+ public void close() throws IOException { }
+
+ static final class ObjectDefinition {
+ }
+
+ class ReadInputStream extends InputStream {
+
+ ReadInputStream() { }
+
+ public int read() throws IOException {
+ return 1;
+ }
+
+ public int read(byte[] buffer, int offset, int length) throws IOException {
+ return 1;
+ }
+
+ public void close() throws IOException { }
+ }
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/HessianInput.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/HessianInput.java
new file mode 100644
index 00000000000..e10a11ad706
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/HessianInput.java
@@ -0,0 +1,229 @@
+package com.caucho.hessian.io;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+
+public class HessianInput extends AbstractHessianInput {
+
+ public HessianInput() {
+ }
+
+ public HessianInput(InputStream is) { }
+
+ public void init(InputStream is) { }
+
+ public String getMethod() {
+ return null;
+ }
+
+ public Throwable getReplyFault() {
+ return null;
+ }
+
+ public int readCall() throws IOException {
+ return 0;
+ }
+
+ public void skipOptionalCall() throws IOException { }
+
+ public String readMethod() throws IOException {
+ return null;
+ }
+
+ public void startCall() throws IOException { }
+
+ public void completeCall() throws IOException { }
+
+ public Object readReply(Class expectedClass) throws Throwable {
+ return null;
+ }
+
+ public void startReply() throws Throwable { }
+
+ public void startReplyBody() throws Throwable { }
+
+ private Throwable prepareFault() throws IOException {
+ return null;
+ }
+
+ public void completeReply() throws IOException { }
+
+ public void completeValueReply() throws IOException { }
+
+ public String readHeader() throws IOException {
+ return null;
+ }
+
+ public void readNull() throws IOException { }
+
+ public boolean readBoolean() throws IOException {
+ return true;
+ }
+
+ public short readShort() throws IOException {
+ return 11111;
+ }
+
+ public int readInt() throws IOException {
+ return 1;
+ }
+
+ public long readLong() throws IOException {
+ return 1L;
+ }
+
+ public float readFloat() throws IOException {
+ return 1.1F;
+ }
+
+ public double readDouble() throws IOException {
+ return 1.1;
+ }
+
+ public long readUTCDate() throws IOException {
+ return 1L;
+ }
+
+ public int readChar() throws IOException {
+ return 1;
+ }
+
+ public int readString(char[] buffer, int offset, int length) throws IOException {
+ return 1;
+ }
+
+ public String readString() throws IOException {
+ return null;
+ }
+
+ public byte[] readBytes() throws IOException {
+ return null;
+ }
+
+ public int readByte() throws IOException {
+ return 1;
+ }
+
+ public int readBytes(byte[] buffer, int offset, int length) throws IOException {
+ return 1;
+ }
+
+ private HashMap readFault() throws IOException {
+ return null;
+ }
+
+ public Object readObject(Class cl) throws IOException {
+ return null;
+ }
+
+ public Object readObject() throws IOException {
+ return null;
+ }
+
+ public Object readRemote() throws IOException {
+ return null;
+ }
+
+ public Object readRef() throws IOException {
+ return null;
+ }
+
+ public int readListStart() throws IOException {
+ return 1;
+ }
+
+ public int readMapStart() throws IOException {
+ return 1;
+ }
+
+ public boolean isEnd() throws IOException {
+ return true;
+ }
+
+ public void readEnd() throws IOException { }
+
+ public void readMapEnd() throws IOException { }
+
+ public void readListEnd() throws IOException { }
+
+ public int addRef(Object ref) {
+ return 1;
+ }
+
+ public void setRef(int i, Object ref) { }
+
+ public void resetReferences() { }
+
+ public Object resolveRemote(String type, String url) throws IOException {
+ return null;
+ }
+
+ public String readType() throws IOException {
+ return null;
+ }
+
+ public int readLength() throws IOException {
+ return 1;
+ }
+
+ private int parseInt() throws IOException {
+ return 1;
+ }
+
+ private long parseLong() throws IOException {
+ return 1L;
+ }
+
+ private double parseDouble() throws IOException {
+ return 1.1;
+ }
+
+ private int parseChar() throws IOException {
+ return 1;
+ }
+
+ private int parseUTF8Char() throws IOException {
+ return 1;
+ }
+
+ private int parseByte() throws IOException {
+ return 1;
+ }
+
+ public InputStream readInputStream() throws IOException {
+ return null;
+ }
+
+ int read(byte[] buffer, int offset, int length) throws IOException {
+ return 1;
+ }
+
+ final int read() throws IOException {
+ return 1;
+ }
+
+ public void close() { }
+
+ public Reader getReader() {
+ return null;
+ }
+
+ protected IOException expect(String expect, int ch) {
+ return null;
+ }
+
+ protected String codeName(int ch) {
+ return null;
+ }
+
+ protected IOException error(String message) {
+ return null;
+ }
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/HessianRemoteResolver.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/HessianRemoteResolver.java
new file mode 100644
index 00000000000..3a6b7f86604
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/HessianRemoteResolver.java
@@ -0,0 +1,8 @@
+package com.caucho.hessian.io;
+
+import java.io.IOException;
+
+public interface HessianRemoteResolver {
+ Object lookup(String var1, String var2) throws IOException;
+}
+
diff --git a/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/SerializerFactory.java b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/SerializerFactory.java
new file mode 100644
index 00000000000..2e87899e6dd
--- /dev/null
+++ b/java/ql/test/stubs/hessian-4.0.38/com/caucho/hessian/io/SerializerFactory.java
@@ -0,0 +1,5 @@
+package com.caucho.hessian.io;
+
+public class SerializerFactory {
+
+}
diff --git a/java/ql/test/stubs/json-io-4.10.0/com/cedarsoftware/util/io/JsonReader.java b/java/ql/test/stubs/json-io-4.10.0/com/cedarsoftware/util/io/JsonReader.java
new file mode 100644
index 00000000000..75bfce50eeb
--- /dev/null
+++ b/java/ql/test/stubs/json-io-4.10.0/com/cedarsoftware/util/io/JsonReader.java
@@ -0,0 +1,41 @@
+package com.cedarsoftware.util.io;
+
+import java.io.Closeable;
+import java.io.InputStream;
+import java.util.Map;
+
+public class JsonReader implements Closeable {
+
+ public static Object jsonToJava(String json) {
+ return null;
+ }
+
+ public static Object jsonToJava(String json, Map optionalArgs) {
+ return null;
+ }
+
+ public static Object jsonToJava(InputStream inputStream, Map optionalArgs) {
+ return null;
+ }
+
+ public JsonReader() { }
+
+ public JsonReader(InputStream inp) { }
+
+ public JsonReader(Map optionalArgs) { }
+
+ public JsonReader(InputStream inp, boolean useMaps) { }
+
+ public JsonReader(InputStream inp, Map optionalArgs) { }
+
+ public JsonReader(String inp, Map optionalArgs) { }
+
+ public JsonReader(byte[] inp, Map optionalArgs) { }
+
+ public Object readObject() {
+ return null;
+ }
+
+ public void close() { }
+}
+
diff --git a/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/Yaml.java b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/Yaml.java
new file mode 100644
index 00000000000..43c10a12142
--- /dev/null
+++ b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/Yaml.java
@@ -0,0 +1,77 @@
+package org.ho.yaml;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.Reader;
+
+public class Yaml {
+
+ public Yaml() {
+ }
+
+ public static Object load(Reader var0) {
+ return null;
+ }
+
+ public static Object load(InputStream var0) {
+ return null;
+ }
+
+ public static Object load(File var0) throws FileNotFoundException {
+ return null;
+ }
+
+ public static Object load(String var0) {
+ return null;
+ }
+
+ public static T loadType(Reader var0, Class var1) {
+ return null;
+ }
+
+ public static T loadType(InputStream var0, Class var1) throws FileNotFoundException {
+ return null;
+ }
+
+ public static T loadType(File var0, Class var1) throws FileNotFoundException {
+ return null;
+ }
+
+ public static T loadType(String var0, Class var1) {
+ return null;
+ }
+
+ public static YamlStream loadStream(Reader var0) {
+ return null;
+ }
+
+ public static YamlStream loadStream(InputStream var0) {
+ return null;
+ }
+
+ public static YamlStream loadStream(File var0) throws FileNotFoundException {
+ return null;
+ }
+
+ public static YamlStream loadStream(String var0) {
+ return null;
+ }
+
+ public static YamlStream loadStreamOfType(Reader var0, Class var1) {
+ return null;
+ }
+
+ public static YamlStream loadStreamOfType(InputStream var0, Class var1) {
+ return null;
+ }
+
+ public static YamlStream loadStreamOfType(File var0, Class var1) throws FileNotFoundException {
+ return null;
+ }
+
+ public static YamlStream loadStreamOfType(String var0, Class var1) throws FileNotFoundException {
+ return null;
+ }
+}
+
diff --git a/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlConfig.java b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlConfig.java
new file mode 100644
index 00000000000..bdf3059eec7
--- /dev/null
+++ b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlConfig.java
@@ -0,0 +1,122 @@
+package org.ho.yaml;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.util.Iterator;
+
+public class YamlConfig implements YamlOperations, Cloneable {
+
+ public YamlConfig() { }
+
+ public Object load(YamlDecoder var1) {
+ return null;
+ }
+
+ public Object load(InputStream var1) {
+ return null;
+ }
+
+ public Object load(Reader var1) {
+ return null;
+ }
+
+ public Object load(File var1) throws FileNotFoundException {
+ return null;
+ }
+
+ public Object load(String var1) {
+ return null;
+ }
+
+ public T loadType(YamlDecoder var1, Class var2) {
+ return null;
+ }
+
+ public T loadType(InputStream var1, Class var2) {
+ return null;
+ }
+
+ public T loadType(Reader var1, Class var2) {
+ return null;
+ }
+
+ public T loadType(File var1, Class var2) throws FileNotFoundException {
+ return null;
+ }
+
+ public T loadType(String var1, Class var2) {
+ return null;
+ }
+
+ public YamlStream loadStream(YamlDecoder var1) {
+ return null;
+ }
+
+ public YamlStream loadStream(Reader var1) {
+ return null;
+ }
+
+ public YamlStream loadStream(InputStream var1) {
+ return null;
+ }
+
+ public YamlStream loadStream(File var1) throws FileNotFoundException {
+ return null;
+ }
+
+ public YamlStream loadStream(String var1) {
+ return null;
+ }
+
+ public YamlStream loadStreamOfType(YamlDecoder var1, Class var2) {
+ return null;
+ }
+
+ public YamlStream loadStreamOfType(Reader var1, Class var2) {
+ return null;
+ }
+
+ public YamlStream loadStreamOfType(InputStream var1, Class var2) {
+ return null;
+ }
+
+ public YamlStream loadStreamOfType(File var1, Class var2) throws FileNotFoundException {
+ return null;
+ }
+
+ public YamlStream loadStreamOfType(String var1, Class var2) {
+ return null;
+ }
+
+ public void dump(Object var1, File var2) throws FileNotFoundException { }
+
+ public void dump(Object var1, File var2, boolean var3) throws FileNotFoundException { }
+
+ public String dump(Object var1) {
+ return null;
+ }
+
+ public String dump(Object var1, boolean var2) {
+ return null;
+ }
+
+ public void dump(Object var1, OutputStream var2, boolean var3) { }
+
+ public void dump(Object var1, OutputStream var2) { }
+
+ public void dumpStream(Iterator var1, File var2, boolean var3) throws FileNotFoundException { }
+
+ public void dumpStream(Iterator var1, File var2) throws FileNotFoundException { }
+
+ public String dumpStream(Iterator var1) {
+ return null;
+ }
+
+ public String dumpStream(Iterator var1, boolean var2) {
+ return null;
+ }
+}
+
diff --git a/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlDecoder.java b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlDecoder.java
new file mode 100644
index 00000000000..b3bd4982a77
--- /dev/null
+++ b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlDecoder.java
@@ -0,0 +1,16 @@
+package org.ho.yaml;
+
+import java.io.InputStream;
+import java.io.Reader;
+
+public class YamlDecoder {
+
+ YamlDecoder(InputStream var1, YamlConfig var2) { }
+
+ public YamlDecoder(InputStream var1) { }
+
+ public YamlDecoder(Reader var1) { }
+
+ public YamlDecoder(Reader var1, YamlConfig var2) { }
+}
+
diff --git a/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlOperations.java b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlOperations.java
new file mode 100644
index 00000000000..b4af6ee7125
--- /dev/null
+++ b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlOperations.java
@@ -0,0 +1,63 @@
+package org.ho.yaml;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.util.Iterator;
+
+public interface YamlOperations {
+ Object load(InputStream var1);
+
+ Object load(Reader var1);
+
+ Object load(File var1) throws FileNotFoundException;
+
+ Object load(String var1);
+
+ T loadType(InputStream var1, Class var2);
+
+ T loadType(Reader var1, Class var2);
+
+ T loadType(File var1, Class var2) throws FileNotFoundException;
+
+ T loadType(String var1, Class var2);
+
+ YamlStream loadStream(InputStream var1);
+
+ YamlStream loadStream(Reader var1);
+
+ YamlStream loadStream(File var1) throws FileNotFoundException;
+
+ YamlStream loadStream(String var1);
+
+ YamlStream loadStreamOfType(InputStream var1, Class var2);
+
+ YamlStream loadStreamOfType(Reader var1, Class var2);
+
+ YamlStream loadStreamOfType(File var1, Class var2) throws FileNotFoundException;
+
+ YamlStream loadStreamOfType(String var1, Class var2);
+
+ void dump(Object var1, File var2) throws FileNotFoundException;
+
+ void dump(Object var1, File var2, boolean var3) throws FileNotFoundException;
+
+ String dump(Object var1);
+
+ String dump(Object var1, boolean var2);
+
+ void dumpStream(Iterator var1, File var2) throws FileNotFoundException;
+
+ void dumpStream(Iterator var1, File var2, boolean var3) throws FileNotFoundException;
+
+ String dumpStream(Iterator var1);
+
+ String dumpStream(Iterator var1, boolean var2);
+
+ void dump(Object var1, OutputStream var2);
+
+ void dump(Object var1, OutputStream var2, boolean var3);
+}
+
diff --git a/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlStream.java b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlStream.java
new file mode 100644
index 00000000000..53f0ddf144e
--- /dev/null
+++ b/java/ql/test/stubs/jyaml-1.3/org/ho/yaml/YamlStream.java
@@ -0,0 +1,7 @@
+package org.ho.yaml;
+
+import java.util.Iterator;
+
+public interface YamlStream extends Iterable, Iterator {
+}
+
diff --git a/java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlConfig.java b/java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlConfig.java
new file mode 100644
index 00000000000..3488ef83dab
--- /dev/null
+++ b/java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlConfig.java
@@ -0,0 +1,7 @@
+package com.esotericsoftware.yamlbeans;
+
+public class YamlConfig {
+
+ public YamlConfig() { }
+}
+
diff --git a/java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlException.java b/java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlException.java
new file mode 100644
index 00000000000..cb2e54f97e0
--- /dev/null
+++ b/java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlException.java
@@ -0,0 +1,18 @@
+package com.esotericsoftware.yamlbeans;
+
+import java.io.IOException;
+
+public class YamlException extends IOException {
+ public YamlException() {
+ }
+
+ public YamlException(String message, Throwable cause) {
+ }
+
+ public YamlException(String message) {
+ }
+
+ public YamlException(Throwable cause) {
+ }
+}
+
diff --git a/java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlReader.java b/java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlReader.java
new file mode 100644
index 00000000000..edaeeb911e0
--- /dev/null
+++ b/java/ql/test/stubs/yamlbeans-1.09/com/esotericsoftware/yamlbeans/YamlReader.java
@@ -0,0 +1,28 @@
+package com.esotericsoftware.yamlbeans;
+
+
+import java.io.Reader;
+
+public class YamlReader {
+
+ public YamlReader(Reader reader) { }
+
+ public YamlReader(Reader reader, YamlConfig config) { }
+
+ public YamlReader(String yaml) { }
+
+ public YamlReader(String yaml, YamlConfig config) { }
+
+ public Object read() throws YamlException {
+ return null;
+ }
+
+ public T read(Class type) throws YamlException {
+ return null;
+ }
+
+ public T read(Class type, Class elementType) throws YamlException {
+ return null;
+ }
+}
+
From 60fc607449b58f73e119cbffea699a303c0f10e0 Mon Sep 17 00:00:00 2001
From: haby0
Date: Fri, 14 May 2021 18:17:05 +0800
Subject: [PATCH 2/9] Modify ql
---
.../CWE/CWE-502/UnsafeDeserialization.ql | 40 +++++-----
.../semmle/code/java/frameworks/Castor.qll | 6 +-
.../{Hessian.qll => HessianBurlap.qll} | 20 ++---
.../src/semmle/code/java/frameworks/JYaml.qll | 8 +-
.../semmle/code/java/frameworks/JsonIo.qll | 36 +++++++--
.../semmle/code/java/frameworks/YamlBeans.qll | 10 +--
.../java/security/UnsafeDeserialization.qll | 36 ++-------
.../test/query-tests/security/CWE-502/C.java | 26 +++++--
.../CWE-502/UnsafeDeserialization.expected | 76 +++++++++----------
9 files changed, 139 insertions(+), 119 deletions(-)
rename java/ql/src/semmle/code/java/frameworks/{Hessian.qll => HessianBurlap.qll} (50%)
diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql
index 3a77af853cf..fe990179de4 100644
--- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql
+++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql
@@ -24,28 +24,14 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
override predicate isAdditionalTaintStep(DataFlow::Node prod, DataFlow::Node succ) {
exists(ClassInstanceExpr cie |
- cie.getConstructor().getDeclaringType() instanceof JsonReader and
cie.getArgument(0) = prod.asExpr() and
cie = succ.asExpr() and
- not exists(SafeJsonIo sji | sji.hasFlowToExpr(cie.getArgument(1)))
- )
- or
- exists(ClassInstanceExpr cie |
- cie.getConstructor().getDeclaringType() instanceof YamlReader and
- cie.getArgument(0) = prod.asExpr() and
- cie = succ.asExpr()
- )
- or
- exists(ClassInstanceExpr cie |
- cie.getConstructor().getDeclaringType() instanceof UnSafeHessianInput and
- cie.getArgument(0) = prod.asExpr() and
- cie = succ.asExpr()
- )
- or
- exists(ClassInstanceExpr cie |
- cie.getConstructor().getDeclaringType() instanceof BurlapInput and
- cie.getArgument(0) = prod.asExpr() and
- cie = succ.asExpr()
+ (
+ cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader or
+ cie.getConstructor().getDeclaringType() instanceof YamlBeansReader or
+ cie.getConstructor().getDeclaringType().getASupertype*() instanceof UnsafeHessianInput or
+ cie.getConstructor().getDeclaringType() instanceof BurlapInput
+ )
)
or
exists(MethodAccess ma |
@@ -54,6 +40,20 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
ma.getQualifier() = succ.asExpr()
)
}
+
+ override predicate isSanitizer(DataFlow::Node node) {
+ exists(ClassInstanceExpr cie |
+ cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and
+ cie = node.asExpr() and
+ exists(SafeJsonIoConfig sji | sji.hasFlowToExpr(cie.getArgument(1)))
+ )
+ or
+ exists(MethodAccess ma |
+ ma.getMethod() instanceof JsonIoJsonToJavaMethod and
+ ma.getArgument(0) = node.asExpr() and
+ exists(SafeJsonIoConfig sji | sji.hasFlowToExpr(ma.getArgument(1)))
+ )
+ }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeDeserializationConfig conf
diff --git a/java/ql/src/semmle/code/java/frameworks/Castor.qll b/java/ql/src/semmle/code/java/frameworks/Castor.qll
index 76abef7b5fe..16884849d51 100644
--- a/java/ql/src/semmle/code/java/frameworks/Castor.qll
+++ b/java/ql/src/semmle/code/java/frameworks/Castor.qll
@@ -7,14 +7,14 @@ import java
/**
* The class `org.exolab.castor.xml.Unmarshaller`.
*/
-class Unmarshaller extends RefType {
- Unmarshaller() { this.hasQualifiedName("org.exolab.castor.xml", "Unmarshaller") }
+class CastorUnmarshaller extends RefType {
+ CastorUnmarshaller() { this.hasQualifiedName("org.exolab.castor.xml", "Unmarshaller") }
}
/** A method with the name `unmarshal` declared in `org.exolab.castor.xml.Unmarshaller`. */
class UnmarshalMethod extends Method {
UnmarshalMethod() {
- this.getDeclaringType() instanceof Unmarshaller and
+ this.getDeclaringType() instanceof CastorUnmarshaller and
this.getName() = "unmarshal"
}
}
diff --git a/java/ql/src/semmle/code/java/frameworks/Hessian.qll b/java/ql/src/semmle/code/java/frameworks/HessianBurlap.qll
similarity index 50%
rename from java/ql/src/semmle/code/java/frameworks/Hessian.qll
rename to java/ql/src/semmle/code/java/frameworks/HessianBurlap.qll
index 78798d2b2fb..ce53e8261c1 100644
--- a/java/ql/src/semmle/code/java/frameworks/Hessian.qll
+++ b/java/ql/src/semmle/code/java/frameworks/HessianBurlap.qll
@@ -1,24 +1,26 @@
/**
- * Provides classes and predicates for working with the Hession framework.
+ * Provides classes and predicates for working with the HessianBurlap framework.
*/
import java
/**
- * The class `com.caucho.hessian.io.HessianInput` or `com.caucho.hessian.io.Hessian2Input`.
+ * The class `com.caucho.hessian.io.AbstractHessianInput` or `com.alibaba.com.caucho.hessian.io.Hessian2StreamingInput`.
*/
-class UnSafeHessianInput extends RefType {
- UnSafeHessianInput() {
- this.hasQualifiedName("com.caucho.hessian.io", ["HessianInput", "Hessian2Input"])
+class UnsafeHessianInput extends RefType {
+ UnsafeHessianInput() {
+ this.hasQualifiedName(["com.caucho.hessian.io", "com.alibaba.com.caucho.hessian.io"],
+ ["AbstractHessianInput", "Hessian2StreamingInput"])
}
}
/**
- * A HessianInput readObject method. This is either `HessianInput.readObject` or `Hessian2Input.readObject`.
+ * A AbstractHessianInput or Hessian2StreamingInput subclass readObject method.
+ * This is either `AbstractHessianInput.readObject` or `Hessian2StreamingInput.readObject`.
*/
-class UnSafeHessianInputReadObjectMethod extends Method {
- UnSafeHessianInputReadObjectMethod() {
- this.getDeclaringType() instanceof UnSafeHessianInput and
+class UnsafeHessianInputReadObjectMethod extends Method {
+ UnsafeHessianInputReadObjectMethod() {
+ this.getDeclaringType().getASupertype*() instanceof UnsafeHessianInput and
this.getName() = "readObject"
}
}
diff --git a/java/ql/src/semmle/code/java/frameworks/JYaml.qll b/java/ql/src/semmle/code/java/frameworks/JYaml.qll
index bf523bec202..1e0f3180607 100644
--- a/java/ql/src/semmle/code/java/frameworks/JYaml.qll
+++ b/java/ql/src/semmle/code/java/frameworks/JYaml.qll
@@ -15,8 +15,8 @@ class JYaml extends RefType {
* A JYaml unsafe load method. This is either `YAML.load` or
* `YAML.loadType` or `YAML.loadStream` or `YAML.loadStreamOfType`.
*/
-class JYamlUnSafeLoadMethod extends Method {
- JYamlUnSafeLoadMethod() {
+class JYamlUnsafeLoadMethod extends Method {
+ JYamlUnsafeLoadMethod() {
this.getDeclaringType() instanceof JYaml and
this.getName() in ["load", "loadType", "loadStream", "loadStreamOfType"]
}
@@ -33,8 +33,8 @@ class JYamlConfig extends RefType {
* A JYamlConfig unsafe load method. This is either `YamlConfig.load` or
* `YAML.loadType` or `YamlConfig.loadStream` or `YamlConfig.loadStreamOfType`.
*/
-class JYamlConfigUnSafeLoadMethod extends Method {
- JYamlConfigUnSafeLoadMethod() {
+class JYamlConfigUnsafeLoadMethod extends Method {
+ JYamlConfigUnsafeLoadMethod() {
this.getDeclaringType() instanceof JYamlConfig and
this.getName() in ["load", "loadType", "loadStream", "loadStreamOfType"]
}
diff --git a/java/ql/src/semmle/code/java/frameworks/JsonIo.qll b/java/ql/src/semmle/code/java/frameworks/JsonIo.qll
index 4170488f78d..1a2acf754ad 100644
--- a/java/ql/src/semmle/code/java/frameworks/JsonIo.qll
+++ b/java/ql/src/semmle/code/java/frameworks/JsonIo.qll
@@ -4,18 +4,20 @@
import java
import semmle.code.java.Maps
+import semmle.code.java.dataflow.DataFlow
+import semmle.code.java.dataflow.DataFlow2
/**
* The class `com.cedarsoftware.util.io.JsonReader`.
*/
-class JsonReader extends RefType {
- JsonReader() { this.hasQualifiedName("com.cedarsoftware.util.io", "JsonReader") }
+class JsonIoJsonReader extends RefType {
+ JsonIoJsonReader() { this.hasQualifiedName("com.cedarsoftware.util.io", "JsonReader") }
}
/** A method with the name `jsonToJava` declared in `com.cedarsoftware.util.io.JsonReader`. */
class JsonIoJsonToJavaMethod extends Method {
JsonIoJsonToJavaMethod() {
- this.getDeclaringType() instanceof JsonReader and
+ this.getDeclaringType() instanceof JsonIoJsonReader and
this.getName() = "jsonToJava"
}
}
@@ -23,13 +25,13 @@ class JsonIoJsonToJavaMethod extends Method {
/** A method with the name `readObject` declared in `com.cedarsoftware.util.io.JsonReader`. */
class JsonIoReadObjectMethod extends Method {
JsonIoReadObjectMethod() {
- this.getDeclaringType() instanceof JsonReader and
+ this.getDeclaringType() instanceof JsonIoJsonReader and
this.getName() = "readObject"
}
}
/**
- * A call to `Map.put` method, set the value of the `USE_MAPS` key to `true`.
+ * A call to `Map.put` method, set the value of the `USE_MAPS` key to `true`.
*/
class JsonIoSafeOptionalArgs extends MethodAccess {
JsonIoSafeOptionalArgs() {
@@ -39,3 +41,27 @@ class JsonIoSafeOptionalArgs extends MethodAccess {
this.getArgument(1).(CompileTimeConstantExpr).getBooleanValue() = true
}
}
+
+/** A data flow configuration tracing flow from JsonIo safe settings. */
+class SafeJsonIoConfig extends DataFlow2::Configuration {
+ SafeJsonIoConfig() { this = "UnsafeDeserialization::SafeJsonIoConfig" }
+
+ override predicate isSource(DataFlow::Node src) {
+ exists(MethodAccess ma |
+ ma instanceof JsonIoSafeOptionalArgs and
+ src.asExpr() = ma.getQualifier()
+ )
+ }
+
+ override predicate isSink(DataFlow::Node sink) {
+ exists(MethodAccess ma |
+ ma.getMethod() instanceof JsonIoJsonToJavaMethod and
+ sink.asExpr() = ma.getArgument(1)
+ )
+ or
+ exists(ClassInstanceExpr cie |
+ cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and
+ sink.asExpr() = cie.getArgument(1)
+ )
+ }
+}
diff --git a/java/ql/src/semmle/code/java/frameworks/YamlBeans.qll b/java/ql/src/semmle/code/java/frameworks/YamlBeans.qll
index 63c282a80ec..b5db59926be 100644
--- a/java/ql/src/semmle/code/java/frameworks/YamlBeans.qll
+++ b/java/ql/src/semmle/code/java/frameworks/YamlBeans.qll
@@ -7,14 +7,14 @@ import java
/**
* The class `com.esotericsoftware.yamlbeans.YamlReader`.
*/
-class YamlReader extends RefType {
- YamlReader() { this.hasQualifiedName("com.esotericsoftware.yamlbeans", "YamlReader") }
+class YamlBeansReader extends RefType {
+ YamlBeansReader() { this.hasQualifiedName("com.esotericsoftware.yamlbeans", "YamlReader") }
}
/** A method with the name `read` declared in `com.esotericsoftware.yamlbeans.YamlReader`. */
-class YamlReaderReadMethod extends Method {
- YamlReaderReadMethod() {
- this.getDeclaringType() instanceof YamlReader and
+class YamlBeansReaderReadMethod extends Method {
+ YamlBeansReaderReadMethod() {
+ this.getDeclaringType() instanceof YamlBeansReader and
this.getName() = "read"
}
}
diff --git a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
index 377303601d4..4f5070edb2a 100644
--- a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
+++ b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
@@ -5,7 +5,7 @@ import semmle.code.java.frameworks.FastJson
import semmle.code.java.frameworks.JYaml
import semmle.code.java.frameworks.JsonIo
import semmle.code.java.frameworks.YamlBeans
-import semmle.code.java.frameworks.Hessian
+import semmle.code.java.frameworks.HessianBurlap
import semmle.code.java.frameworks.Castor
import semmle.code.java.frameworks.apache.Lang
@@ -55,29 +55,6 @@ class SafeKryo extends DataFlow2::Configuration {
}
}
-class SafeJsonIo extends DataFlow2::Configuration {
- SafeJsonIo() { this = "UnsafeDeserialization::SafeJsonIo" }
-
- override predicate isSource(DataFlow::Node src) {
- exists(MethodAccess ma |
- ma instanceof JsonIoSafeOptionalArgs and
- src.asExpr() = ma.getQualifier()
- )
- }
-
- override predicate isSink(DataFlow::Node sink) {
- exists(MethodAccess ma |
- ma.getMethod() instanceof JsonIoJsonToJavaMethod and
- sink.asExpr() = ma.getArgument(1)
- )
- or
- exists(ClassInstanceExpr cie |
- cie.getConstructor().getDeclaringType() instanceof JsonReader and
- sink.asExpr() = cie.getArgument(1)
- )
- }
-}
-
predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
exists(Method m | m = ma.getMethod() |
m instanceof ObjectInputStreamReadObjectMethod and
@@ -110,22 +87,21 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
not fastJsonLooksSafe() and
sink = ma.getArgument(0)
or
- ma.getMethod() instanceof JYamlUnSafeLoadMethod and
+ ma.getMethod() instanceof JYamlUnsafeLoadMethod and
sink = ma.getArgument(0)
or
- ma.getMethod() instanceof JYamlConfigUnSafeLoadMethod and
+ ma.getMethod() instanceof JYamlConfigUnsafeLoadMethod and
sink = ma.getArgument(0)
or
ma.getMethod() instanceof JsonIoJsonToJavaMethod and
- sink = ma.getArgument(0) and
- not exists(SafeJsonIo sji | sji.hasFlowToExpr(ma.getArgument(1)))
+ sink = ma.getArgument(0)
or
ma.getMethod() instanceof JsonIoReadObjectMethod and
sink = ma.getQualifier()
or
- ma.getMethod() instanceof YamlReaderReadMethod and sink = ma.getQualifier()
+ ma.getMethod() instanceof YamlBeansReaderReadMethod and sink = ma.getQualifier()
or
- ma.getMethod() instanceof UnSafeHessianInputReadObjectMethod and sink = ma.getQualifier()
+ ma.getMethod() instanceof UnsafeHessianInputReadObjectMethod and sink = ma.getQualifier()
or
ma.getMethod() instanceof UnmarshalMethod and sink = ma.getAnArgument()
or
diff --git a/java/ql/test/query-tests/security/CWE-502/C.java b/java/ql/test/query-tests/security/CWE-502/C.java
index ede36d8410b..bae0ca8ceae 100644
--- a/java/ql/test/query-tests/security/CWE-502/C.java
+++ b/java/ql/test/query-tests/security/CWE-502/C.java
@@ -42,13 +42,8 @@ public class C {
JsonReader.jsonToJava(data); //bad
- JsonReader.jsonToJava(data, hashMap); //good
-
JsonReader jr = new JsonReader(data, null); //bad
jr.readObject();
-
- JsonReader jr1 = new JsonReader(data, hashMap); //good
- jr1.readObject();
}
@GetMapping(value = "yamlbeans")
@@ -95,4 +90,25 @@ public class C {
burlapInput1.init(is);
burlapInput1.readObject(); //bad
}
+
+ @GetMapping(value = "jsonio1")
+ public void good1(HttpServletRequest request) {
+ String data = request.getParameter("data");
+
+ HashMap hashMap = new HashMap();
+ hashMap.put("USE_MAPS", true);
+
+ JsonReader.jsonToJava(data, hashMap); //good
+ }
+
+ @GetMapping(value = "jsonio2")
+ public void good2(HttpServletRequest request) {
+ String data = request.getParameter("data");
+
+ HashMap hashMap = new HashMap();
+ hashMap.put("USE_MAPS", true);
+
+ JsonReader jr1 = new JsonReader(data, hashMap); //good
+ jr1.readObject();
+ }
}
diff --git a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
index d583caafc9b..6f25b28bda5 100644
--- a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
+++ b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
@@ -34,17 +34,17 @@ edges
| C.java:23:17:23:44 | getParameter(...) : String | C.java:32:31:32:34 | data |
| C.java:23:17:23:44 | getParameter(...) : String | C.java:33:23:33:26 | data |
| C.java:38:17:38:44 | getParameter(...) : String | C.java:43:25:43:28 | data |
-| C.java:38:17:38:44 | getParameter(...) : String | C.java:48:3:48:4 | jr |
-| C.java:56:17:56:44 | getParameter(...) : String | C.java:58:3:58:3 | r |
-| C.java:56:17:56:44 | getParameter(...) : String | C.java:59:3:59:3 | r |
-| C.java:56:17:56:44 | getParameter(...) : String | C.java:60:3:60:3 | r |
-| C.java:65:18:65:45 | getParameter(...) : String | C.java:68:3:68:14 | hessianInput |
-| C.java:65:18:65:45 | getParameter(...) : String | C.java:69:3:69:14 | hessianInput |
-| C.java:74:18:74:45 | getParameter(...) : String | C.java:77:3:77:14 | hessianInput |
-| C.java:74:18:74:45 | getParameter(...) : String | C.java:78:3:78:14 | hessianInput |
-| C.java:84:43:84:70 | getParameter(...) : String | C.java:84:26:84:71 | new StringReader(...) |
-| C.java:89:27:89:54 | getParameter(...) : String | C.java:92:3:92:13 | burlapInput |
-| C.java:89:27:89:54 | getParameter(...) : String | C.java:96:3:96:14 | burlapInput1 |
+| C.java:38:17:38:44 | getParameter(...) : String | C.java:46:3:46:4 | jr |
+| C.java:51:17:51:44 | getParameter(...) : String | C.java:53:3:53:3 | r |
+| C.java:51:17:51:44 | getParameter(...) : String | C.java:54:3:54:3 | r |
+| C.java:51:17:51:44 | getParameter(...) : String | C.java:55:3:55:3 | r |
+| C.java:60:18:60:45 | getParameter(...) : String | C.java:63:3:63:14 | hessianInput |
+| C.java:60:18:60:45 | getParameter(...) : String | C.java:64:3:64:14 | hessianInput |
+| C.java:69:18:69:45 | getParameter(...) : String | C.java:72:3:72:14 | hessianInput |
+| C.java:69:18:69:45 | getParameter(...) : String | C.java:73:3:73:14 | hessianInput |
+| C.java:79:43:79:70 | getParameter(...) : String | C.java:79:26:79:71 | new StringReader(...) |
+| C.java:84:27:84:54 | getParameter(...) : String | C.java:87:3:87:13 | burlapInput |
+| C.java:84:27:84:54 | getParameter(...) : String | C.java:91:3:91:14 | burlapInput1 |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
nodes
| A.java:13:31:13:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
@@ -96,22 +96,22 @@ nodes
| C.java:33:23:33:26 | data | semmle.label | data |
| C.java:38:17:38:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| C.java:43:25:43:28 | data | semmle.label | data |
-| C.java:48:3:48:4 | jr | semmle.label | jr |
-| C.java:56:17:56:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| C.java:58:3:58:3 | r | semmle.label | r |
-| C.java:59:3:59:3 | r | semmle.label | r |
-| C.java:60:3:60:3 | r | semmle.label | r |
-| C.java:65:18:65:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| C.java:68:3:68:14 | hessianInput | semmle.label | hessianInput |
-| C.java:69:3:69:14 | hessianInput | semmle.label | hessianInput |
-| C.java:74:18:74:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| C.java:77:3:77:14 | hessianInput | semmle.label | hessianInput |
-| C.java:78:3:78:14 | hessianInput | semmle.label | hessianInput |
-| C.java:84:26:84:71 | new StringReader(...) | semmle.label | new StringReader(...) |
-| C.java:84:43:84:70 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| C.java:89:27:89:54 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| C.java:92:3:92:13 | burlapInput | semmle.label | burlapInput |
-| C.java:96:3:96:14 | burlapInput1 | semmle.label | burlapInput1 |
+| C.java:46:3:46:4 | jr | semmle.label | jr |
+| C.java:51:17:51:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:53:3:53:3 | r | semmle.label | r |
+| C.java:54:3:54:3 | r | semmle.label | r |
+| C.java:55:3:55:3 | r | semmle.label | r |
+| C.java:60:18:60:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:63:3:63:14 | hessianInput | semmle.label | hessianInput |
+| C.java:64:3:64:14 | hessianInput | semmle.label | hessianInput |
+| C.java:69:18:69:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:72:3:72:14 | hessianInput | semmle.label | hessianInput |
+| C.java:73:3:73:14 | hessianInput | semmle.label | hessianInput |
+| C.java:79:26:79:71 | new StringReader(...) | semmle.label | new StringReader(...) |
+| C.java:79:43:79:70 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:84:27:84:54 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:87:3:87:13 | burlapInput | semmle.label | burlapInput |
+| C.java:91:3:91:14 | burlapInput1 | semmle.label | burlapInput1 |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | semmle.label | entityStream : InputStream |
| TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | semmle.label | new ObjectInputStream(...) |
#select
@@ -150,15 +150,15 @@ nodes
| C.java:32:3:32:49 | loadStreamOfType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:32:31:32:34 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
| C.java:33:3:33:41 | loadType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:33:23:33:26 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
| C.java:43:3:43:29 | jsonToJava(...) | C.java:38:17:38:44 | getParameter(...) : String | C.java:43:25:43:28 | data | Unsafe deserialization of $@. | C.java:38:17:38:44 | getParameter(...) | user input |
-| C.java:48:3:48:17 | readObject(...) | C.java:38:17:38:44 | getParameter(...) : String | C.java:48:3:48:4 | jr | Unsafe deserialization of $@. | C.java:38:17:38:44 | getParameter(...) | user input |
-| C.java:58:3:58:10 | read(...) | C.java:56:17:56:44 | getParameter(...) : String | C.java:58:3:58:3 | r | Unsafe deserialization of $@. | C.java:56:17:56:44 | getParameter(...) | user input |
-| C.java:59:3:59:22 | read(...) | C.java:56:17:56:44 | getParameter(...) : String | C.java:59:3:59:3 | r | Unsafe deserialization of $@. | C.java:56:17:56:44 | getParameter(...) | user input |
-| C.java:60:3:60:36 | read(...) | C.java:56:17:56:44 | getParameter(...) : String | C.java:60:3:60:3 | r | Unsafe deserialization of $@. | C.java:56:17:56:44 | getParameter(...) | user input |
-| C.java:68:3:68:27 | readObject(...) | C.java:65:18:65:45 | getParameter(...) : String | C.java:68:3:68:14 | hessianInput | Unsafe deserialization of $@. | C.java:65:18:65:45 | getParameter(...) | user input |
-| C.java:69:3:69:39 | readObject(...) | C.java:65:18:65:45 | getParameter(...) : String | C.java:69:3:69:14 | hessianInput | Unsafe deserialization of $@. | C.java:65:18:65:45 | getParameter(...) | user input |
-| C.java:77:3:77:27 | readObject(...) | C.java:74:18:74:45 | getParameter(...) : String | C.java:77:3:77:14 | hessianInput | Unsafe deserialization of $@. | C.java:74:18:74:45 | getParameter(...) | user input |
-| C.java:78:3:78:39 | readObject(...) | C.java:74:18:74:45 | getParameter(...) : String | C.java:78:3:78:14 | hessianInput | Unsafe deserialization of $@. | C.java:74:18:74:45 | getParameter(...) | user input |
-| C.java:84:3:84:72 | unmarshal(...) | C.java:84:43:84:70 | getParameter(...) : String | C.java:84:26:84:71 | new StringReader(...) | Unsafe deserialization of $@. | C.java:84:43:84:70 | getParameter(...) | user input |
-| C.java:92:3:92:26 | readObject(...) | C.java:89:27:89:54 | getParameter(...) : String | C.java:92:3:92:13 | burlapInput | Unsafe deserialization of $@. | C.java:89:27:89:54 | getParameter(...) | user input |
-| C.java:96:3:96:27 | readObject(...) | C.java:89:27:89:54 | getParameter(...) : String | C.java:96:3:96:14 | burlapInput1 | Unsafe deserialization of $@. | C.java:89:27:89:54 | getParameter(...) | user input |
+| C.java:46:3:46:17 | readObject(...) | C.java:38:17:38:44 | getParameter(...) : String | C.java:46:3:46:4 | jr | Unsafe deserialization of $@. | C.java:38:17:38:44 | getParameter(...) | user input |
+| C.java:53:3:53:10 | read(...) | C.java:51:17:51:44 | getParameter(...) : String | C.java:53:3:53:3 | r | Unsafe deserialization of $@. | C.java:51:17:51:44 | getParameter(...) | user input |
+| C.java:54:3:54:22 | read(...) | C.java:51:17:51:44 | getParameter(...) : String | C.java:54:3:54:3 | r | Unsafe deserialization of $@. | C.java:51:17:51:44 | getParameter(...) | user input |
+| C.java:55:3:55:36 | read(...) | C.java:51:17:51:44 | getParameter(...) : String | C.java:55:3:55:3 | r | Unsafe deserialization of $@. | C.java:51:17:51:44 | getParameter(...) | user input |
+| C.java:63:3:63:27 | readObject(...) | C.java:60:18:60:45 | getParameter(...) : String | C.java:63:3:63:14 | hessianInput | Unsafe deserialization of $@. | C.java:60:18:60:45 | getParameter(...) | user input |
+| C.java:64:3:64:39 | readObject(...) | C.java:60:18:60:45 | getParameter(...) : String | C.java:64:3:64:14 | hessianInput | Unsafe deserialization of $@. | C.java:60:18:60:45 | getParameter(...) | user input |
+| C.java:72:3:72:27 | readObject(...) | C.java:69:18:69:45 | getParameter(...) : String | C.java:72:3:72:14 | hessianInput | Unsafe deserialization of $@. | C.java:69:18:69:45 | getParameter(...) | user input |
+| C.java:73:3:73:39 | readObject(...) | C.java:69:18:69:45 | getParameter(...) : String | C.java:73:3:73:14 | hessianInput | Unsafe deserialization of $@. | C.java:69:18:69:45 | getParameter(...) | user input |
+| C.java:79:3:79:72 | unmarshal(...) | C.java:79:43:79:70 | getParameter(...) : String | C.java:79:26:79:71 | new StringReader(...) | Unsafe deserialization of $@. | C.java:79:43:79:70 | getParameter(...) | user input |
+| C.java:87:3:87:26 | readObject(...) | C.java:84:27:84:54 | getParameter(...) : String | C.java:87:3:87:13 | burlapInput | Unsafe deserialization of $@. | C.java:84:27:84:54 | getParameter(...) | user input |
+| C.java:91:3:91:27 | readObject(...) | C.java:84:27:84:54 | getParameter(...) : String | C.java:91:3:91:14 | burlapInput1 | Unsafe deserialization of $@. | C.java:84:27:84:54 | getParameter(...) | user input |
| TestMessageBodyReader.java:22:18:22:65 | readObject(...) | TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | Unsafe deserialization of $@. | TestMessageBodyReader.java:20:55:20:78 | entityStream | user input |
From 58d774ae85b7af152b28fce465c315c0a0bed5e4 Mon Sep 17 00:00:00 2001
From: haby0
Date: Mon, 17 May 2021 14:52:05 +0800
Subject: [PATCH 3/9] add change notes
---
...-05-17-add-unsafe-deserialization-sinks.md | 3 ++
.../CWE/CWE-502/UnsafeDeserialization.qhelp | 2 +-
.../code/java/frameworks/HessianBurlap.qll | 2 +-
.../src/semmle/code/java/frameworks/JYaml.qll | 33 ++++---------------
.../java/security/UnsafeDeserialization.qll | 5 +--
5 files changed, 13 insertions(+), 32 deletions(-)
create mode 100644 java/change-notes/2021-05-17-add-unsafe-deserialization-sinks.md
diff --git a/java/change-notes/2021-05-17-add-unsafe-deserialization-sinks.md b/java/change-notes/2021-05-17-add-unsafe-deserialization-sinks.md
new file mode 100644
index 00000000000..2304cecbf49
--- /dev/null
+++ b/java/change-notes/2021-05-17-add-unsafe-deserialization-sinks.md
@@ -0,0 +1,3 @@
+lgtm,codescanning
+* The "Deserialization of user-controlled data" (`java/unsafe-deserialization`) query
+ now recognizes `JYaml`, `JsonIO`, `YAMLBeans`, `HessianBurlap`, `Castor`, `Burlap` deserialization.
diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp
index ce7f4751800..f1831ac5c21 100644
--- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp
+++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp
@@ -14,7 +14,7 @@ may have unforeseen effects, such as the execution of arbitrary code.
There are many different serialization frameworks. This query currently
-supports Kryo, XmlDecoder, XStream, SnakeYaml, Hessian, JsonIO, YAMLBeans, Castor, Burlap,
+supports Kryo, XmlDecoder, XStream, SnakeYaml, JYaml, JsonIO, YAMLBeans, HessianBurlap, Castor, Burlap
and Java IO serialization through ObjectInputStream/ObjectOutputStream.
diff --git a/java/ql/src/semmle/code/java/frameworks/HessianBurlap.qll b/java/ql/src/semmle/code/java/frameworks/HessianBurlap.qll
index ce53e8261c1..95803d192a7 100644
--- a/java/ql/src/semmle/code/java/frameworks/HessianBurlap.qll
+++ b/java/ql/src/semmle/code/java/frameworks/HessianBurlap.qll
@@ -5,7 +5,7 @@
import java
/**
- * The class `com.caucho.hessian.io.AbstractHessianInput` or `com.alibaba.com.caucho.hessian.io.Hessian2StreamingInput`.
+ * The classes `[com.alibaba.]com.caucho.hessian.io.AbstractHessianInput` or `[com.alibaba.]com.caucho.hessian.io.Hessian2StreamingInput`.
*/
class UnsafeHessianInput extends RefType {
UnsafeHessianInput() {
diff --git a/java/ql/src/semmle/code/java/frameworks/JYaml.qll b/java/ql/src/semmle/code/java/frameworks/JYaml.qll
index 1e0f3180607..9d77b86f6c1 100644
--- a/java/ql/src/semmle/code/java/frameworks/JYaml.qll
+++ b/java/ql/src/semmle/code/java/frameworks/JYaml.qll
@@ -5,37 +5,18 @@
import java
/**
- * The class `org.ho.yaml.Yaml`.
+ * The class `org.ho.yaml.Yaml` or `org.ho.yaml.YamlConfig`.
*/
-class JYaml extends RefType {
- JYaml() { this.hasQualifiedName("org.ho.yaml", "Yaml") }
+class JYamlLoader extends RefType {
+ JYamlLoader() { this.hasQualifiedName("org.ho.yaml", ["Yaml", "YamlConfig"]) }
}
/**
- * A JYaml unsafe load method. This is either `YAML.load` or
- * `YAML.loadType` or `YAML.loadStream` or `YAML.loadStreamOfType`.
+ * A JYaml unsafe load method, declared on either `Yaml` or `YamlConfig`.
*/
-class JYamlUnsafeLoadMethod extends Method {
- JYamlUnsafeLoadMethod() {
- this.getDeclaringType() instanceof JYaml and
- this.getName() in ["load", "loadType", "loadStream", "loadStreamOfType"]
- }
-}
-
-/**
- * The class `org.ho.yaml.YamlConfig`.
- */
-class JYamlConfig extends RefType {
- JYamlConfig() { this.hasQualifiedName("org.ho.yaml", "YamlConfig") }
-}
-
-/**
- * A JYamlConfig unsafe load method. This is either `YamlConfig.load` or
- * `YAML.loadType` or `YamlConfig.loadStream` or `YamlConfig.loadStreamOfType`.
- */
-class JYamlConfigUnsafeLoadMethod extends Method {
- JYamlConfigUnsafeLoadMethod() {
- this.getDeclaringType() instanceof JYamlConfig and
+class JYamlLoaderUnsafeLoadMethod extends Method {
+ JYamlLoaderUnsafeLoadMethod() {
+ this.getDeclaringType() instanceof JYamlLoader and
this.getName() in ["load", "loadType", "loadStream", "loadStreamOfType"]
}
}
diff --git a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
index 4f5070edb2a..41840e4c1f7 100644
--- a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
+++ b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
@@ -87,10 +87,7 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
not fastJsonLooksSafe() and
sink = ma.getArgument(0)
or
- ma.getMethod() instanceof JYamlUnsafeLoadMethod and
- sink = ma.getArgument(0)
- or
- ma.getMethod() instanceof JYamlConfigUnsafeLoadMethod and
+ ma.getMethod() instanceof JYamlLoaderUnsafeLoadMethod and
sink = ma.getArgument(0)
or
ma.getMethod() instanceof JsonIoJsonToJavaMethod and
From 95c33a240fe962487a1597cd9d307a925e591790 Mon Sep 17 00:00:00 2001
From: haby0
Date: Mon, 17 May 2021 18:49:16 +0800
Subject: [PATCH 4/9] Update
java/change-notes/2021-05-17-add-unsafe-deserialization-sinks.md
Co-authored-by: Chris Smowton
---
.../change-notes/2021-05-17-add-unsafe-deserialization-sinks.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/change-notes/2021-05-17-add-unsafe-deserialization-sinks.md b/java/change-notes/2021-05-17-add-unsafe-deserialization-sinks.md
index 2304cecbf49..f294b223d01 100644
--- a/java/change-notes/2021-05-17-add-unsafe-deserialization-sinks.md
+++ b/java/change-notes/2021-05-17-add-unsafe-deserialization-sinks.md
@@ -1,3 +1,3 @@
lgtm,codescanning
* The "Deserialization of user-controlled data" (`java/unsafe-deserialization`) query
- now recognizes `JYaml`, `JsonIO`, `YAMLBeans`, `HessianBurlap`, `Castor`, `Burlap` deserialization.
+ now recognizes `JYaml`, `JsonIO`, `YAMLBeans`, `Castor`, `Hessian` and `Burlap` deserialization.
From 689c28a1780eb1aa83fb6ea0ccc5c71d642cf2f4 Mon Sep 17 00:00:00 2001
From: haby0
Date: Mon, 17 May 2021 19:00:59 +0800
Subject: [PATCH 5/9] modified JsonIoSafeOptionalArgs
---
java/ql/src/semmle/code/java/frameworks/JsonIo.qll | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/java/ql/src/semmle/code/java/frameworks/JsonIo.qll b/java/ql/src/semmle/code/java/frameworks/JsonIo.qll
index 1a2acf754ad..ab4c1b115d9 100644
--- a/java/ql/src/semmle/code/java/frameworks/JsonIo.qll
+++ b/java/ql/src/semmle/code/java/frameworks/JsonIo.qll
@@ -33,8 +33,8 @@ class JsonIoReadObjectMethod extends Method {
/**
* A call to `Map.put` method, set the value of the `USE_MAPS` key to `true`.
*/
-class JsonIoSafeOptionalArgs extends MethodAccess {
- JsonIoSafeOptionalArgs() {
+class JsonIoUseMapsSetter extends MethodAccess {
+ JsonIoUseMapsSetter() {
this.getMethod().getDeclaringType().getASourceSupertype*() instanceof MapType and
this.getMethod().hasName("put") and
this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "USE_MAPS" and
@@ -48,7 +48,7 @@ class SafeJsonIoConfig extends DataFlow2::Configuration {
override predicate isSource(DataFlow::Node src) {
exists(MethodAccess ma |
- ma instanceof JsonIoSafeOptionalArgs and
+ ma instanceof JsonIoUseMapsSetter and
src.asExpr() = ma.getQualifier()
)
}
From d6782767b7c289a68baaaf037245047a4ba9d844 Mon Sep 17 00:00:00 2001
From: haby0
Date: Mon, 31 May 2021 11:12:22 +0800
Subject: [PATCH 6/9] Fix typos
---
java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql
index fe990179de4..27ababae1d4 100644
--- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql
+++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql
@@ -22,9 +22,9 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink }
- override predicate isAdditionalTaintStep(DataFlow::Node prod, DataFlow::Node succ) {
+ override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(ClassInstanceExpr cie |
- cie.getArgument(0) = prod.asExpr() and
+ cie.getArgument(0) = pred.asExpr() and
cie = succ.asExpr() and
(
cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader or
@@ -36,7 +36,7 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
or
exists(MethodAccess ma |
ma.getMethod() instanceof BurlapInputInitMethod and
- ma.getArgument(0) = prod.asExpr() and
+ ma.getArgument(0) = pred.asExpr() and
ma.getQualifier() = succ.asExpr()
)
}
From 9badd7aa274ad6a3af01ff354781c6dece0725f4 Mon Sep 17 00:00:00 2001
From: haby0
Date: Wed, 16 Jun 2021 11:29:37 +0800
Subject: [PATCH 7/9] change name
---
java/ql/src/semmle/code/java/frameworks/Castor.qll | 4 ++--
.../src/semmle/code/java/security/UnsafeDeserialization.qll | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/java/ql/src/semmle/code/java/frameworks/Castor.qll b/java/ql/src/semmle/code/java/frameworks/Castor.qll
index 16884849d51..f1e1b825725 100644
--- a/java/ql/src/semmle/code/java/frameworks/Castor.qll
+++ b/java/ql/src/semmle/code/java/frameworks/Castor.qll
@@ -12,8 +12,8 @@ class CastorUnmarshaller extends RefType {
}
/** A method with the name `unmarshal` declared in `org.exolab.castor.xml.Unmarshaller`. */
-class UnmarshalMethod extends Method {
- UnmarshalMethod() {
+class CastorUnmarshalMethod extends Method {
+ CastorUnmarshalMethod() {
this.getDeclaringType() instanceof CastorUnmarshaller and
this.getName() = "unmarshal"
}
diff --git a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
index 41840e4c1f7..b8cc7ede9bc 100644
--- a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
+++ b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
@@ -100,7 +100,7 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
or
ma.getMethod() instanceof UnsafeHessianInputReadObjectMethod and sink = ma.getQualifier()
or
- ma.getMethod() instanceof UnmarshalMethod and sink = ma.getAnArgument()
+ ma.getMethod() instanceof CastorUnmarshalMethod and sink = ma.getAnArgument()
or
ma.getMethod() instanceof BurlapInputReadObjectMethod and sink = ma.getQualifier()
)
From 3dd851fffb39bef31907ed6d15015f1051f91af6 Mon Sep 17 00:00:00 2001
From: haby0
Date: Thu, 17 Jun 2021 15:20:03 +0800
Subject: [PATCH 8/9] expected
---
.../CWE-502/UnsafeDeserialization.expected | 75 ++++---------------
1 file changed, 14 insertions(+), 61 deletions(-)
diff --git a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
index 99b8c2ea94c..6f25b28bda5 100644
--- a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
+++ b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
@@ -1,53 +1,30 @@
edges
-| A.java:13:31:13:51 | getInputStream(...) : InputStream | A.java:14:50:14:60 | inputStream : InputStream |
| A.java:13:31:13:51 | getInputStream(...) : InputStream | A.java:15:12:15:13 | in |
-| A.java:14:28:14:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:15:12:15:13 | in |
-| A.java:14:50:14:60 | inputStream : InputStream | A.java:14:28:14:61 | new ObjectInputStream(...) : ObjectInputStream |
-| A.java:19:31:19:51 | getInputStream(...) : InputStream | A.java:20:50:20:60 | inputStream : InputStream |
| A.java:19:31:19:51 | getInputStream(...) : InputStream | A.java:21:12:21:13 | in |
-| A.java:20:28:20:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:21:12:21:13 | in |
-| A.java:20:50:20:60 | inputStream : InputStream | A.java:20:28:20:61 | new ObjectInputStream(...) : ObjectInputStream |
-| A.java:25:31:25:51 | getInputStream(...) : InputStream | A.java:26:35:26:45 | inputStream : InputStream |
-| A.java:26:20:26:46 | new XMLDecoder(...) : XMLDecoder | A.java:27:12:27:12 | d |
-| A.java:26:35:26:45 | inputStream : InputStream | A.java:26:20:26:46 | new XMLDecoder(...) : XMLDecoder |
-| A.java:32:31:32:51 | getInputStream(...) : InputStream | A.java:33:43:33:53 | inputStream : InputStream |
-| A.java:33:21:33:54 | new InputStreamReader(...) : InputStreamReader | A.java:34:23:34:28 | reader |
-| A.java:33:43:33:53 | inputStream : InputStream | A.java:33:21:33:54 | new InputStreamReader(...) : InputStreamReader |
-| A.java:39:19:39:50 | new Input(...) : Input | A.java:40:28:40:32 | input |
-| A.java:39:19:39:50 | new Input(...) : Input | A.java:41:34:41:38 | input |
-| A.java:39:19:39:50 | new Input(...) : Input | A.java:42:40:42:44 | input |
-| A.java:39:29:39:49 | getInputStream(...) : InputStream | A.java:39:19:39:50 | new Input(...) : Input |
+| A.java:25:31:25:51 | getInputStream(...) : InputStream | A.java:27:12:27:12 | d |
+| A.java:32:31:32:51 | getInputStream(...) : InputStream | A.java:34:23:34:28 | reader |
+| A.java:39:29:39:49 | getInputStream(...) : InputStream | A.java:40:28:40:32 | input |
+| A.java:39:29:39:49 | getInputStream(...) : InputStream | A.java:41:34:41:38 | input |
+| A.java:39:29:39:49 | getInputStream(...) : InputStream | A.java:42:40:42:44 | input |
| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:61:26:61:30 | input |
| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:62:30:62:34 | input |
-| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:63:50:63:54 | input : InputStream |
+| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:63:28:63:55 | new InputStreamReader(...) |
| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:64:24:64:28 | input |
-| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:65:46:65:50 | input : InputStream |
-| A.java:63:50:63:54 | input : InputStream | A.java:63:28:63:55 | new InputStreamReader(...) |
-| A.java:65:46:65:50 | input : InputStream | A.java:65:24:65:51 | new InputStreamReader(...) |
+| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:65:24:65:51 | new InputStreamReader(...) |
| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:71:26:71:30 | input |
| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:72:30:72:34 | input |
-| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:73:50:73:54 | input : InputStream |
+| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:73:28:73:55 | new InputStreamReader(...) |
| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:74:24:74:28 | input |
-| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:75:46:75:50 | input : InputStream |
-| A.java:73:50:73:54 | input : InputStream | A.java:73:28:73:55 | new InputStreamReader(...) |
-| A.java:75:46:75:50 | input : InputStream | A.java:75:24:75:51 | new InputStreamReader(...) |
+| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:75:24:75:51 | new InputStreamReader(...) |
| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:91:26:91:30 | input |
| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:92:30:92:34 | input |
-| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:93:50:93:54 | input : InputStream |
+| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) |
| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:94:24:94:28 | input |
-| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:95:46:95:50 | input : InputStream |
-| A.java:93:50:93:54 | input : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) |
-| A.java:95:46:95:50 | input : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) |
+| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) |
| B.java:7:31:7:51 | getInputStream(...) : InputStream | B.java:8:29:8:39 | inputStream |
-| B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:14:5:14:15 | inputStream : InputStream |
-| B.java:14:5:14:15 | inputStream : InputStream | B.java:14:22:14:26 | bytes [post update] : byte[] |
-| B.java:14:22:14:26 | bytes [post update] : byte[] | B.java:15:23:15:27 | bytes |
-| B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:21:5:21:15 | inputStream : InputStream |
-| B.java:21:5:21:15 | inputStream : InputStream | B.java:21:22:21:26 | bytes [post update] : byte[] |
-| B.java:21:22:21:26 | bytes [post update] : byte[] | B.java:23:29:23:29 | s |
-| B.java:27:31:27:51 | getInputStream(...) : InputStream | B.java:29:5:29:15 | inputStream : InputStream |
-| B.java:29:5:29:15 | inputStream : InputStream | B.java:29:22:29:26 | bytes [post update] : byte[] |
-| B.java:29:22:29:26 | bytes [post update] : byte[] | B.java:31:23:31:23 | s |
+| B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:15:23:15:27 | bytes |
+| B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:23:29:23:29 | s |
+| B.java:27:31:27:51 | getInputStream(...) : InputStream | B.java:31:23:31:23 | s |
| C.java:23:17:23:44 | getParameter(...) : String | C.java:24:13:24:16 | data |
| C.java:23:17:23:44 | getParameter(...) : String | C.java:25:19:25:22 | data |
| C.java:23:17:23:44 | getParameter(...) : String | C.java:26:25:26:28 | data |
@@ -69,26 +46,15 @@ edges
| C.java:84:27:84:54 | getParameter(...) : String | C.java:87:3:87:13 | burlapInput |
| C.java:84:27:84:54 | getParameter(...) : String | C.java:91:3:91:14 | burlapInput1 |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
-| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream |
-| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
nodes
| A.java:13:31:13:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
-| A.java:14:28:14:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream |
-| A.java:14:50:14:60 | inputStream : InputStream | semmle.label | inputStream : InputStream |
| A.java:15:12:15:13 | in | semmle.label | in |
| A.java:19:31:19:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
-| A.java:20:28:20:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream |
-| A.java:20:50:20:60 | inputStream : InputStream | semmle.label | inputStream : InputStream |
| A.java:21:12:21:13 | in | semmle.label | in |
| A.java:25:31:25:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
-| A.java:26:20:26:46 | new XMLDecoder(...) : XMLDecoder | semmle.label | new XMLDecoder(...) : XMLDecoder |
-| A.java:26:35:26:45 | inputStream : InputStream | semmle.label | inputStream : InputStream |
| A.java:27:12:27:12 | d | semmle.label | d |
| A.java:32:31:32:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
-| A.java:33:21:33:54 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader |
-| A.java:33:43:33:53 | inputStream : InputStream | semmle.label | inputStream : InputStream |
| A.java:34:23:34:28 | reader | semmle.label | reader |
-| A.java:39:19:39:50 | new Input(...) : Input | semmle.label | new Input(...) : Input |
| A.java:39:29:39:49 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| A.java:40:28:40:32 | input | semmle.label | input |
| A.java:41:34:41:38 | input | semmle.label | input |
@@ -97,39 +63,27 @@ nodes
| A.java:61:26:61:30 | input | semmle.label | input |
| A.java:62:30:62:34 | input | semmle.label | input |
| A.java:63:28:63:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
-| A.java:63:50:63:54 | input : InputStream | semmle.label | input : InputStream |
| A.java:64:24:64:28 | input | semmle.label | input |
| A.java:65:24:65:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
-| A.java:65:46:65:50 | input : InputStream | semmle.label | input : InputStream |
| A.java:70:25:70:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| A.java:71:26:71:30 | input | semmle.label | input |
| A.java:72:30:72:34 | input | semmle.label | input |
| A.java:73:28:73:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
-| A.java:73:50:73:54 | input : InputStream | semmle.label | input : InputStream |
| A.java:74:24:74:28 | input | semmle.label | input |
| A.java:75:24:75:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
-| A.java:75:46:75:50 | input : InputStream | semmle.label | input : InputStream |
| A.java:90:25:90:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| A.java:91:26:91:30 | input | semmle.label | input |
| A.java:92:30:92:34 | input | semmle.label | input |
| A.java:93:28:93:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
-| A.java:93:50:93:54 | input : InputStream | semmle.label | input : InputStream |
| A.java:94:24:94:28 | input | semmle.label | input |
| A.java:95:24:95:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
-| A.java:95:46:95:50 | input : InputStream | semmle.label | input : InputStream |
| B.java:7:31:7:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| B.java:8:29:8:39 | inputStream | semmle.label | inputStream |
| B.java:12:31:12:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
-| B.java:14:5:14:15 | inputStream : InputStream | semmle.label | inputStream : InputStream |
-| B.java:14:22:14:26 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
| B.java:15:23:15:27 | bytes | semmle.label | bytes |
| B.java:19:31:19:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
-| B.java:21:5:21:15 | inputStream : InputStream | semmle.label | inputStream : InputStream |
-| B.java:21:22:21:26 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
| B.java:23:29:23:29 | s | semmle.label | s |
| B.java:27:31:27:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
-| B.java:29:5:29:15 | inputStream : InputStream | semmle.label | inputStream : InputStream |
-| B.java:29:22:29:26 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
| B.java:31:23:31:23 | s | semmle.label | s |
| C.java:23:17:23:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| C.java:24:13:24:16 | data | semmle.label | data |
@@ -160,7 +114,6 @@ nodes
| C.java:91:3:91:14 | burlapInput1 | semmle.label | burlapInput1 |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | semmle.label | entityStream : InputStream |
| TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | semmle.label | new ObjectInputStream(...) |
-| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | semmle.label | entityStream : InputStream |
#select
| A.java:15:12:15:26 | readObject(...) | A.java:13:31:13:51 | getInputStream(...) : InputStream | A.java:15:12:15:13 | in | Unsafe deserialization of $@. | A.java:13:31:13:51 | getInputStream(...) | user input |
| A.java:21:12:21:28 | readUnshared(...) | A.java:19:31:19:51 | getInputStream(...) : InputStream | A.java:21:12:21:13 | in | Unsafe deserialization of $@. | A.java:19:31:19:51 | getInputStream(...) | user input |
From 363ad5b4708bbffed03f30807f1de67dd255cce8 Mon Sep 17 00:00:00 2001
From: haby0
Date: Thu, 17 Jun 2021 17:36:35 +0800
Subject: [PATCH 9/9] Fix error
---
.../CWE-502/UnsafeDeserialization.expected | 93 ++++++++++++++++---
1 file changed, 79 insertions(+), 14 deletions(-)
diff --git a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
index 6f25b28bda5..7b02131cd73 100644
--- a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
+++ b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected
@@ -1,30 +1,53 @@
edges
+| A.java:13:31:13:51 | getInputStream(...) : InputStream | A.java:14:50:14:60 | inputStream : InputStream |
| A.java:13:31:13:51 | getInputStream(...) : InputStream | A.java:15:12:15:13 | in |
+| A.java:14:28:14:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:15:12:15:13 | in |
+| A.java:14:50:14:60 | inputStream : InputStream | A.java:14:28:14:61 | new ObjectInputStream(...) : ObjectInputStream |
+| A.java:19:31:19:51 | getInputStream(...) : InputStream | A.java:20:50:20:60 | inputStream : InputStream |
| A.java:19:31:19:51 | getInputStream(...) : InputStream | A.java:21:12:21:13 | in |
-| A.java:25:31:25:51 | getInputStream(...) : InputStream | A.java:27:12:27:12 | d |
-| A.java:32:31:32:51 | getInputStream(...) : InputStream | A.java:34:23:34:28 | reader |
-| A.java:39:29:39:49 | getInputStream(...) : InputStream | A.java:40:28:40:32 | input |
-| A.java:39:29:39:49 | getInputStream(...) : InputStream | A.java:41:34:41:38 | input |
-| A.java:39:29:39:49 | getInputStream(...) : InputStream | A.java:42:40:42:44 | input |
+| A.java:20:28:20:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:21:12:21:13 | in |
+| A.java:20:50:20:60 | inputStream : InputStream | A.java:20:28:20:61 | new ObjectInputStream(...) : ObjectInputStream |
+| A.java:25:31:25:51 | getInputStream(...) : InputStream | A.java:26:35:26:45 | inputStream : InputStream |
+| A.java:26:20:26:46 | new XMLDecoder(...) : XMLDecoder | A.java:27:12:27:12 | d |
+| A.java:26:35:26:45 | inputStream : InputStream | A.java:26:20:26:46 | new XMLDecoder(...) : XMLDecoder |
+| A.java:32:31:32:51 | getInputStream(...) : InputStream | A.java:33:43:33:53 | inputStream : InputStream |
+| A.java:33:21:33:54 | new InputStreamReader(...) : InputStreamReader | A.java:34:23:34:28 | reader |
+| A.java:33:43:33:53 | inputStream : InputStream | A.java:33:21:33:54 | new InputStreamReader(...) : InputStreamReader |
+| A.java:39:19:39:50 | new Input(...) : Input | A.java:40:28:40:32 | input |
+| A.java:39:19:39:50 | new Input(...) : Input | A.java:41:34:41:38 | input |
+| A.java:39:19:39:50 | new Input(...) : Input | A.java:42:40:42:44 | input |
+| A.java:39:29:39:49 | getInputStream(...) : InputStream | A.java:39:19:39:50 | new Input(...) : Input |
| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:61:26:61:30 | input |
| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:62:30:62:34 | input |
-| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:63:28:63:55 | new InputStreamReader(...) |
+| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:63:50:63:54 | input : InputStream |
| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:64:24:64:28 | input |
-| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:65:24:65:51 | new InputStreamReader(...) |
+| A.java:60:25:60:45 | getInputStream(...) : InputStream | A.java:65:46:65:50 | input : InputStream |
+| A.java:63:50:63:54 | input : InputStream | A.java:63:28:63:55 | new InputStreamReader(...) |
+| A.java:65:46:65:50 | input : InputStream | A.java:65:24:65:51 | new InputStreamReader(...) |
| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:71:26:71:30 | input |
| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:72:30:72:34 | input |
-| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:73:28:73:55 | new InputStreamReader(...) |
+| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:73:50:73:54 | input : InputStream |
| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:74:24:74:28 | input |
-| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:75:24:75:51 | new InputStreamReader(...) |
+| A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:75:46:75:50 | input : InputStream |
+| A.java:73:50:73:54 | input : InputStream | A.java:73:28:73:55 | new InputStreamReader(...) |
+| A.java:75:46:75:50 | input : InputStream | A.java:75:24:75:51 | new InputStreamReader(...) |
| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:91:26:91:30 | input |
| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:92:30:92:34 | input |
-| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) |
+| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:93:50:93:54 | input : InputStream |
| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:94:24:94:28 | input |
-| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) |
+| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:95:46:95:50 | input : InputStream |
+| A.java:93:50:93:54 | input : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) |
+| A.java:95:46:95:50 | input : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) |
| B.java:7:31:7:51 | getInputStream(...) : InputStream | B.java:8:29:8:39 | inputStream |
-| B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:15:23:15:27 | bytes |
-| B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:23:29:23:29 | s |
-| B.java:27:31:27:51 | getInputStream(...) : InputStream | B.java:31:23:31:23 | s |
+| B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:14:5:14:15 | inputStream : InputStream |
+| B.java:14:5:14:15 | inputStream : InputStream | B.java:14:22:14:26 | bytes [post update] : byte[] |
+| B.java:14:22:14:26 | bytes [post update] : byte[] | B.java:15:23:15:27 | bytes |
+| B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:21:5:21:15 | inputStream : InputStream |
+| B.java:21:5:21:15 | inputStream : InputStream | B.java:21:22:21:26 | bytes [post update] : byte[] |
+| B.java:21:22:21:26 | bytes [post update] : byte[] | B.java:23:29:23:29 | s |
+| B.java:27:31:27:51 | getInputStream(...) : InputStream | B.java:29:5:29:15 | inputStream : InputStream |
+| B.java:29:5:29:15 | inputStream : InputStream | B.java:29:22:29:26 | bytes [post update] : byte[] |
+| B.java:29:22:29:26 | bytes [post update] : byte[] | B.java:31:23:31:23 | s |
| C.java:23:17:23:44 | getParameter(...) : String | C.java:24:13:24:16 | data |
| C.java:23:17:23:44 | getParameter(...) : String | C.java:25:19:25:22 | data |
| C.java:23:17:23:44 | getParameter(...) : String | C.java:26:25:26:28 | data |
@@ -38,23 +61,46 @@ edges
| C.java:51:17:51:44 | getParameter(...) : String | C.java:53:3:53:3 | r |
| C.java:51:17:51:44 | getParameter(...) : String | C.java:54:3:54:3 | r |
| C.java:51:17:51:44 | getParameter(...) : String | C.java:55:3:55:3 | r |
+| C.java:60:18:60:45 | getParameter(...) : String | C.java:61:55:61:59 | bytes : byte[] |
| C.java:60:18:60:45 | getParameter(...) : String | C.java:63:3:63:14 | hessianInput |
| C.java:60:18:60:45 | getParameter(...) : String | C.java:64:3:64:14 | hessianInput |
+| C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:63:3:63:14 | hessianInput |
+| C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:64:3:64:14 | hessianInput |
+| C.java:61:55:61:59 | bytes : byte[] | C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream |
+| C.java:69:18:69:45 | getParameter(...) : String | C.java:70:55:70:59 | bytes : byte[] |
| C.java:69:18:69:45 | getParameter(...) : String | C.java:72:3:72:14 | hessianInput |
| C.java:69:18:69:45 | getParameter(...) : String | C.java:73:3:73:14 | hessianInput |
+| C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:72:3:72:14 | hessianInput |
+| C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:73:3:73:14 | hessianInput |
+| C.java:70:55:70:59 | bytes : byte[] | C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream |
| C.java:79:43:79:70 | getParameter(...) : String | C.java:79:26:79:71 | new StringReader(...) |
+| C.java:84:27:84:54 | getParameter(...) : String | C.java:85:54:85:67 | serializedData : byte[] |
| C.java:84:27:84:54 | getParameter(...) : String | C.java:87:3:87:13 | burlapInput |
| C.java:84:27:84:54 | getParameter(...) : String | C.java:91:3:91:14 | burlapInput1 |
+| C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:87:3:87:13 | burlapInput |
+| C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:91:3:91:14 | burlapInput1 |
+| C.java:85:54:85:67 | serializedData : byte[] | C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
+| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream |
+| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
nodes
| A.java:13:31:13:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
+| A.java:14:28:14:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream |
+| A.java:14:50:14:60 | inputStream : InputStream | semmle.label | inputStream : InputStream |
| A.java:15:12:15:13 | in | semmle.label | in |
| A.java:19:31:19:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
+| A.java:20:28:20:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream |
+| A.java:20:50:20:60 | inputStream : InputStream | semmle.label | inputStream : InputStream |
| A.java:21:12:21:13 | in | semmle.label | in |
| A.java:25:31:25:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
+| A.java:26:20:26:46 | new XMLDecoder(...) : XMLDecoder | semmle.label | new XMLDecoder(...) : XMLDecoder |
+| A.java:26:35:26:45 | inputStream : InputStream | semmle.label | inputStream : InputStream |
| A.java:27:12:27:12 | d | semmle.label | d |
| A.java:32:31:32:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
+| A.java:33:21:33:54 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader |
+| A.java:33:43:33:53 | inputStream : InputStream | semmle.label | inputStream : InputStream |
| A.java:34:23:34:28 | reader | semmle.label | reader |
+| A.java:39:19:39:50 | new Input(...) : Input | semmle.label | new Input(...) : Input |
| A.java:39:29:39:49 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| A.java:40:28:40:32 | input | semmle.label | input |
| A.java:41:34:41:38 | input | semmle.label | input |
@@ -63,27 +109,39 @@ nodes
| A.java:61:26:61:30 | input | semmle.label | input |
| A.java:62:30:62:34 | input | semmle.label | input |
| A.java:63:28:63:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
+| A.java:63:50:63:54 | input : InputStream | semmle.label | input : InputStream |
| A.java:64:24:64:28 | input | semmle.label | input |
| A.java:65:24:65:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
+| A.java:65:46:65:50 | input : InputStream | semmle.label | input : InputStream |
| A.java:70:25:70:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| A.java:71:26:71:30 | input | semmle.label | input |
| A.java:72:30:72:34 | input | semmle.label | input |
| A.java:73:28:73:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
+| A.java:73:50:73:54 | input : InputStream | semmle.label | input : InputStream |
| A.java:74:24:74:28 | input | semmle.label | input |
| A.java:75:24:75:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
+| A.java:75:46:75:50 | input : InputStream | semmle.label | input : InputStream |
| A.java:90:25:90:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| A.java:91:26:91:30 | input | semmle.label | input |
| A.java:92:30:92:34 | input | semmle.label | input |
| A.java:93:28:93:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
+| A.java:93:50:93:54 | input : InputStream | semmle.label | input : InputStream |
| A.java:94:24:94:28 | input | semmle.label | input |
| A.java:95:24:95:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) |
+| A.java:95:46:95:50 | input : InputStream | semmle.label | input : InputStream |
| B.java:7:31:7:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| B.java:8:29:8:39 | inputStream | semmle.label | inputStream |
| B.java:12:31:12:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
+| B.java:14:5:14:15 | inputStream : InputStream | semmle.label | inputStream : InputStream |
+| B.java:14:22:14:26 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
| B.java:15:23:15:27 | bytes | semmle.label | bytes |
| B.java:19:31:19:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
+| B.java:21:5:21:15 | inputStream : InputStream | semmle.label | inputStream : InputStream |
+| B.java:21:22:21:26 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
| B.java:23:29:23:29 | s | semmle.label | s |
| B.java:27:31:27:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
+| B.java:29:5:29:15 | inputStream : InputStream | semmle.label | inputStream : InputStream |
+| B.java:29:22:29:26 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
| B.java:31:23:31:23 | s | semmle.label | s |
| C.java:23:17:23:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| C.java:24:13:24:16 | data | semmle.label | data |
@@ -102,18 +160,25 @@ nodes
| C.java:54:3:54:3 | r | semmle.label | r |
| C.java:55:3:55:3 | r | semmle.label | r |
| C.java:60:18:60:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | semmle.label | new ByteArrayInputStream(...) : ByteArrayInputStream |
+| C.java:61:55:61:59 | bytes : byte[] | semmle.label | bytes : byte[] |
| C.java:63:3:63:14 | hessianInput | semmle.label | hessianInput |
| C.java:64:3:64:14 | hessianInput | semmle.label | hessianInput |
| C.java:69:18:69:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | semmle.label | new ByteArrayInputStream(...) : ByteArrayInputStream |
+| C.java:70:55:70:59 | bytes : byte[] | semmle.label | bytes : byte[] |
| C.java:72:3:72:14 | hessianInput | semmle.label | hessianInput |
| C.java:73:3:73:14 | hessianInput | semmle.label | hessianInput |
| C.java:79:26:79:71 | new StringReader(...) | semmle.label | new StringReader(...) |
| C.java:79:43:79:70 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| C.java:84:27:84:54 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | semmle.label | new ByteArrayInputStream(...) : ByteArrayInputStream |
+| C.java:85:54:85:67 | serializedData : byte[] | semmle.label | serializedData : byte[] |
| C.java:87:3:87:13 | burlapInput | semmle.label | burlapInput |
| C.java:91:3:91:14 | burlapInput1 | semmle.label | burlapInput1 |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | semmle.label | entityStream : InputStream |
| TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | semmle.label | new ObjectInputStream(...) |
+| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | semmle.label | entityStream : InputStream |
#select
| A.java:15:12:15:26 | readObject(...) | A.java:13:31:13:51 | getInputStream(...) : InputStream | A.java:15:12:15:13 | in | Unsafe deserialization of $@. | A.java:13:31:13:51 | getInputStream(...) | user input |
| A.java:21:12:21:28 | readUnshared(...) | A.java:19:31:19:51 | getInputStream(...) : InputStream | A.java:21:12:21:13 | in | Unsafe deserialization of $@. | A.java:19:31:19:51 | getInputStream(...) | user input |