Revert "Java: Convert other sinks"

This reverts commit 87d42b02c0.
This commit is contained in:
Tamas Vajk
2021-04-09 13:13:49 +02:00
parent 87d42b02c0
commit 351f35d9bc
17 changed files with 354 additions and 302 deletions

View File

@@ -16,7 +16,6 @@ import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.XSS
private import semmle.code.java.dataflow.ExternalFlow
/**
* One of the `printStackTrace()` overloads on `Throwable`.
@@ -38,12 +37,10 @@ class ServletWriterSourceToPrintStackTraceMethodFlowConfig extends TaintTracking
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ServletWriterSource }
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "print-stack-trace") }
}
private class PrintStackTraceSinkModel extends SinkModelCsv {
override predicate row(string row) {
row = ["java.lang;Throwable;true;printStackTrace;;;Argument;print-stack-trace"]
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getAnArgument() and ma.getMethod() instanceof PrintStackTraceMethod
)
}
}

View File

@@ -15,7 +15,6 @@ import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.ExternalFlow
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
class URLConstructor extends ClassInstanceExpr {
URLConstructor() { this.getConstructor().getDeclaringType() instanceof TypeUrl }
@@ -40,7 +39,13 @@ class RemoteURLToOpenStreamFlowConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "url-open-stream") }
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess m |
sink.asExpr() = m.getQualifier() and m.getMethod() instanceof URLOpenStreamMethod
)
or
sinkNode(sink, "url-open-stream")
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(URLConstructor u |
@@ -50,12 +55,6 @@ class RemoteURLToOpenStreamFlowConfig extends TaintTracking::Configuration {
}
}
private class URLOpenStreamSinkModel extends SinkModelCsv {
override predicate row(string row) {
row = ["java.net;URL;false;openStream;;;Argument[-1];url-open-stream"]
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess call
where
sink.getNode().asExpr() = call.getQualifier() and

View File

@@ -2,7 +2,6 @@ import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.XmlParsers
import DataFlow
private import semmle.code.java.dataflow.ExternalFlow
/**
* A taint-tracking configuration for unvalidated user input that is used in XSLT transformation.
@@ -104,20 +103,15 @@ class TypeXsltPackage extends Class {
/** A data flow sink for unvalidated user input that is used in XSLT transformation. */
class XsltInjectionSink extends DataFlow::ExprNode {
XsltInjectionSink() { sinkNode(this, "xslt") }
}
private class XsltInjectionSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"net.sf.saxon.s9api;XsltTransformer;false;transform;;;Argument[-1];xslt",
"net.sf.saxon.s9api;Xslt30Transformer;false;transform;;;Argument[-1];xslt",
"net.sf.saxon.s9api;Xslt30Transformer;false;applyTemplates;;;Argument[-1];xslt",
"net.sf.saxon.s9api;Xslt30Transformer;false;callFunction;;;Argument[-1];xslt",
"net.sf.saxon.s9api;Xslt30Transformer;false;callTemplate;;;Argument[-1];xslt",
"javax.xml.transform;Transformer;false;transform;;;Argument[-1];xslt"
]
XsltInjectionSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() and ma.getQualifier() = this.getExpr() |
ma instanceof TransformerTransform or
m instanceof XsltTransformerTransformMethod or
m instanceof Xslt30TransformerTransformMethod or
m instanceof Xslt30TransformerApplyTemplatesMethod or
m instanceof Xslt30TransformerCallFunctionMethod or
m instanceof Xslt30TransformerCallTemplateMethod
)
}
}
@@ -192,21 +186,16 @@ private class TransformerFactoryWithSecureProcessingFeatureFlowConfig extends Da
)
}
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "xslt-transformer") }
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and
ma.getMethod().getDeclaringType() instanceof TransformerFactory
)
}
override int fieldFlowBranchLimit() { result = 0 }
}
private class TransformerFactorySinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"javax.xml.transform;TransformerFactory;false;;;;Argument[-1];xslt-transformer",
"javax.xml.transform.sax;SAXTransformerFactory;false;;;;Argument[-1];xslt-transformer"
]
}
}
/** A `ParserConfig` specific to `TransformerFactory`. */
private class TransformerFactoryFeatureConfig extends ParserConfig {
TransformerFactoryFeatureConfig() {

View File

@@ -1,7 +1,6 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.ExternalFlow
/**
* A taint-tracking configuration for unsafe user input
@@ -22,7 +21,7 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
}
/**
* A sink for Expression Language injection vulnerabilities via Jexl,
* A sink for Expresssion Language injection vulnerabilities via Jexl,
* i.e. method calls that run evaluation of a JEXL expression.
*
* Creating a `Callable` from a tainted JEXL expression or script is considered as a sink
@@ -31,41 +30,18 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
* maybe stored in an object field and then reached by a different flow.
*/
private class JexlEvaluationSink extends DataFlow::ExprNode {
JexlEvaluationSink() { sinkNode(this, "jexl") }
}
private class JexlEvaluationSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
// Direct JEXL evaluation
"org.apache.commons.jexl2;Expression;false;evaluate;;;Argument[-1];jexl",
"org.apache.commons.jexl3;JexlExpression;false;evaluate;;;Argument[-1];jexl",
"org.apache.commons.jexl2;Script;false;execute;;;Argument[-1];jexl",
"org.apache.commons.jexl3;JexlScript;false;execute;;;Argument[-1];jexl",
"org.apache.commons.jexl2;JxltEngine$Expression;false;evaluate;;;Argument[-1];jexl",
"org.apache.commons.jexl3;JxltEngine$Expression;false;evaluate;;;Argument[-1];jexl",
"org.apache.commons.jexl2;JxltEngine$Expression;false;prepare;;;Argument[-1];jexl",
"org.apache.commons.jexl3;JxltEngine$Expression;false;prepare;;;Argument[-1];jexl",
"org.apache.commons.jexl2;JxltEngine$Template;false;evaluate;;;Argument[-1];jexl",
"org.apache.commons.jexl3;JxltEngine$Template;false;evaluate;;;Argument[-1];jexl",
"org.apache.commons.jexl2;UnifiedJEXL$Expression;false;evaluate;;;Argument[-1];jexl",
"org.apache.commons.jexl3;UnifiedJEXL$Expression;false;evaluate;;;Argument[-1];jexl",
"org.apache.commons.jexl2;UnifiedJEXL$Expression;false;prepare;;;Argument[-1];jexl",
"org.apache.commons.jexl3;UnifiedJEXL$Expression;false;prepare;;;Argument[-1];jexl",
"org.apache.commons.jexl2;UnifiedJEXL$Template;false;evaluate;;;Argument[-1];jexl",
"org.apache.commons.jexl3;UnifiedJEXL$Template;false;evaluate;;;Argument[-1];jexl",
// JEXL callable
"org.apache.commons.jexl2;Expression;false;callable;;;Argument[-1];jexl",
"org.apache.commons.jexl3;JexlExpression;false;callable;;;Argument[-1];jexl",
"org.apache.commons.jexl2;Script;false;callable;;;Argument[-1];jexl",
"org.apache.commons.jexl3;JexlScript;false;callable;;;Argument[-1];jexl",
// Methods in the `JexlEngine` class that gets or sets a property with a JEXL expression.
"org.apache.commons.jexl2;JexlEngine;false;getProperty;;;Argument[1..2];jexl",
"org.apache.commons.jexl3;JexlEngine;false;getProperty;;;Argument[1..2];jexl",
"org.apache.commons.jexl2;JexlEngine;false;setProperty;;;Argument[1];jexl",
"org.apache.commons.jexl3;JexlEngine;false;setProperty;;;Argument[1];jexl"
]
JexlEvaluationSink() {
exists(MethodAccess ma, Method m, Expr taintFrom |
ma.getMethod() = m and taintFrom = this.asExpr()
|
m instanceof DirectJexlEvaluationMethod and ma.getQualifier() = taintFrom
or
m instanceof CreateJexlCallableMethod and ma.getQualifier() = taintFrom
or
m instanceof JexlEngineGetSetPropertyMethod and
taintFrom.getType() instanceof TypeString and
ma.getAnArgument() = taintFrom
)
}
}
@@ -122,36 +98,22 @@ private class SandboxedJexlFlowConfig extends DataFlow2::Configuration {
override predicate isSource(DataFlow::Node node) { node instanceof SandboxedJexlSource }
override predicate isSink(DataFlow::Node node) { sinkNode(node, "sandboxed-jexl") }
override predicate isSink(DataFlow::Node node) {
exists(MethodAccess ma, Method m | ma.getMethod() = m |
(
m instanceof CreateJexlScriptMethod or
m instanceof CreateJexlExpressionMethod or
m instanceof CreateJexlTemplateMethod
) and
ma.getQualifier() = node.asExpr()
)
}
override predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
createsJexlEngine(fromNode, toNode)
}
}
private class SandboxedJexlEvaluationSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
// CreateJexlScriptMethod
"org.apache.commons.jexl2;JexlEngine;false;createScript;;;Argument[-1];sandboxed-jexl",
"org.apache.commons.jexl3;JexlEngine;false;createScript;;;Argument[-1];sandboxed-jexl",
// CreateJexlExpressionMethod
"org.apache.commons.jexl2;UnifiedJEXL;false;parse;;;Argument[-1];sandboxed-jexl",
"org.apache.commons.jexl3;UnifiedJEXL;false;parse;;;Argument[-1];sandboxed-jexl",
"org.apache.commons.jexl2;JxltEngine;false;createExpression;;;Argument[-1];sandboxed-jexl",
"org.apache.commons.jexl3;JxltEngine;false;createExpression;;;Argument[-1];sandboxed-jexl",
"org.apache.commons.jexl2;JexlEngine;false;createExpression;;;Argument[-1];sandboxed-jexl",
"org.apache.commons.jexl3;JexlEngine;false;createExpression;;;Argument[-1];sandboxed-jexl",
// CreateJexlTemplateMethod
"org.apache.commons.jexl2;JxltEngine;false;createTemplate;;;Argument[-1];sandboxed-jexl",
"org.apache.commons.jexl3;JxltEngine;false;createTemplate;;;Argument[-1];sandboxed-jexl",
"org.apache.commons.jexl2;UnifiedJEXL;false;createTemplate;;;Argument[-1];sandboxed-jexl",
"org.apache.commons.jexl3;UnifiedJEXL;false;createTemplate;;;Argument[-1];sandboxed-jexl"
]
}
}
/**
* Defines a data flow source for JEXL engines configured with a sandbox.
*/
@@ -202,6 +164,35 @@ private predicate returnsDataFromBean(DataFlow::Node fromNode, DataFlow::Node to
)
}
/**
* A methods in the `JexlEngine` class that gets or sets a property with a JEXL expression.
*/
private class JexlEngineGetSetPropertyMethod extends Method {
JexlEngineGetSetPropertyMethod() {
getDeclaringType() instanceof JexlEngine and
hasName(["getProperty", "setProperty"])
}
}
/**
* A method that triggers direct evaluation of JEXL expressions.
*/
private class DirectJexlEvaluationMethod extends Method {
DirectJexlEvaluationMethod() {
getDeclaringType() instanceof JexlExpression and hasName("evaluate")
or
getDeclaringType() instanceof JexlScript and hasName("execute")
or
getDeclaringType() instanceof JxltEngineExpression and hasName(["evaluate", "prepare"])
or
getDeclaringType() instanceof JxltEngineTemplate and hasName("evaluate")
or
getDeclaringType() instanceof UnifiedJexlExpression and hasName(["evaluate", "prepare"])
or
getDeclaringType() instanceof UnifiedJexlTemplate and hasName("evaluate")
}
}
/**
* A method that creates a JEXL script.
*/
@@ -209,6 +200,16 @@ private class CreateJexlScriptMethod extends Method {
CreateJexlScriptMethod() { getDeclaringType() instanceof JexlEngine and hasName("createScript") }
}
/**
* A method that creates a `Callable` for a JEXL expression or script.
*/
private class CreateJexlCallableMethod extends Method {
CreateJexlCallableMethod() {
(getDeclaringType() instanceof JexlExpression or getDeclaringType() instanceof JexlScript) and
hasName("callable")
}
}
/**
* A method that creates a JEXL template.
*/
@@ -266,6 +267,22 @@ private class JexlUberspect extends Interface {
}
}
private class JxltEngineExpression extends NestedType {
JxltEngineExpression() { getEnclosingType() instanceof JxltEngine and hasName("Expression") }
}
private class JxltEngineTemplate extends NestedType {
JxltEngineTemplate() { getEnclosingType() instanceof JxltEngine and hasName("Template") }
}
private class UnifiedJexlExpression extends NestedType {
UnifiedJexlExpression() { getEnclosingType() instanceof UnifiedJexl and hasName("Expression") }
}
private class UnifiedJexlTemplate extends NestedType {
UnifiedJexlTemplate() { getEnclosingType() instanceof UnifiedJexl and hasName("Template") }
}
private class Reader extends RefType {
Reader() { hasQualifiedName("java.io", "Reader") }
}

