1
1
import java
2
2
import semmle.code.java.dataflow.FlowSources
3
3
import semmle.code.java.dataflow.TaintTracking
4
- private import semmle.code.java.dataflow.ExternalFlow
5
4
6
5
/**
7
6
* A taint-tracking configuration for unsafe user input
@@ -22,7 +21,7 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
22
21
}
23
22
24
23
/**
25
- * A sink for Expression Language injection vulnerabilities via Jexl,
24
+ * A sink for Expresssion Language injection vulnerabilities via Jexl,
26
25
* i.e. method calls that run evaluation of a JEXL expression.
27
26
*
28
27
* Creating a `Callable` from a tainted JEXL expression or script is considered as a sink
@@ -31,41 +30,18 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
31
30
* maybe stored in an object field and then reached by a different flow.
32
31
*/
33
32
private class JexlEvaluationSink extends DataFlow:: ExprNode {
34
- JexlEvaluationSink ( ) { sinkNode ( this , "jexl" ) }
35
- }
36
-
37
- private class JexlEvaluationSinkModel extends SinkModelCsv {
38
- override predicate row ( string row ) {
39
- row =
40
- [
41
- // Direct JEXL evaluation
42
- "org.apache.commons.jexl2;Expression;false;evaluate;;;Argument[-1];jexl" ,
43
- "org.apache.commons.jexl3;JexlExpression;false;evaluate;;;Argument[-1];jexl" ,
44
- "org.apache.commons.jexl2;Script;false;execute;;;Argument[-1];jexl" ,
45
- "org.apache.commons.jexl3;JexlScript;false;execute;;;Argument[-1];jexl" ,
46
- "org.apache.commons.jexl2;JxltEngine$Expression;false;evaluate;;;Argument[-1];jexl" ,
47
- "org.apache.commons.jexl3;JxltEngine$Expression;false;evaluate;;;Argument[-1];jexl" ,
48
- "org.apache.commons.jexl2;JxltEngine$Expression;false;prepare;;;Argument[-1];jexl" ,
49
- "org.apache.commons.jexl3;JxltEngine$Expression;false;prepare;;;Argument[-1];jexl" ,
50
- "org.apache.commons.jexl2;JxltEngine$Template;false;evaluate;;;Argument[-1];jexl" ,
51
- "org.apache.commons.jexl3;JxltEngine$Template;false;evaluate;;;Argument[-1];jexl" ,
52
- "org.apache.commons.jexl2;UnifiedJEXL$Expression;false;evaluate;;;Argument[-1];jexl" ,
53
- "org.apache.commons.jexl3;UnifiedJEXL$Expression;false;evaluate;;;Argument[-1];jexl" ,
54
- "org.apache.commons.jexl2;UnifiedJEXL$Expression;false;prepare;;;Argument[-1];jexl" ,
55
- "org.apache.commons.jexl3;UnifiedJEXL$Expression;false;prepare;;;Argument[-1];jexl" ,
56
- "org.apache.commons.jexl2;UnifiedJEXL$Template;false;evaluate;;;Argument[-1];jexl" ,
57
- "org.apache.commons.jexl3;UnifiedJEXL$Template;false;evaluate;;;Argument[-1];jexl" ,
58
- // JEXL callable
59
- "org.apache.commons.jexl2;Expression;false;callable;;;Argument[-1];jexl" ,
60
- "org.apache.commons.jexl3;JexlExpression;false;callable;;;Argument[-1];jexl" ,
61
- "org.apache.commons.jexl2;Script;false;callable;;;Argument[-1];jexl" ,
62
- "org.apache.commons.jexl3;JexlScript;false;callable;;;Argument[-1];jexl" ,
63
- // Methods in the `JexlEngine` class that gets or sets a property with a JEXL expression.
64
- "org.apache.commons.jexl2;JexlEngine;false;getProperty;;;Argument[1..2];jexl" ,
65
- "org.apache.commons.jexl3;JexlEngine;false;getProperty;;;Argument[1..2];jexl" ,
66
- "org.apache.commons.jexl2;JexlEngine;false;setProperty;;;Argument[1];jexl" ,
67
- "org.apache.commons.jexl3;JexlEngine;false;setProperty;;;Argument[1];jexl"
68
- ]
33
+ JexlEvaluationSink ( ) {
34
+ exists ( MethodAccess ma , Method m , Expr taintFrom |
35
+ ma .getMethod ( ) = m and taintFrom = this .asExpr ( )
36
+ |
37
+ m instanceof DirectJexlEvaluationMethod and ma .getQualifier ( ) = taintFrom
38
+ or
39
+ m instanceof CreateJexlCallableMethod and ma .getQualifier ( ) = taintFrom
40
+ or
41
+ m instanceof JexlEngineGetSetPropertyMethod and
42
+ taintFrom .getType ( ) instanceof TypeString and
43
+ ma .getAnArgument ( ) = taintFrom
44
+ )
69
45
}
70
46
}
71
47
@@ -122,36 +98,22 @@ private class SandboxedJexlFlowConfig extends DataFlow2::Configuration {
122
98
123
99
override predicate isSource ( DataFlow:: Node node ) { node instanceof SandboxedJexlSource }
124
100
125
- override predicate isSink ( DataFlow:: Node node ) { sinkNode ( node , "sandboxed-jexl" ) }
101
+ override predicate isSink ( DataFlow:: Node node ) {
102
+ exists ( MethodAccess ma , Method m | ma .getMethod ( ) = m |
103
+ (
104
+ m instanceof CreateJexlScriptMethod or
105
+ m instanceof CreateJexlExpressionMethod or
106
+ m instanceof CreateJexlTemplateMethod
107
+ ) and
108
+ ma .getQualifier ( ) = node .asExpr ( )
109
+ )
110
+ }
126
111
127
112
override predicate isAdditionalFlowStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
128
113
createsJexlEngine ( fromNode , toNode )
129
114
}
130
115
}
131
116
132
- private class SandboxedJexlEvaluationSinkModel extends SinkModelCsv {
133
- override predicate row ( string row ) {
134
- row =
135
- [
136
- // CreateJexlScriptMethod
137
- "org.apache.commons.jexl2;JexlEngine;false;createScript;;;Argument[-1];sandboxed-jexl" ,
138
- "org.apache.commons.jexl3;JexlEngine;false;createScript;;;Argument[-1];sandboxed-jexl" ,
139
- // CreateJexlExpressionMethod
140
- "org.apache.commons.jexl2;UnifiedJEXL;false;parse;;;Argument[-1];sandboxed-jexl" ,
141
- "org.apache.commons.jexl3;UnifiedJEXL;false;parse;;;Argument[-1];sandboxed-jexl" ,
142
- "org.apache.commons.jexl2;JxltEngine;false;createExpression;;;Argument[-1];sandboxed-jexl" ,
143
- "org.apache.commons.jexl3;JxltEngine;false;createExpression;;;Argument[-1];sandboxed-jexl" ,
144
- "org.apache.commons.jexl2;JexlEngine;false;createExpression;;;Argument[-1];sandboxed-jexl" ,
145
- "org.apache.commons.jexl3;JexlEngine;false;createExpression;;;Argument[-1];sandboxed-jexl" ,
146
- // CreateJexlTemplateMethod
147
- "org.apache.commons.jexl2;JxltEngine;false;createTemplate;;;Argument[-1];sandboxed-jexl" ,
148
- "org.apache.commons.jexl3;JxltEngine;false;createTemplate;;;Argument[-1];sandboxed-jexl" ,
149
- "org.apache.commons.jexl2;UnifiedJEXL;false;createTemplate;;;Argument[-1];sandboxed-jexl" ,
150
- "org.apache.commons.jexl3;UnifiedJEXL;false;createTemplate;;;Argument[-1];sandboxed-jexl"
151
- ]
152
- }
153
- }
154
-
155
117
/**
156
118
* Defines a data flow source for JEXL engines configured with a sandbox.
157
119
*/
@@ -202,13 +164,52 @@ private predicate returnsDataFromBean(DataFlow::Node fromNode, DataFlow::Node to
202
164
)
203
165
}
204
166
167
+ /**
168
+ * A methods in the `JexlEngine` class that gets or sets a property with a JEXL expression.
169
+ */
170
+ private class JexlEngineGetSetPropertyMethod extends Method {
171
+ JexlEngineGetSetPropertyMethod ( ) {
172
+ getDeclaringType ( ) instanceof JexlEngine and
173
+ hasName ( [ "getProperty" , "setProperty" ] )
174
+ }
175
+ }
176
+
177
+ /**
178
+ * A method that triggers direct evaluation of JEXL expressions.
179
+ */
180
+ private class DirectJexlEvaluationMethod extends Method {
181
+ DirectJexlEvaluationMethod ( ) {
182
+ getDeclaringType ( ) instanceof JexlExpression and hasName ( "evaluate" )
183
+ or
184
+ getDeclaringType ( ) instanceof JexlScript and hasName ( "execute" )
185
+ or
186
+ getDeclaringType ( ) instanceof JxltEngineExpression and hasName ( [ "evaluate" , "prepare" ] )
187
+ or
188
+ getDeclaringType ( ) instanceof JxltEngineTemplate and hasName ( "evaluate" )
189
+ or
190
+ getDeclaringType ( ) instanceof UnifiedJexlExpression and hasName ( [ "evaluate" , "prepare" ] )
191
+ or
192
+ getDeclaringType ( ) instanceof UnifiedJexlTemplate and hasName ( "evaluate" )
193
+ }
194
+ }
195
+
205
196
/**
206
197
* A method that creates a JEXL script.
207
198
*/
208
199
private class CreateJexlScriptMethod extends Method {
209
200
CreateJexlScriptMethod ( ) { getDeclaringType ( ) instanceof JexlEngine and hasName ( "createScript" ) }
210
201
}
211
202
203
+ /**
204
+ * A method that creates a `Callable` for a JEXL expression or script.
205
+ */
206
+ private class CreateJexlCallableMethod extends Method {
207
+ CreateJexlCallableMethod ( ) {
208
+ ( getDeclaringType ( ) instanceof JexlExpression or getDeclaringType ( ) instanceof JexlScript ) and
209
+ hasName ( "callable" )
210
+ }
211
+ }
212
+
212
213
/**
213
214
* A method that creates a JEXL template.
214
215
*/
@@ -266,6 +267,22 @@ private class JexlUberspect extends Interface {
266
267
}
267
268
}
268
269
270
+ private class JxltEngineExpression extends NestedType {
271
+ JxltEngineExpression ( ) { getEnclosingType ( ) instanceof JxltEngine and hasName ( "Expression" ) }
272
+ }
273
+
274
+ private class JxltEngineTemplate extends NestedType {
275
+ JxltEngineTemplate ( ) { getEnclosingType ( ) instanceof JxltEngine and hasName ( "Template" ) }
276
+ }
277
+
278
+ private class UnifiedJexlExpression extends NestedType {
279
+ UnifiedJexlExpression ( ) { getEnclosingType ( ) instanceof UnifiedJexl and hasName ( "Expression" ) }
280
+ }
281
+
282
+ private class UnifiedJexlTemplate extends NestedType {
283
+ UnifiedJexlTemplate ( ) { getEnclosingType ( ) instanceof UnifiedJexl and hasName ( "Template" ) }
284
+ }
285
+
269
286
private class Reader extends RefType {
270
287
Reader ( ) { hasQualifiedName ( "java.io" , "Reader" ) }
271
288
}
0 commit comments