mirror of
https://github.com/github/codeql.git
synced 2026-01-27 13:23:00 +01:00
91 lines
3.2 KiB
Plaintext
91 lines
3.2 KiB
Plaintext
/** Provides taint tracking configurations to be used in XSLT injection queries. */
|
|
|
|
import java
|
|
import semmle.code.java.dataflow.FlowSources
|
|
import semmle.code.java.dataflow.TaintTracking
|
|
import semmle.code.java.security.XmlParsers
|
|
import semmle.code.java.security.XsltInjection
|
|
|
|
/**
|
|
* A taint-tracking configuration for unvalidated user input that is used in XSLT transformation.
|
|
*/
|
|
class XsltInjectionFlowConfig extends TaintTracking::Configuration {
|
|
XsltInjectionFlowConfig() { this = "XsltInjectionFlowConfig" }
|
|
|
|
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
|
|
|
override predicate isSink(DataFlow::Node sink) { sink instanceof XsltInjectionSink }
|
|
|
|
override predicate isSanitizer(DataFlow::Node node) {
|
|
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
|
}
|
|
|
|
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
any(XsltInjectionAdditionalTaintStep c).step(node1, node2)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A set of additional taint steps to consider when taint tracking XSLT related data flows.
|
|
* These steps use data flow logic themselves.
|
|
*/
|
|
private class DataFlowXsltInjectionAdditionalTaintStep extends XsltInjectionAdditionalTaintStep {
|
|
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
|
|
newTransformerOrTemplatesStep(node1, node2)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Holds if `n1` to `n2` is a dataflow step that converts between `Source` and `Transformer` or
|
|
* `Templates`, i.e. `TransformerFactory.newTransformer(tainted)` or
|
|
* `TransformerFactory.newTemplates(tainted)`.
|
|
*/
|
|
private predicate newTransformerOrTemplatesStep(DataFlow::Node n1, DataFlow::Node n2) {
|
|
exists(MethodAccess ma, Method m | ma.getMethod() = m |
|
|
n1.asExpr() = ma.getAnArgument() and
|
|
n2.asExpr() = ma and
|
|
m.getDeclaringType() instanceof TransformerFactory and
|
|
m.hasName(["newTransformer", "newTemplates"]) and
|
|
not exists(TransformerFactoryWithSecureProcessingFeatureFlowConfig conf |
|
|
conf.hasFlowToExpr(ma.getQualifier())
|
|
)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* A data flow configuration for secure processing feature that is enabled on `TransformerFactory`.
|
|
*/
|
|
private class TransformerFactoryWithSecureProcessingFeatureFlowConfig extends DataFlow2::Configuration {
|
|
TransformerFactoryWithSecureProcessingFeatureFlowConfig() {
|
|
this = "TransformerFactoryWithSecureProcessingFeatureFlowConfig"
|
|
}
|
|
|
|
override predicate isSource(DataFlow::Node src) {
|
|
exists(Variable v | v = src.asExpr().(VarAccess).getVariable() |
|
|
exists(TransformerFactoryFeatureConfig config | config.getQualifier() = v.getAnAccess() |
|
|
config.enables(configSecureProcessing())
|
|
)
|
|
)
|
|
}
|
|
|
|
override predicate isSink(DataFlow::Node sink) {
|
|
exists(MethodAccess ma |
|
|
sink.asExpr() = ma.getQualifier() and
|
|
ma.getMethod().getDeclaringType() instanceof TransformerFactory
|
|
)
|
|
}
|
|
|
|
override int fieldFlowBranchLimit() { result = 0 }
|
|
}
|
|
|
|
/** A `ParserConfig` specific to `TransformerFactory`. */
|
|
private class TransformerFactoryFeatureConfig extends ParserConfig {
|
|
TransformerFactoryFeatureConfig() {
|
|
exists(Method m |
|
|
m = this.getMethod() and
|
|
m.getDeclaringType() instanceof TransformerFactory and
|
|
m.hasName("setFeature")
|
|
)
|
|
}
|
|
}
|