View File

@@ -1,7 +1,6 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.ExternalFlow
/**
* A taint-tracking configuration for unsafe user input
@@ -31,31 +30,36 @@ class MvelInjectionConfig extends TaintTracking::Configuration {
* i.e. methods that run evaluation of a MVEL expression.
*/
class MvelEvaluationSink extends DataFlow::ExprNode {
MvelEvaluationSink() { sinkNode(this, "mvel") }
}
private class MvelEvaluationSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"org.mvel2.jsr223;MvelScriptEngine;false;evaluate;;;Argument[0];mvel",
"org.mvel2.jsr223;MvelScriptEngine;false;eval;;;Argument[0];mvel",
"org.mvel2.compiler;ExecutableStatement;false;getValue;;;Argument[-1];mvel",
"org.mvel2.compiler;CompiledExpression;false;getDirectValue;;;Argument[-1];mvel",
"org.mvel2.compiler;CompiledAccExpression;false;getValue;;;Argument[-1];mvel",
"org.mvel2.compiler;Accessor;false;getValue;;;Argument[-1];mvel",
"javax.script;CompiledScript;false;eval;;;Argument[-1];mvel",
"org.mvel2.jsr223;MvelCompiledScript;false;eval;;;Argument[-1];mvel",
"org.mvel2;MVEL;false;eval;;;Argument[0];mvel",
"org.mvel2;MVEL;false;executeExpression;;;Argument[0];mvel",
"org.mvel2;MVEL;false;evalToBoolean;;;Argument[0];mvel",
"org.mvel2;MVEL;false;evalToString;;;Argument[0];mvel",
"org.mvel2;MVEL;false;executeAllExpression;;;Argument[0];mvel",
"org.mvel2;MVEL;false;executeSetExpression;;;Argument[0];mvel",
"org.mvel2.templates;TemplateRuntime;false;eval;;;Argument[0];mvel",
"org.mvel2.templates;TemplateRuntime;false;execute;;;Argument[0];mvel",
"org.mvel2;MVELRuntime;false;execute;;;Argument[1];mvel"
]
MvelEvaluationSink() {
exists(StaticMethodAccess ma, Method m | m = ma.getMethod() |
(
m instanceof MvelEvalMethod or
m instanceof TemplateRuntimeEvaluationMethod
) and
ma.getArgument(0) = asExpr()
)
or
exists(MethodAccess ma, Method m | m = ma.getMethod() |
m instanceof MvelScriptEngineEvaluationMethod and
ma.getArgument(0) = asExpr()
)
or
exists(MethodAccess ma, Method m | m = ma.getMethod() |
(
m instanceof ExecutableStatementEvaluationMethod or
m instanceof CompiledExpressionEvaluationMethod or
m instanceof CompiledAccExpressionEvaluationMethod or
m instanceof AccessorEvaluationMethod or
m instanceof CompiledScriptEvaluationMethod or
m instanceof MvelCompiledScriptEvaluationMethod
) and
ma.getQualifier() = asExpr()
)
or
exists(StaticMethodAccess ma, Method m | m = ma.getMethod() |
m instanceof MvelRuntimeEvaluationMethod and
ma.getArgument(1) = asExpr()
)
}
}

