11import java
22import semmle.code.java.dataflow.FlowSources
33import semmle.code.java.dataflow.TaintTracking
4+ private import semmle.code.java.dataflow.ExternalFlow
45
56/**
67 * A taint-tracking configuration for unsafe user input
@@ -21,7 +22,7 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
2122}
2223
2324/**
24- * A sink for Expresssion Language injection vulnerabilities via Jexl,
25+ * A sink for Expression Language injection vulnerabilities via Jexl,
2526 * i.e. method calls that run evaluation of a JEXL expression.
2627 *
2728 * Creating a `Callable` from a tainted JEXL expression or script is considered as a sink
@@ -30,18 +31,41 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
3031 * maybe stored in an object field and then reached by a different flow.
3132 */
3233private 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+ ]
4569 }
4670}
4771
@@ -98,22 +122,36 @@ private class SandboxedJexlFlowConfig extends DataFlow2::Configuration {
98122
99123 override predicate isSource ( DataFlow:: Node node ) { node instanceof SandboxedJexlSource }
100124
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" ) }
111126
112127 override predicate isAdditionalFlowStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
113128 createsJexlEngine ( fromNode , toNode )
114129 }
115130}
116131
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+
117155/**
118156 * Defines a data flow source for JEXL engines configured with a sandbox.
119157 */
@@ -164,52 +202,13 @@ private predicate returnsDataFromBean(DataFlow::Node fromNode, DataFlow::Node to
164202 )
165203}
166204
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-
196205/**
197206 * A method that creates a JEXL script.
198207 */
199208private class CreateJexlScriptMethod extends Method {
200209 CreateJexlScriptMethod ( ) { getDeclaringType ( ) instanceof JexlEngine and hasName ( "createScript" ) }
201210}
202211
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-
213212/**
214213 * A method that creates a JEXL template.
215214 */
@@ -267,22 +266,6 @@ private class JexlUberspect extends Interface {
267266 }
268267}
269268
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-
286269private class Reader extends RefType {
287270 Reader ( ) { hasQualifiedName ( "java.io" , "Reader" ) }
288271}
0 commit comments