1
- /** Provides classes to reason about SpEL injection attacks . */
1
+ /** Provides taint tracking and dataflow configurations to be used in SpEL injection queries . */
2
2
3
3
import java
4
4
import semmle.code.java.dataflow.DataFlow
5
5
import 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
42
8
43
9
/**
44
10
* A taint-tracking configuration for unsafe user input
@@ -56,6 +22,19 @@ class SpelInjectionConfig extends TaintTracking::Configuration {
56
22
}
57
23
}
58
24
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
+
59
38
/**
60
39
* A configuration for safe evaluation context that may be used in expression evaluation.
61
40
*/
@@ -74,6 +53,9 @@ private class SafeEvaluationContextFlowConfig extends DataFlow2::Configuration {
74
53
override int fieldFlowBranchLimit ( ) { result = 0 }
75
54
}
76
55
56
+ /**
57
+ * A `ContextSource` that is safe from SpEL injection
58
+ */
77
59
private class SafeContextSource extends DataFlow:: ExprNode {
78
60
SafeContextSource ( ) {
79
61
isSimpleEvaluationContextConstructorCall ( getExpr ( ) ) or
@@ -102,47 +84,3 @@ private predicate isSimpleEvaluationContextBuilderCall(Expr expr) {
102
84
ma = expr
103
85
)
104
86
}
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