View File

@@ -12,7 +12,6 @@
import java
import semmle.code.java.security.Encryption
import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.ExternalFlow
/** The Java class `java.security.spec.ECGenParameterSpec`. */
class ECGenParameterSpec extends RefType {
@@ -56,12 +55,11 @@ class KeyGeneratorInitConfiguration extends TaintTracking::Configuration {
exists(JavaxCryptoKeyGenerator jcg | jcg = source.asExpr())
}
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "keygen") }
}
private class KeyGeneratorInitSinkModel extends SinkModelCsv {
override predicate row(string row) {
row = ["javax.crypto;KeyGenerator;false;init;;;Argument[-1];keygen"]
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod() instanceof KeyGeneratorInitMethod and
sink.asExpr() = ma.getQualifier()
)
}
}
@@ -73,12 +71,11 @@ class KeyPairGeneratorInitConfiguration extends TaintTracking::Configuration {
exists(JavaSecurityKeyPairGenerator jkg | jkg = source.asExpr())
}
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "keypairgen") }
}
private class KeyPairGeneratorInitSinkModel extends SinkModelCsv {
override predicate row(string row) {
row = ["java.security;KeyPairGenerator;false;initialize;;;Argument[-1];keypairgen"]
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
sink.asExpr() = ma.getQualifier()
)
}
}

