Promote exxperimental XXE sinks

This commit is contained in:
Tony Torralba
2023-04-26 12:11:48 +02:00
parent 8b65937159
commit 1e66a544fd
5 changed files with 204 additions and 5 deletions

View File

@@ -0,0 +1,90 @@
/** Provides XML definitions related to the `org.apache.commons` package. */
import java
private import semmle.code.java.dataflow.RangeUtils
private import semmle.code.java.security.XmlParsers
/**
* The classes `org.apache.commons.digester3.Digester`, `org.apache.commons.digester.Digester` or `org.apache.tomcat.util.digester.Digester`.
*/
private class Digester extends RefType {
Digester() {
this.hasQualifiedName([
"org.apache.commons.digester3", "org.apache.commons.digester",
"org.apache.tomcat.util.digester"
], "Digester")
}
}
/** A call to `Digester.parse`. */
private class DigesterParse extends XmlParserCall {
DigesterParse() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Digester and
m.hasName("parse")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { SafeDigesterFlow::flowToExpr(this.getQualifier()) }
}
/** A `ParserConfig` that is specific to `Digester`. */
private class DigesterConfig extends ParserConfig {
DigesterConfig() {
exists(Method m |
m = this.getMethod() and
m.getDeclaringType() instanceof Digester and
m.hasName("setFeature")
)
}
}
/**
* A safely configured `Digester`.
*/
private class SafeDigester extends VarAccess {
SafeDigester() {
exists(Variable v | v = this.getVariable() |
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config.enables(singleSafeConfig())
)
or
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-general-entities"
))
) and
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-parameter-entities"
))
) and
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() =
"http://apache.org/xml/features/nonvalidating/load-external-dtd"
))
)
)
}
}
private module SafeDigesterFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDigester }
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and ma.getMethod().getDeclaringType() instanceof Digester
)
}
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeDigesterFlow = DataFlow::Global<SafeDigesterFlowConfig>;

View File

@@ -0,0 +1,64 @@
/** Provides definitions related to the `javax.xml` package. */
import java
private import semmle.code.java.security.XmlParsers
/** A call to `Validator.validate`. */
private class ValidatorValidate extends XmlParserCall {
ValidatorValidate() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Validator and
m.hasName("validate")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { SafeValidatorFlow::flowToExpr(this.getQualifier()) }
}
/** A `TransformerConfig` specific to `Validator`. */
private class ValidatorConfig extends TransformerConfig {
ValidatorConfig() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Validator and
m.hasName("setProperty")
)
}
}
/** The class `javax.xml.validation.Validator`. */
private class Validator extends RefType {
Validator() { this.hasQualifiedName("javax.xml.validation", "Validator") }
}
/** A safely configured `Validator`. */
private class SafeValidator extends VarAccess {
SafeValidator() {
exists(Variable v | v = this.getVariable() |
exists(ValidatorConfig config | config.getQualifier() = v.getAnAccess() |
config.disables(configAccessExternalDtd())
) and
exists(ValidatorConfig config | config.getQualifier() = v.getAnAccess() |
config.disables(configAccessExternalSchema())
)
)
}
}
private module SafeValidatorFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeValidator }
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and
ma.getMethod().getDeclaringType() instanceof Validator
)
}
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeValidatorFlow = DataFlow::Global<SafeValidatorFlowConfig>;

View File

@@ -0,0 +1,24 @@
/** Provides definitions related to the `java.beans` package. */
import java
private import semmle.code.java.security.XmlParsers
/** The class `java.beans.XMLDecoder`. */
private class XmlDecoder extends RefType {
XmlDecoder() { this.hasQualifiedName("java.beans", "XMLDecoder") }
}
/** A call to `XMLDecoder.readObject`. */
private class XmlDecoderReadObject extends XmlParserCall {
XmlDecoderReadObject() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof XmlDecoder and
m.hasName("readObject")
)
}
override Expr getSink() { result = this.getQualifier() }
override predicate isSafe() { none() }
}

View File

@@ -0,0 +1,19 @@
/** Provides definitions related to XML parsing in Rundeck. */
import java
private import semmle.code.java.security.XmlParsers
/** A call to `ParserHelper.loadDocument`. */
private class ParserHelperLoadDocument extends XmlParserCall {
ParserHelperLoadDocument() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType().hasQualifiedName("org.rundeck.api.parser", "ParserHelper") and
m.hasName("loadDocument")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { none() }
}

View File

@@ -2,13 +2,15 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.DataFlow2
import semmle.code.java.dataflow.DataFlow3
private import semmle.code.java.dataflow.RangeUtils
/*
* Various XML parsers in Java.
*/
private module Frameworks {
private import semmle.code.java.frameworks.apache.CommonsXml
private import semmle.code.java.frameworks.javaee.Xml
private import semmle.code.java.frameworks.javase.Beans
private import semmle.code.java.frameworks.rundeck.RundeckXml
}
/**
* An abstract type representing a call to parse XML files.
@@ -946,7 +948,7 @@ class TransformerFactorySource extends XmlParserCall {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof TransformerFactory and
m.hasName("newTransformer")
m.hasName(["newTransformer", "newTransformerHandler"])
)
}