diff --git a/java/ql/src/Security/CWE/CWE-094/JexlInjection.ql b/java/ql/src/Security/CWE/CWE-094/JexlInjection.ql index 2c2076ee2c0..26585e5d2dc 100644 --- a/java/ql/src/Security/CWE/CWE-094/JexlInjection.ql +++ b/java/ql/src/Security/CWE/CWE-094/JexlInjection.ql @@ -12,27 +12,9 @@ */ import java -import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.JexlInjectionQuery import DataFlow::PathGraph -/** - * A taint-tracking configuration for unsafe user input - * that is used to construct and evaluate a JEXL expression. - * It supports both JEXL 2 and 3. - */ -class JexlInjectionConfig extends TaintTracking::Configuration { - JexlInjectionConfig() { this = "JexlInjectionConfig" } - - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { sink instanceof JexlEvaluationSink } - - override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { - any(JexlInjectionAdditionalTaintStep c).step(node1, node2) - } -} - from DataFlow::PathNode source, DataFlow::PathNode sink, JexlInjectionConfig conf where conf.hasFlowPath(source, sink) select sink.getNode(), source, sink, "JEXL injection from $@.", source.getNode(), "this user input" diff --git a/java/ql/src/semmle/code/java/security/JexlInjectionQuery.qll b/java/ql/src/semmle/code/java/security/JexlInjectionQuery.qll index 07000df15ce..bfb77715569 100644 --- a/java/ql/src/semmle/code/java/security/JexlInjectionQuery.qll +++ b/java/ql/src/semmle/code/java/security/JexlInjectionQuery.qll @@ -2,6 +2,7 @@ import java import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.FlowSources private import semmle.code.java.dataflow.ExternalFlow /** @@ -37,6 +38,23 @@ private class DefaultJexlInjectionAdditionalTaintStep extends JexlInjectionAddit } } +/** + * A taint-tracking configuration for unsafe user input + * that is used to construct and evaluate a JEXL expression. + * It supports both JEXL 2 and 3. + */ +class JexlInjectionConfig extends TaintTracking::Configuration { + JexlInjectionConfig() { this = "JexlInjectionConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof JexlEvaluationSink } + + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + any(JexlInjectionAdditionalTaintStep c).step(node1, node2) + } +} + /** * Holds if `n1` to `n2` is a dataflow step that creates a JEXL script using an unsafe engine * by calling `tainted.createScript(jexlExpr)`. diff --git a/java/ql/test/query-tests/security/CWE-094/JexlInjectionTest.ql b/java/ql/test/query-tests/security/CWE-094/JexlInjectionTest.ql index 58f16bf068d..b9cb3fc03df 100644 --- a/java/ql/test/query-tests/security/CWE-094/JexlInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-094/JexlInjectionTest.ql @@ -1,22 +1,7 @@ import java -import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.FlowSteps -import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.JexlInjectionQuery import TestUtilities.InlineExpectationsTest -class Conf extends TaintTracking::Configuration { - Conf() { this = "qltest:cwe:jexl-injection" } - - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { sink instanceof JexlEvaluationSink } - - override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { - any(JexlInjectionAdditionalTaintStep c).step(node1, node2) - } -} - class JexlInjectionTest extends InlineExpectationsTest { JexlInjectionTest() { this = "HasJexlInjectionTest" } @@ -24,7 +9,9 @@ class JexlInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasJexlInjection" and - exists(DataFlow::Node src, DataFlow::Node sink, Conf conf | conf.hasFlow(src, sink) | + exists(DataFlow::Node src, DataFlow::Node sink, JexlInjectionConfig conf | + conf.hasFlow(src, sink) + | sink.getLocation() = location and element = sink.toString() and value = ""