View File

@@ -3,7 +3,6 @@ import semmle.code.java.security.Encryption
import semmle.code.java.dataflow.TaintTracking
import DataFlow
import PathGraph
private import semmle.code.java.dataflow.ExternalFlow
/**
* A taint-tracking configuration for unsafe SSL and TLS versions.
@@ -13,20 +12,11 @@ class UnsafeTlsVersionConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof UnsafeTlsVersion }
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "ssl") }
}
private class UnsafeTlsVersionSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"javax.net.ssl;SSLContext;false;getInstance;;;Argument[0];ssl",
"javax.net.ssl;SSLParameters;false;SSLParameters;;;Argument[1];ssl",
"javax.net.ssl;SSLParameters;false;setProtocols;;;Argument[0];ssl",
"javax.net.ssl;SSLSocket;false;setEnabledProtocols;;;Argument[0];ssl",
"javax.net.ssl;SSLServerSocket;false;setEnabledProtocols;;;Argument[0];ssl",
"javax.net.ssl;SSLEngine;false;setEnabledProtocols;;;Argument[0];ssl"
]
override predicate isSink(DataFlow::Node sink) {
sink instanceof SslContextGetInstanceSink or
sink instanceof CreateSslParametersSink or
sink instanceof SslParametersSetProtocolsSink or
sink instanceof SetEnabledProtocolsSink
}
}

View File

@@ -15,7 +15,6 @@ import semmle.code.java.frameworks.Servlets
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.TaintTracking2
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
/**
* Holds if `header` sets `Access-Control-Allow-Credentials` to `true`. This ensures fair chances of exploitability.
@@ -30,29 +29,33 @@ private predicate setsAllowCredentials(MethodAccess header) {
header.getArgument(1).(CompileTimeConstantExpr).getStringValue().toLowerCase() = "true"
}
private class CorsProbableCheckAccess extends MethodAccess {
CorsProbableCheckAccess() {
getMethod().hasName("contains") and
getMethod().getDeclaringType().getASourceSupertype*() instanceof CollectionType
or
getMethod().hasName("containsKey") and
getMethod().getDeclaringType().getASourceSupertype*() instanceof MapType
or
getMethod().hasName("equals") and
getQualifier().getType() instanceof TypeString
}
}
private Expr getAccessControlAllowOriginHeaderName() {
result.(CompileTimeConstantExpr).getStringValue().toLowerCase() = "access-control-allow-origin"
}
/**
* This taintflow2 configuration checks if there is a flow from source node towards probably CORS checking methods.
* This taintflow2 configuration checks if there is a flow from source node towards CorsProbableCheckAccess methods.
*/
class CorsSourceReachesCheckConfig extends TaintTracking2::Configuration {
CorsSourceReachesCheckConfig() { this = "CorsOriginConfig" }
override predicate isSource(DataFlow::Node source) { any(CorsOriginConfig c).hasFlow(source, _) }
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "cors") }
}
private class CorsProbableCheckAccessSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"java.util;Collection;true;contains;;;Argument;cors",
"java.util;Map;true;containsKey;;;Argument;cors",
"java.lang;String;true;equals;;;Argument;cors"
]
override predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(CorsProbableCheckAccess check).getAnArgument()
}
}

