1- /** Provides classes to reason about SpEL injection attacks . */
1+ /** Provides taint tracking and dataflow configurations to be used in SpEL injection queries . */
22
33import java
44import semmle.code.java.dataflow.DataFlow
55import semmle.code.java.dataflow.FlowSources
6-
7- /** A data flow sink for unvalidated user input that is used to construct SpEL expressions. */
8- abstract class SpelExpressionEvaluationSink extends DataFlow:: ExprNode { }
9-
10- /** Default sink for SpEL injection vulnerabilities. */
11- private class DefaultSpelExpressionEvaluationSink extends SpelExpressionEvaluationSink {
12- DefaultSpelExpressionEvaluationSink ( ) {
13- exists ( MethodAccess ma |
14- sinkNode ( this , "spel" ) and
15- this .asExpr ( ) = ma .getQualifier ( ) and
16- not exists ( SafeEvaluationContextFlowConfig config |
17- config .hasFlowTo ( DataFlow:: exprNode ( ma .getArgument ( 0 ) ) )
18- )
19- )
20- }
21- }
22-
23- /**
24- * A unit class for adding additional taint steps.
25- *
26- * Extend this class to add additional taint steps that should apply to the `SpELInjectionConfig`.
27- */
28- class SpelExpressionInjectionAdditionalTaintStep extends Unit {
29- /**
30- * Holds if the step from `node1` to `node2` should be considered a taint
31- * step for the `SpELInjectionConfig` configuration.
32- */
33- abstract predicate step ( DataFlow:: Node node1 , DataFlow:: Node node2 ) ;
34- }
35-
36- /** A set of additional taint steps to consider when taint tracking SpEL related data flows. */
37- private class DefaultSpelExpressionInjectionAdditionalTaintStep extends SpelExpressionInjectionAdditionalTaintStep {
38- override predicate step ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
39- expressionParsingStep ( node1 , node2 )
40- }
41- }
6+ import semmle.code.java.frameworks.spring.SpringExpression
7+ import semmle.code.java.security.SpelInjection
428
439/**
4410 * A taint-tracking configuration for unsafe user input
@@ -56,6 +22,19 @@ class SpelInjectionConfig extends TaintTracking::Configuration {
5622 }
5723}
5824
25+ /** Default sink for SpEL injection vulnerabilities. */
26+ private class DefaultSpelExpressionEvaluationSink extends SpelExpressionEvaluationSink {
27+ DefaultSpelExpressionEvaluationSink ( ) {
28+ exists ( MethodAccess ma |
29+ sinkNode ( this , "spel" ) and
30+ this .asExpr ( ) = ma .getQualifier ( ) and
31+ not exists ( SafeEvaluationContextFlowConfig config |
32+ config .hasFlowTo ( DataFlow:: exprNode ( ma .getArgument ( 0 ) ) )
33+ )
34+ )
35+ }
36+ }
37+
5938/**
6039 * A configuration for safe evaluation context that may be used in expression evaluation.
6140 */
@@ -74,6 +53,9 @@ private class SafeEvaluationContextFlowConfig extends DataFlow2::Configuration {
7453 override int fieldFlowBranchLimit ( ) { result = 0 }
7554}
7655
56+ /**
57+ * A `ContextSource` that is safe from SpEL injection
58+ */
7759private class SafeContextSource extends DataFlow:: ExprNode {
7860 SafeContextSource ( ) {
7961 isSimpleEvaluationContextConstructorCall ( getExpr ( ) ) or
@@ -102,47 +84,3 @@ private predicate isSimpleEvaluationContextBuilderCall(Expr expr) {
10284 ma = expr
10385 )
10486}
105-
106- /**
107- * Methods that trigger evaluation of an expression.
108- */
109- private class ExpressionEvaluationMethod extends Method {
110- ExpressionEvaluationMethod ( ) {
111- this .getDeclaringType ( ) .getASupertype * ( ) instanceof Expression and
112- this .hasName ( [ "getValue" , "getValueTypeDescriptor" , "getValueType" , "setValue" ] )
113- }
114- }
115-
116- /**
117- * Holds if `node1` to `node2` is a dataflow step that parses a SpEL expression,
118- * by calling `parser.parseExpression(tainted)`.
119- */
120- private predicate expressionParsingStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
121- exists ( MethodAccess ma , Method m | ma .getMethod ( ) = m |
122- m .getDeclaringType ( ) .getASupertype * ( ) instanceof ExpressionParser and
123- m .hasName ( [ "parseExpression" , "parseRaw" ] ) and
124- ma .getAnArgument ( ) = node1 .asExpr ( ) and
125- node2 .asExpr ( ) = ma
126- )
127- }
128-
129- private class SimpleEvaluationContext extends RefType {
130- SimpleEvaluationContext ( ) {
131- hasQualifiedName ( "org.springframework.expression.spel.support" , "SimpleEvaluationContext" )
132- }
133- }
134-
135- private class SimpleEvaluationContextBuilder extends RefType {
136- SimpleEvaluationContextBuilder ( ) {
137- hasQualifiedName ( "org.springframework.expression.spel.support" ,
138- "SimpleEvaluationContext$Builder" )
139- }
140- }
141-
142- private class Expression extends RefType {
143- Expression ( ) { hasQualifiedName ( "org.springframework.expression" , "Expression" ) }
144- }
145-
146- private class ExpressionParser extends RefType {
147- ExpressionParser ( ) { hasQualifiedName ( "org.springframework.expression" , "ExpressionParser" ) }
148- }
0 commit comments