mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
Merge pull request #6456 from smowton/smowton/admin/flexjson-unsafe-deserialization
Java: add unsafe-deserialization support for Flexjson
This commit is contained in:
@@ -81,6 +81,7 @@ private module Frameworks {
|
||||
private import semmle.code.java.frameworks.ApacheHttp
|
||||
private import semmle.code.java.frameworks.apache.Collections
|
||||
private import semmle.code.java.frameworks.apache.Lang
|
||||
private import semmle.code.java.frameworks.Flexjson
|
||||
private import semmle.code.java.frameworks.guava.Guava
|
||||
private import semmle.code.java.frameworks.jackson.JacksonSerializability
|
||||
private import semmle.code.java.frameworks.JavaxJson
|
||||
|
||||
41
java/ql/lib/semmle/code/java/frameworks/Flexjson.qll
Normal file
41
java/ql/lib/semmle/code/java/frameworks/Flexjson.qll
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Provides classes for working with the Flexjson framework.
|
||||
*/
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/** The class `flexjson.JSONDeserializer`. */
|
||||
class FlexjsonDeserializer extends RefType {
|
||||
FlexjsonDeserializer() { this.hasQualifiedName("flexjson", "JSONDeserializer") }
|
||||
}
|
||||
|
||||
/** The class `flexjson.ObjectFactory`. */
|
||||
class FlexjsonObjectFactory extends RefType {
|
||||
FlexjsonObjectFactory() { this.hasQualifiedName("flexjson", "ObjectFactory") }
|
||||
}
|
||||
|
||||
/** The deserialization method `deserialize`. */
|
||||
class FlexjsonDeserializeMethod extends Method {
|
||||
FlexjsonDeserializeMethod() {
|
||||
this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof
|
||||
FlexjsonDeserializer and
|
||||
this.getName() = "deserialize" and
|
||||
not this.getAParameter().getType() instanceof FlexjsonObjectFactory // deserialization method with specified class types in object factory is unlikely to be vulnerable
|
||||
}
|
||||
}
|
||||
|
||||
/** The method `use` to configure allowed class type. */
|
||||
class FlexjsonDeserializerUseMethod extends Method {
|
||||
FlexjsonDeserializerUseMethod() {
|
||||
this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof
|
||||
FlexjsonDeserializer and
|
||||
this.hasName("use")
|
||||
}
|
||||
}
|
||||
|
||||
private class FluentUseMethodModel extends SummaryModelCsv {
|
||||
override predicate row(string r) {
|
||||
r = "flexjson;JSONDeserializer;true;use;;;Argument[-1];ReturnValue;value"
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ private import semmle.code.java.frameworks.Castor
|
||||
private import semmle.code.java.frameworks.Jackson
|
||||
private import semmle.code.java.frameworks.Jabsorb
|
||||
private import semmle.code.java.frameworks.JoddJson
|
||||
private import semmle.code.java.frameworks.Flexjson
|
||||
private import semmle.code.java.frameworks.apache.Lang
|
||||
private import semmle.code.java.Reflection
|
||||
|
||||
@@ -203,6 +204,9 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
|
||||
// jodd.json.JsonParser may be configured for unrestricted deserialization to user-specified types
|
||||
joddJsonParserConfiguredUnsafely(ma.getQualifier())
|
||||
)
|
||||
or
|
||||
m instanceof FlexjsonDeserializeMethod and
|
||||
sink = ma.getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -270,9 +274,48 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
|
||||
not ma.getArgument(1).getType().getName() = ["Class<Object>", "Class<?>"] and
|
||||
node.asExpr() = ma.getAnArgument()
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
// Sanitize the input to flexjson.JSONDeserializer.deserialize whenever it appears
|
||||
// to be called with an explicit class argument limiting those types that can
|
||||
// be instantiated during deserialization, or if the deserializer has already been
|
||||
// configured to use a specified root class.
|
||||
ma.getMethod() instanceof FlexjsonDeserializeMethod and
|
||||
node.asExpr() = ma.getAnArgument() and
|
||||
(
|
||||
ma.getArgument(1).getType() instanceof TypeClass and
|
||||
not ma.getArgument(1) instanceof NullLiteral and
|
||||
not ma.getArgument(1).getType().getName() = ["Class<Object>", "Class<?>"]
|
||||
or
|
||||
isSafeFlexjsonDeserializer(ma.getQualifier())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a safe usage of the `use` method of Flexjson, which could be:
|
||||
* use(String, ...) where the path is null or
|
||||
* use(ObjectFactory, String...) where the string varargs (or array) contains null
|
||||
*/
|
||||
MethodAccess getASafeFlexjsonUseCall() {
|
||||
result.getMethod() instanceof FlexjsonDeserializerUseMethod and
|
||||
(
|
||||
result.getMethod().getParameterType(0) instanceof TypeString and
|
||||
result.getArgument(0) instanceof NullLiteral
|
||||
or
|
||||
result.getMethod().getParameterType(0) instanceof FlexjsonObjectFactory and
|
||||
exists(NullLiteral e | e = result.getAnArgument())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is a safely configured Flexjson `JSONDeserializer`.
|
||||
*/
|
||||
predicate isSafeFlexjsonDeserializer(Expr e) {
|
||||
DataFlow::localExprFlow(getASafeFlexjsonUseCall().getQualifier(), e)
|
||||
}
|
||||
|
||||
/** Holds if `fromNode` to `toNode` is a dataflow step that resolves a class. */
|
||||
predicate resolveClassStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
||||
exists(ReflectiveClassIdentifierMethodAccess ma |
|
||||
|
||||
Reference in New Issue
Block a user