View File

@@ -16,7 +16,6 @@ import semmle.code.java.frameworks.Jndi
import semmle.code.java.frameworks.Networking
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
/**
* Insecure (non-SSL, non-private) LDAP URL string literal.
@@ -146,7 +145,12 @@ class InsecureUrlFlowConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof InsecureLdapUrl }
/** Sink of directory context creation. */
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "ldap") }
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc |
cc.getConstructedType().getASupertype*() instanceof TypeDirContext and
sink.asExpr() = cc.getArgument(0)
)
}
/** Method call of `env.put()`. */
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
@@ -172,12 +176,11 @@ class BasicAuthFlowConfig extends DataFlow::Configuration {
}
/** Sink of directory context creation. */
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "ldap") }
}
private class LdapSinkModel extends SinkModelCsv {
override predicate row(string row) {
row = ["javax.naming.directory;DirContext;true;.ctor;;;Argument[0];ldap"]
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc |
cc.getConstructedType().getASupertype*() instanceof TypeDirContext and
sink.asExpr() = cc.getArgument(0)
)
}
}
@@ -195,7 +198,12 @@ class SSLFlowConfig extends DataFlow::Configuration {
}
/** Sink of directory context creation. */
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "ldap") }
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc |
cc.getConstructedType().getASupertype*() instanceof TypeDirContext and
sink.asExpr() = cc.getArgument(0)
)
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, InsecureUrlFlowConfig config

View File

@@ -15,7 +15,6 @@ import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.XmlParsers
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
class XPathInjectionConfiguration extends TaintTracking::Configuration {
XPathInjectionConfiguration() { this = "XPathInjection" }
@@ -26,18 +25,16 @@ class XPathInjectionConfiguration extends TaintTracking::Configuration {
}
class XPathInjectionSink extends DataFlow::ExprNode {
XPathInjectionSink() { sinkNode(this, "xpath") }
}
private class XPathInjectionSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"javax.xml.xpath;XPath;false;compile;;;Argument[0];xpath",
"javax.xml.xpath;XPath;false;evaluate;;;Argument[0];xpath",
"org.dom4j;Node;false;selectNodes;;;Argument[0];xpath",
"org.dom4j;Node;false;selectSingleNode;;;Argument[0];xpath"
]
XPathInjectionSink() {
exists(Method m, MethodAccess ma | ma.getMethod() = m |
m.getDeclaringType().hasQualifiedName("javax.xml.xpath", "XPath") and
(m.hasName("evaluate") or m.hasName("compile")) and
ma.getArgument(0) = this.getExpr()
or
m.getDeclaringType().hasQualifiedName("org.dom4j", "Node") and
(m.hasName("selectNodes") or m.hasName("selectSingleNode")) and
ma.getArgument(0) = this.getExpr()
)
}
}

View File

