11import java
22import semmle.code.java.dataflow.FlowSources
33import semmle.code.java.dataflow.TaintTracking
4- private import semmle.code.java.dataflow.ExternalFlow
54
65/**
76 * A taint-tracking configuration for unsafe user input
@@ -22,7 +21,7 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
2221}
2322
2423/**
25- * A sink for Expression Language injection vulnerabilities via Jexl,
24+ * A sink for Expresssion Language injection vulnerabilities via Jexl,
2625 * i.e. method calls that run evaluation of a JEXL expression.
2726 *
2827 * Creating a `Callable` from a tainted JEXL expression or script is considered as a sink
@@ -31,41 +30,18 @@ class JexlInjectionConfig extends TaintTracking::Configuration {
3130 * maybe stored in an object field and then reached by a different flow.
3231 */
3332private 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+ )
6945 }
7046}
7147
@@ -122,36 +98,22 @@ private class SandboxedJexlFlowConfig extends DataFlow2::Configuration {
12298
12399 override predicate isSource ( DataFlow:: Node node ) { node instanceof SandboxedJexlSource }
124100
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+ }
126111
127112 override predicate isAdditionalFlowStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
128113 createsJexlEngine ( fromNode , toNode )
129114 }
130115}
131116
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-
155117/**
156118 * Defines a data flow source for JEXL engines configured with a sandbox.
157119 */
@@ -202,13 +164,52 @@ private predicate returnsDataFromBean(DataFlow::Node fromNode, DataFlow::Node to
202164 )
203165}
204166
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+
205196/**
206197 * A method that creates a JEXL script.
207198 */
208199private class CreateJexlScriptMethod extends Method {
209200 CreateJexlScriptMethod ( ) { getDeclaringType ( ) instanceof JexlEngine and hasName ( "createScript" ) }
210201}
211202
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+
212213/**
213214 * A method that creates a JEXL template.
214215 */
@@ -266,6 +267,22 @@ private class JexlUberspect extends Interface {
266267 }
267268}
268269
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+
269286private class Reader extends RefType {
270287 Reader ( ) { hasQualifiedName ( "java.io" , "Reader" ) }
271288}
0 commit comments