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
4
5
5
6
/**
6
7
* A taint-tracking configuration for unsafe user input
@@ -21,7 +22,7 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
21
22
}
22
23
23
24
/**
24
- * A sink for Expresssion Language injection vulnerabilities via Jexl,
25
+ * A sink for Expression Language injection vulnerabilities via Jexl,
25
26
* i.e. method calls that run evaluation of a JEXL expression.
26
27
*
27
28
* Creating a `Callable` from a tainted JEXL expression or script is considered as a sink
@@ -30,18 +31,41 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
30
31
* maybe stored in an object field and then reached by a different flow.
31
32
*/
32
33
private class JexlEvaluationSink extends DataFlow:: ExprNode {
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
- )
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
+ ]
45
69
}
46
70
}
47
71
@@ -98,22 +122,36 @@ private class SandboxedJexlFlowConfig extends DataFlow2::Configuration {
98
122
99
123
override predicate isSource ( DataFlow:: Node node ) { node instanceof SandboxedJexlSource }
100
124
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
- }
125
+ override predicate isSink ( DataFlow:: Node node ) { sinkNode ( node , "sandboxed-jexl" ) }
111
126
112
127
override predicate isAdditionalFlowStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
113
128
createsJexlEngine ( fromNode , toNode )
114
129
}
115
130
}
116
131
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
+
117
155
/**
118
156
* Defines a data flow source for JEXL engines configured with a sandbox.
119
157
*/
@@ -164,52 +202,13 @@ private predicate returnsDataFromBean(DataFlow::Node fromNode, DataFlow::Node to
164
202
)
165
203
}
166
204
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
-
196
205
/**
197
206
* A method that creates a JEXL script.
198
207
*/
199
208
private class CreateJexlScriptMethod extends Method {
200
209
CreateJexlScriptMethod ( ) { getDeclaringType ( ) instanceof JexlEngine and hasName ( "createScript" ) }
201
210
}
202
211
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
-
213
212
/**
214
213
* A method that creates a JEXL template.
215
214
*/
@@ -267,22 +266,6 @@ private class JexlUberspect extends Interface {
267
266
}
268
267
}
269
268
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
-
286
269
private class Reader extends RefType {
287
270
Reader ( ) { hasQualifiedName ( "java.io" , "Reader" ) }
288
271
}
0 commit comments