@@ -14,7 +14,6 @@ import java
import semmle.code.java.dataflow.FlowSources
import XQueryInjectionLib
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
/**
* A taint-tracking configuration tracing flow from remote sources, through an XQuery parser, to its eventual execution.
@@ -24,7 +23,11 @@ class XQueryInjectionConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "xquery") }
override predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(XQueryPreparedExecuteCall xpec).getPreparedExpression() or
sink.asExpr() = any(XQueryExecuteCall xec).getExecuteQueryArgument() or
sink.asExpr() = any(XQueryExecuteCommandCall xecc).getExecuteCommandArgument()
}
/**
* Holds if taint from the input `pred` to a `prepareExpression` call flows to the returned prepared expression `succ`.

View File

@@ -1,5 +1,4 @@
import java
private import semmle.code.java.dataflow.ExternalFlow
/** A call to `XQConnection.prepareExpression`. */
class XQueryParserCall extends MethodAccess {
@@ -67,14 +66,3 @@ class XQueryExecuteCommandCall extends MethodAccess {
/** Return this execute command argument. */
Expr getExecuteCommandArgument() { result = this.getArgument(0) }
}
private class XQuerySinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"javax.xml.xquery;XQPreparedExpression;true;executeQuery;;;Argument[-1];xquery",
"javax.xml.xquery;XQExpression;true;executeQuery;;;Argument[0];xquery",
"javax.xml.xquery;XQExpression;true;executeCommand;;;Argument[0];xquery"
]
}
}

View File

@@ -2,7 +2,6 @@ import java
import semmle.code.java.dataflow.FlowSources
import DataFlow
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
/**
* A taint-tracking configuration for unvalidated user input that is used in OGNL EL evaluation.
@@ -83,25 +82,12 @@ predicate ognlInjectionSinkMethod(Method m, int index) {
/** A data flow sink for unvalidated user input that is used in OGNL EL evaluation. */
class OgnlInjectionSink extends DataFlow::ExprNode {
OgnlInjectionSink() { sinkNode(this, "ognl") }
}
private class OgnlInjectionSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"org.apache.commons.ognl;Ognl;false;setValue;;;Argument[-1..0];ognl",
"org.apache.commons.ognl;Ognl;false;getValue;;;Argument[-1..0];ognl",
"ognl;Ognl;false;setValue;;;Argument[-1..0];ognl",
"ognl;Ognl;false;getValue;;;Argument[-1..0];ognl",
"org.apache.commons.ognl;Node;true;setValue;;;Argument[-1..0];ognl",
"org.apache.commons.ognl;Node;true;getValue;;;Argument[-1..0];ognl",
"ognl;Node;true;setValue;;;Argument[-1..0];ognl",
"ognl;Node;true;getValue;;;Argument[-1..0];ognl",
"com.opensymphony.xwork2.ognl;OgnlUtil;false;setValue;;;Argument[-1..0];ognl",
"com.opensymphony.xwork2.ognl;OgnlUtil;false;getValue;;;Argument[-1..0];ognl",
"com.opensymphony.xwork2.ognl;OgnlUtil;false;callMethod;;;Argument[-1..0];ognl"
]
OgnlInjectionSink() {
exists(MethodAccess ma, Method m, int index |
ma.getMethod() = m and
(ma.getArgument(index) = this.getExpr() or ma.getQualifier() = this.getExpr()) and
ognlInjectionSinkMethod(m, index)
)
}
}

View File

