Files
codeql/java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll
2021-10-15 15:27:37 +02:00

87 lines
2.9 KiB
Plaintext

/** Provides taint tracking and dataflow configurations to be used in SpEL injection queries. */
import java
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.frameworks.spring.SpringExpression
private import semmle.code.java.security.SpelInjection
/**
* A taint-tracking configuration for unsafe user input
* that is used to construct and evaluate a SpEL expression.
*/
class SpelInjectionConfig extends TaintTracking::Configuration {
SpelInjectionConfig() { this = "SpelInjectionConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof SpelExpressionEvaluationSink }
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
any(SpelExpressionInjectionAdditionalTaintStep c).step(node1, node2)
}
}
/** Default sink for SpEL injection vulnerabilities. */
private class DefaultSpelExpressionEvaluationSink extends SpelExpressionEvaluationSink {
DefaultSpelExpressionEvaluationSink() {
exists(MethodAccess ma |
ma.getMethod() instanceof ExpressionEvaluationMethod and
ma.getQualifier() = this.asExpr() and
not exists(SafeEvaluationContextFlowConfig config |
config.hasFlowTo(DataFlow::exprNode(ma.getArgument(0)))
)
)
}
}
/**
* A configuration for safe evaluation context that may be used in expression evaluation.
*/
private class SafeEvaluationContextFlowConfig extends DataFlow2::Configuration {
SafeEvaluationContextFlowConfig() { this = "SpelInjection::SafeEvaluationContextFlowConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof SafeContextSource }
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod() instanceof ExpressionEvaluationMethod and
ma.getArgument(0) = sink.asExpr()
)
}
override int fieldFlowBranchLimit() { result = 0 }
}
/**
* A `ContextSource` that is safe from SpEL injection.
*/
private class SafeContextSource extends DataFlow::ExprNode {
SafeContextSource() {
isSimpleEvaluationContextConstructorCall(this.getExpr()) or
isSimpleEvaluationContextBuilderCall(this.getExpr())
}
}
/**
* Holds if `expr` constructs `SimpleEvaluationContext`.
*/
private predicate isSimpleEvaluationContextConstructorCall(Expr expr) {
exists(ConstructorCall cc |
cc.getConstructedType() instanceof SimpleEvaluationContext and
cc = expr
)
}
/**
* Holds if `expr` builds `SimpleEvaluationContext` via `SimpleEvaluationContext.Builder`,
* for instance, `SimpleEvaluationContext.forReadWriteDataBinding().build()`.
*/
private predicate isSimpleEvaluationContextBuilderCall(Expr expr) {
exists(MethodAccess ma, Method m | ma.getMethod() = m |
m.getDeclaringType() instanceof SimpleEvaluationContextBuilder and
m.hasName("build") and
ma = expr
)
}