@@ -14,16 +14,13 @@ import java
import semmle.code.java.dataflow.FlowSources
import RequestForgery
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
class RequestForgeryConfiguration extends TaintTracking::Configuration {
RequestForgeryConfiguration() { this = "Server Side Request Forgery" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
sink instanceof RequestForgerySink or sinkNode(sink, "request-forgery-sink")
}
override predicate isSink(DataFlow::Node sink) { sink instanceof RequestForgerySink }
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
requestForgeryStep(pred, succ)

View File

@@ -5,7 +5,6 @@ import semmle.code.java.frameworks.spring.Spring
import semmle.code.java.frameworks.JaxWS
import semmle.code.java.frameworks.javase.Http
import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.ExternalFlow
predicate requestForgeryStep(DataFlow::Node pred, DataFlow::Node succ) {
// propagate to a URI when its host is assigned to
@@ -39,42 +38,119 @@ predicate requestForgeryStep(DataFlow::Node pred, DataFlow::Node succ) {
)
}
private class RequestForgerySinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"java.net;URL;false;openConnection;;;Argument[-1];request-forgery-sink",
"java.net;URL;false;openStream;;;Argument[-1];request-forgery-sink",
"org.apache.http.client.methods;HttpRequestBase;true;setURI;;;Argument[0];request-forgery-sink",
"org.apache.http.message;BasicHttpRequest;true;setURI;;;Argument[0];request-forgery-sink",
"org.apache.http.client.methods;HttpRequestBase;true;.ctor;;;Argument[0];request-forgery-sink",
"org.apache.http.message;BasicHttpRequest;true;.ctor;;;Argument[0];request-forgery-sink",
"org.apache.http.client.methods;RequestBuilder;false;setURI;;;Argument[0];request-forgery-sink",
"org.apache.http.client.methods;RequestBuilder;false;get;;;Argument[0];request-forgery-sink",
"org.apache.http.client.methods;RequestBuilder;false;post;;;Argument[0];request-forgery-sink",
"org.apache.http.client.methods;RequestBuilder;false;put;;;Argument[0];request-forgery-sink",
"org.apache.http.client.methods;RequestBuilder;false;options;;;Argument[0];request-forgery-sink",
"org.apache.http.client.methods;RequestBuilder;false;head;;;Argument[0];request-forgery-sink",
"org.apache.http.client.methods;RequestBuilder;false;delete;;;Argument[0];request-forgery-sink",
"java.net.http;HttpRequest$Builder;false;uri;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;patchForObject;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;getForObject;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;getForEntity;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;execute;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;exchange;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;put;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;postForObject;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;postForLocation;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;postForEntity;;;Argument[0];request-forgery-sink",
"org.springframework.web.client;RestTemplate;false;doExecute;;;Argument[0];request-forgery-sink",
"javax.ws.rs.client;Client;false;target;;;Argument[0];request-forgery-sink",
"java.net.http;HttpRequest;false;newBuilder;;;Argument[0];request-forgery-sink" // todo: this might be stricter than before. Previously the package name was not checked.
]
/** A data flow sink for request forgery vulnerabilities. */
abstract class RequestForgerySink extends DataFlow::Node { }
/**
* An argument to an url `openConnection` or `openStream` call
* taken as a sink for request forgery vulnerabilities.
*/
private class UrlOpen extends RequestForgerySink {
UrlOpen() {
exists(MethodAccess ma |
ma.getMethod() instanceof UrlOpenConnectionMethod or
ma.getMethod() instanceof UrlOpenStreamMethod
|
this.asExpr() = ma.getQualifier()
)
}
}
/** A data flow sink for request forgery vulnerabilities. */
abstract class RequestForgerySink extends DataFlow::Node { }
/**
* An argument to an Apache `setURI` call taken as a
* sink for request forgery vulnerabilities.
*/
private class ApacheSetUri extends RequestForgerySink {
ApacheSetUri() {
exists(MethodAccess ma |
ma.getReceiverType() instanceof ApacheHttpRequest and
ma.getMethod().hasName("setURI")
|
this.asExpr() = ma.getArgument(0)
)
}
}
/**
* An argument to any Apache Request Instantiation call taken as a
* sink for request forgery vulnerabilities.
*/
private class ApacheHttpRequestInstantiation extends RequestForgerySink {
ApacheHttpRequestInstantiation() {
exists(ClassInstanceExpr c | c.getConstructedType() instanceof ApacheHttpRequest |
this.asExpr() = c.getArgument(0)
)
}
}
/**
* An argument to a Apache RequestBuilder method call taken as a
* sink for request forgery vulnerabilities.
*/
private class ApacheHttpRequestBuilderArgument extends RequestForgerySink {
ApacheHttpRequestBuilderArgument() {
exists(MethodAccess ma |
ma.getReceiverType() instanceof TypeApacheHttpRequestBuilder and
ma.getMethod().hasName(["setURI", "get", "post", "put", "optons", "head", "delete"])
|
this.asExpr() = ma.getArgument(0)
)
}
}
/**
* An argument to any Java.net.http.request Instantiation call taken as a
* sink for request forgery vulnerabilities.
*/
private class HttpRequestNewBuilder extends RequestForgerySink {
HttpRequestNewBuilder() {
exists(MethodAccess call |
call.getCallee().hasName("newBuilder") and
call.getMethod().getDeclaringType().getName() = "HttpRequest"
|
this.asExpr() = call.getArgument(0)
)
}
}
/**
* An argument to an Http Builder `uri` call taken as a
* sink for request forgery vulnerabilities.
*/
private class HttpBuilderUriArgument extends RequestForgerySink {
HttpBuilderUriArgument() {
exists(MethodAccess ma | ma.getMethod() instanceof HttpBuilderUri |
this.asExpr() = ma.getArgument(0)
)
}
}
/**
* An argument to a Spring Rest Template method call taken as a
* sink for request forgery vulnerabilities.
*/
private class SpringRestTemplateArgument extends RequestForgerySink {
SpringRestTemplateArgument() {
exists(MethodAccess ma |
this.asExpr() = ma.getMethod().(SpringRestTemplateUrlMethods).getUrlArgument(ma)
)
}
}
/**
* An argument to `javax.ws.rs.Client`s `target` method call taken as a
* sink for request forgery vulnerabilities.
*/
private class JaxRsClientTarget extends RequestForgerySink {
JaxRsClientTarget() {
exists(MethodAccess ma |
ma.getMethod().getDeclaringType() instanceof JaxRsClient and
ma.getMethod().hasName("target")
|
this.asExpr() = ma.getArgument(0)
)
}
}
/**
* An argument to `org.springframework.http.RequestEntity`s constructor call
@@ -90,3 +166,27 @@ private class RequestEntityUriArg extends RequestForgerySink {
)
}
}
/**
* A class representing all Spring Rest Template methods
* which take an URL as an argument.
*/
private class SpringRestTemplateUrlMethods extends Method {
SpringRestTemplateUrlMethods() {
this.getDeclaringType() instanceof SpringRestTemplate and
this.hasName([
"doExecute", "postForEntity", "postForLocation", "postForObject", "put", "exchange",
"execute", "getForEntity", "getForObject", "patchForObject"
])
}
/**
* Gets the argument which corresponds to a URL argument
* passed as a `java.net.URL` object or as a string or the like
*/
Argument getUrlArgument(MethodAccess ma) {
// doExecute(URI url, HttpMethod method, RequestCallback requestCallback,
// ResponseExtractor<T> responseExtractor)
result = ma.getArgument(0)
}
}

View File

@@ -472,7 +472,7 @@ module CsvValidation {
not type.regexpMatch("[a-zA-Z0-9_\\$]+") and
msg = "Dubious type \"" + type + "\" in " + pred + " model."
or
not (name.regexpMatch("[a-zA-Z0-9_]*") or name = ".ctor") and
not name.regexpMatch("[a-zA-Z0-9_]*") and
msg = "Dubious name \"" + name + "\" in " + pred + " model."
or
not signature.regexpMatch("|\\([a-zA-Z0-9_\\.\\$<>,\\[\\]]*\\)") and
@@ -562,34 +562,23 @@ private string paramsString(Callable c) {
}
private Element interpretElement0(
string namespace, string type, boolean subtypes, string name, string signature, string ext
string namespace, string type, boolean subtypes, string name, string signature
) {
elementSpec(namespace, type, subtypes, name, signature, _) and
exists(RefType t | t = interpretType(namespace, type, subtypes) |
exists(Member m |
result = m and
m.getDeclaringType() = t and
(
m.hasName(name)
or
name = ".ctor" and m.hasName(t.getName())
)
m.hasName(name)
|
signature = "" or
m.(Callable).getSignature() = any(string nameprefix) + signature or
paramsString(m) = signature
) and
ext = ""
)
or
result = t and
name = "" and
signature = "" and
ext = "Annotated"
or
result = t.getAMember() and
name = "" and
signature = "" and
ext = ""
signature = ""
)
}
@@ -597,7 +586,7 @@ private Element interpretElement(
string namespace, string type, boolean subtypes, string name, string signature, string ext
) {
elementSpec(namespace, type, subtypes, name, signature, ext) and
exists(Element e | e = interpretElement0(namespace, type, subtypes, name, signature, ext) |
exists(Element e | e = interpretElement0(namespace, type, subtypes, name, signature) |
ext = "" and result = e
or
ext = "Annotated" and result.(Annotatable).getAnAnnotation().getType() = e

View File

@@ -3,7 +3,6 @@ import semmle.code.java.frameworks.XStream
import semmle.code.java.frameworks.SnakeYaml
import semmle.code.java.frameworks.FastJson
import semmle.code.java.frameworks.apache.Lang
private import semmle.code.java.dataflow.ExternalFlow
class ObjectInputStreamReadObjectMethod extends Method {
ObjectInputStreamReadObjectMethod() {
@@ -27,16 +26,11 @@ class SafeXStream extends DataFlow2::Configuration {
src.asExpr()
}
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "safe-xstream") }
}
private class SafeXStreamSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"com.thoughtworks.xstream;XStream;false;unmarshal;;;Argument[-1];safe-xstream",
"com.thoughtworks.xstream;XStream;false;fromXML;;;Argument[-1];safe-xstream"
]
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and
ma.getMethod() instanceof XStreamReadObjectMethod
)
}
}
@@ -48,17 +42,11 @@ class SafeKryo extends DataFlow2::Configuration {
src.asExpr()
}
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "safe-kryo") }
}
private class SafeKryoSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"com.esotericsoftware.kryo;Kryo;false;readObjectOrNull;;;Argument[-1];safe-kryo",
"com.esotericsoftware.kryo;Kryo;false;readObject;;;Argument[-1];safe-kryo",
"com.esotericsoftware.kryo;Kryo;false;readClassAndObject;;;Argument[-1];safe-kryo"
]
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and
ma.getMethod() instanceof KryoReadObjectMethod
)
}
}