From 457e2eaf594f052af8e89375670fac54437074c8 Mon Sep 17 00:00:00 2001 From: Grzegorz Golawski Date: Sun, 19 Apr 2020 20:31:57 +0200 Subject: [PATCH 1/4] CodeQL query to detect OGNL injections --- .../Security/CWE/CWE-917/OgnlInjection.java | 17 +++ .../Security/CWE/CWE-917/OgnlInjection.qhelp | 34 ++++++ .../Security/CWE/CWE-917/OgnlInjection.ql | 22 ++++ .../Security/CWE/CWE-917/OgnlInjectionLib.qll | 109 ++++++++++++++++++ java/ql/src/experimental/qlpack.yml | 4 + java/ql/test/experimental/qlpack.yml | 4 + .../security/CWE-917/OgnlInjection.expected | 48 ++++++++ .../security/CWE-917/OgnlInjection.java | 41 +++++++ .../security/CWE-917/OgnlInjection.qlref | 1 + .../query-tests/security/CWE-917/options | 1 + .../stubs/ognl-3.2.14/ognl/JavaSource.java | 3 + .../stubs/ognl-3.2.14/ognl/Node.java | 6 + .../stubs/ognl-3.2.14/ognl/Ognl.java | 26 +++++ .../stubs/ognl-3.2.14/ognl/OgnlContext.java | 71 ++++++++++++ .../stubs/ognl-3.2.14/ognl/OgnlException.java | 3 + .../web/bind/annotation/RequestParam.java | 8 ++ .../opensymphony/xwork2/ognl/OgnlUtil.java | 16 +++ 17 files changed, 414 insertions(+) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.java create mode 100644 java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp create mode 100644 java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.ql create mode 100644 java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjectionLib.qll create mode 100644 java/ql/src/experimental/qlpack.yml create mode 100644 java/ql/test/experimental/qlpack.yml create mode 100644 java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.qlref create mode 100644 java/ql/test/experimental/query-tests/security/CWE-917/options create mode 100644 java/ql/test/experimental/stubs/ognl-3.2.14/ognl/JavaSource.java create mode 100644 java/ql/test/experimental/stubs/ognl-3.2.14/ognl/Node.java create mode 100644 java/ql/test/experimental/stubs/ognl-3.2.14/ognl/Ognl.java create mode 100644 java/ql/test/experimental/stubs/ognl-3.2.14/ognl/OgnlContext.java create mode 100644 java/ql/test/experimental/stubs/ognl-3.2.14/ognl/OgnlException.java create mode 100644 java/ql/test/experimental/stubs/springframework-5.2.3/org/springframework/web/bind/annotation/RequestParam.java create mode 100644 java/ql/test/experimental/stubs/struts2-core-2.5.22/com/opensymphony/xwork2/ognl/OgnlUtil.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.java b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.java new file mode 100644 index 00000000000..cc99ff46517 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.java @@ -0,0 +1,17 @@ +import ognl.Ognl; +import ognl.OgnlException; + +public void evaluate(HttpServletRequest request, Object root) throws OgnlException { + String expression = request.getParameter("expression"); + + // BAD: User provided expression is evaluated + Ognl.getValue(expression, root); + + // GOOD: The name is validated and expression is evaluated in sandbox + System.setProperty("ognl.security.manager", ""); // Or add -Dognl.security.manager to JVM args + if (isValid(expression)) { + Ognl.getValue(expression, root); + } else { + // Reject the request + } +} \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp new file mode 100644 index 00000000000..66d04e41433 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp @@ -0,0 +1,34 @@ + + + +

Object-Graph Navigation Language (OGNL) is an open-source Expression Language (EL) for Java. Due +to its ability to create or change executable code, OGNL is capable of introducing critical +security flaws to any application that uses it. Evaluation of unvalidated expressions can let +attacker to modify Java objects' properties or execute arbitrary code.

+
+ + +

The general recommendation is to not evaluate untrusted ONGL expressions. If user provided OGNL +expressions must be evaluated, do this in sandbox (add `-Dognl.security.manager` to JVM arguments) +and validate the expressions before evaluation.

+
+ + +

In the following examples, the code accepts an OGNL expression from the user and evaluates it. +

+ +

In the first example, the user provided OGNL expression is parsed and evaluated.

+ +

The second example validates the expression and evaluates it inside the sandbox.

+ + +
+ + +
  • Oracle: Java Naming and Directory Interface (JNDI).
  • +
  • Black Hat materials: A Journey from JNDI/LDAP Manipulation to Remote Code Execution Dream Land.
  • +
  • Veracode: Exploiting JNDI Injections in Java.
  • +
    +
    diff --git a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.ql new file mode 100644 index 00000000000..e8a75591b98 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.ql @@ -0,0 +1,22 @@ +/** + * @name OGNL Expression Language statement with user-controlled input + * @description Evaluation of OGNL Expression Language statement with user-controlled input can + * lead to execution of arbitrary code. + * @kind path-problem + * @problem.severity error + * @precision high + * @id java/ognl-injection + * @tags security + * external/cwe/cwe-917 + */ + +import java +import semmle.code.java.dataflow.FlowSources +import DataFlow +import DataFlow::PathGraph +import OgnlInjectionLib + +from DataFlow::PathNode source, DataFlow::PathNode sink, OgnlInjectionFlowConfig conf +where conf.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "OGNL expression might include input from $@.", + source.getNode(), "this user input" diff --git a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjectionLib.qll b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjectionLib.qll new file mode 100644 index 00000000000..faac234574b --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjectionLib.qll @@ -0,0 +1,109 @@ +import java +import semmle.code.java.dataflow.FlowSources +import DataFlow +import DataFlow::PathGraph + +/** + * A taint-tracking configuration for unvalidated user input that is used in OGNL EL evaluation. + */ +class OgnlInjectionFlowConfig extends TaintTracking::Configuration { + OgnlInjectionFlowConfig() { this = "OgnlInjectionFlowConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof OgnlInjectionSink } + + override predicate isSanitizer(DataFlow::Node node) { + node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType + } + + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + parseCompileExpressionStep(node1, node2) + } +} + +/** The class `org.apache.commons.ognl.Ognl` or `ognl.Ognl`. */ +class TypeOgnl extends Class { + TypeOgnl() { + this.hasQualifiedName("org.apache.commons.ognl", "Ognl") or + this.hasQualifiedName("ognl", "Ognl") + } +} + +/** The interface `org.apache.commons.ognl.Node` or `ognl.Node`. */ +class TypeNode extends Interface { + TypeNode() { + this.hasQualifiedName("org.apache.commons.ognl", "Node") or + this.hasQualifiedName("ognl", "Node") + } +} + +/** The class `com.opensymphony.xwork2.ognl.OgnlUtil`. */ +class TypeOgnlUtil extends Class { + TypeOgnlUtil() { this.hasQualifiedName("com.opensymphony.xwork2.ognl", "OgnlUtil") } +} + +/** + * OGNL sink for OGNL injection vulnerabilities, i.e. 1st argument to `getValue` or `setValue` + * method from `Ognl` or `getValue` or `setValue` method from `Node`. + */ +predicate ognlSinkMethod(Method m, int index) { + ( + m.getDeclaringType() instanceof TypeOgnl and index = 0 + or + m.getDeclaringType().getAnAncestor*() instanceof TypeNode + ) and + ( + m.hasName("getValue") or + m.hasName("setValue") + ) and + index = 0 +} + +/** + * Struts sink for OGNL injection vulnerabilities, i.e. 1st argument to `getValue`, `setValue` or + * `callMethod` method from `OgnlUtil`. + */ +predicate strutsSinkMethod(Method m, int index) { + m.getDeclaringType() instanceof TypeOgnlUtil and + ( + m.hasName("getValue") or + m.hasName("setValue") or + m.hasName("callMethod") + ) and + index = 0 +} + +/** Holds if parameter at index `index` in method `m` is OGNL injection sink. */ +predicate ognlInjectionSinkMethod(Method m, int index) { + ognlSinkMethod(m, index) or + strutsSinkMethod(m, index) +} + +/** A data flow sink for unvalidated user input that is used in OGNL EL evaluation. */ +class OgnlInjectionSink extends DataFlow::ExprNode { + OgnlInjectionSink() { + exists(MethodAccess ma, Method m, int index | + ma.getMethod() = m and + (ma.getArgument(index) = this.getExpr() or ma.getQualifier() = this.getExpr()) and + ognlInjectionSinkMethod(m, index) + ) + } +} + +/** + * Holds if `n1` to `n2` is a dataflow step that converts between `String` and `Object` or `Node`, + * i.e. `Ognl.parseExpression(tainted)` or `Ognl.compileExpression(tainted)`. + */ +predicate parseCompileExpressionStep(ExprNode n1, ExprNode n2) { + exists(MethodAccess ma, Method m, int index | + n1.asExpr() = ma.getArgument(index) and + n2.asExpr() = ma and + ma.getMethod() = m and + m.getDeclaringType() instanceof TypeOgnl + | + m.hasName("parseExpression") and index = 0 + or + m.hasName("compileExpression") and index = 2 + ) +} diff --git a/java/ql/src/experimental/qlpack.yml b/java/ql/src/experimental/qlpack.yml new file mode 100644 index 00000000000..bf76fc1b736 --- /dev/null +++ b/java/ql/src/experimental/qlpack.yml @@ -0,0 +1,4 @@ +name: codeql-java-experimental +version: 0.0.0 +libraryPathDependencies: codeql-java +extractor: java diff --git a/java/ql/test/experimental/qlpack.yml b/java/ql/test/experimental/qlpack.yml new file mode 100644 index 00000000000..4b7a7635a6c --- /dev/null +++ b/java/ql/test/experimental/qlpack.yml @@ -0,0 +1,4 @@ +name: codeql-java-experimental-tests +version: 0.0.0 +libraryPathDependencies: codeql-java-experimental +extractor: java diff --git a/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.expected new file mode 100644 index 00000000000..e74636a2b61 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.expected @@ -0,0 +1,48 @@ +edges +| OgnlInjection.java:11:39:11:63 | expr : String | OgnlInjection.java:13:19:13:22 | tree | +| OgnlInjection.java:11:39:11:63 | expr : String | OgnlInjection.java:14:19:14:22 | tree | +| OgnlInjection.java:11:39:11:63 | expr : String | OgnlInjection.java:16:17:16:27 | (...)... : Object | +| OgnlInjection.java:16:17:16:27 | (...)... : Object | OgnlInjection.java:17:5:17:8 | node | +| OgnlInjection.java:16:17:16:27 | (...)... : Object | OgnlInjection.java:18:5:18:8 | node | +| OgnlInjection.java:21:41:21:65 | expr : String | OgnlInjection.java:23:19:23:22 | tree | +| OgnlInjection.java:21:41:21:65 | expr : String | OgnlInjection.java:24:19:24:22 | tree | +| OgnlInjection.java:21:41:21:65 | expr : String | OgnlInjection.java:26:5:26:8 | tree | +| OgnlInjection.java:21:41:21:65 | expr : String | OgnlInjection.java:27:5:27:8 | tree | +| OgnlInjection.java:30:40:30:64 | expr : String | OgnlInjection.java:31:19:31:22 | expr | +| OgnlInjection.java:30:40:30:64 | expr : String | OgnlInjection.java:32:19:32:22 | expr | +| OgnlInjection.java:35:26:35:50 | expr : String | OgnlInjection.java:37:19:37:22 | expr | +| OgnlInjection.java:35:26:35:50 | expr : String | OgnlInjection.java:38:19:38:22 | expr | +| OgnlInjection.java:35:26:35:50 | expr : String | OgnlInjection.java:39:31:39:34 | expr | +nodes +| OgnlInjection.java:11:39:11:63 | expr : String | semmle.label | expr : String | +| OgnlInjection.java:13:19:13:22 | tree | semmle.label | tree | +| OgnlInjection.java:14:19:14:22 | tree | semmle.label | tree | +| OgnlInjection.java:16:17:16:27 | (...)... : Object | semmle.label | (...)... : Object | +| OgnlInjection.java:17:5:17:8 | node | semmle.label | node | +| OgnlInjection.java:18:5:18:8 | node | semmle.label | node | +| OgnlInjection.java:21:41:21:65 | expr : String | semmle.label | expr : String | +| OgnlInjection.java:23:19:23:22 | tree | semmle.label | tree | +| OgnlInjection.java:24:19:24:22 | tree | semmle.label | tree | +| OgnlInjection.java:26:5:26:8 | tree | semmle.label | tree | +| OgnlInjection.java:27:5:27:8 | tree | semmle.label | tree | +| OgnlInjection.java:30:40:30:64 | expr : String | semmle.label | expr : String | +| OgnlInjection.java:31:19:31:22 | expr | semmle.label | expr | +| OgnlInjection.java:32:19:32:22 | expr | semmle.label | expr | +| OgnlInjection.java:35:26:35:50 | expr : String | semmle.label | expr : String | +| OgnlInjection.java:37:19:37:22 | expr | semmle.label | expr | +| OgnlInjection.java:38:19:38:22 | expr | semmle.label | expr | +| OgnlInjection.java:39:31:39:34 | expr | semmle.label | expr | +#select +| OgnlInjection.java:13:19:13:22 | tree | OgnlInjection.java:11:39:11:63 | expr : String | OgnlInjection.java:13:19:13:22 | tree | OGNL expression might include input from $@. | OgnlInjection.java:11:39:11:63 | expr | this user input | +| OgnlInjection.java:14:19:14:22 | tree | OgnlInjection.java:11:39:11:63 | expr : String | OgnlInjection.java:14:19:14:22 | tree | OGNL expression might include input from $@. | OgnlInjection.java:11:39:11:63 | expr | this user input | +| OgnlInjection.java:17:5:17:8 | node | OgnlInjection.java:11:39:11:63 | expr : String | OgnlInjection.java:17:5:17:8 | node | OGNL expression might include input from $@. | OgnlInjection.java:11:39:11:63 | expr | this user input | +| OgnlInjection.java:18:5:18:8 | node | OgnlInjection.java:11:39:11:63 | expr : String | OgnlInjection.java:18:5:18:8 | node | OGNL expression might include input from $@. | OgnlInjection.java:11:39:11:63 | expr | this user input | +| OgnlInjection.java:23:19:23:22 | tree | OgnlInjection.java:21:41:21:65 | expr : String | OgnlInjection.java:23:19:23:22 | tree | OGNL expression might include input from $@. | OgnlInjection.java:21:41:21:65 | expr | this user input | +| OgnlInjection.java:24:19:24:22 | tree | OgnlInjection.java:21:41:21:65 | expr : String | OgnlInjection.java:24:19:24:22 | tree | OGNL expression might include input from $@. | OgnlInjection.java:21:41:21:65 | expr | this user input | +| OgnlInjection.java:26:5:26:8 | tree | OgnlInjection.java:21:41:21:65 | expr : String | OgnlInjection.java:26:5:26:8 | tree | OGNL expression might include input from $@. | OgnlInjection.java:21:41:21:65 | expr | this user input | +| OgnlInjection.java:27:5:27:8 | tree | OgnlInjection.java:21:41:21:65 | expr : String | OgnlInjection.java:27:5:27:8 | tree | OGNL expression might include input from $@. | OgnlInjection.java:21:41:21:65 | expr | this user input | +| OgnlInjection.java:31:19:31:22 | expr | OgnlInjection.java:30:40:30:64 | expr : String | OgnlInjection.java:31:19:31:22 | expr | OGNL expression might include input from $@. | OgnlInjection.java:30:40:30:64 | expr | this user input | +| OgnlInjection.java:32:19:32:22 | expr | OgnlInjection.java:30:40:30:64 | expr : String | OgnlInjection.java:32:19:32:22 | expr | OGNL expression might include input from $@. | OgnlInjection.java:30:40:30:64 | expr | this user input | +| OgnlInjection.java:37:19:37:22 | expr | OgnlInjection.java:35:26:35:50 | expr : String | OgnlInjection.java:37:19:37:22 | expr | OGNL expression might include input from $@. | OgnlInjection.java:35:26:35:50 | expr | this user input | +| OgnlInjection.java:38:19:38:22 | expr | OgnlInjection.java:35:26:35:50 | expr : String | OgnlInjection.java:38:19:38:22 | expr | OGNL expression might include input from $@. | OgnlInjection.java:35:26:35:50 | expr | this user input | +| OgnlInjection.java:39:31:39:34 | expr | OgnlInjection.java:35:26:35:50 | expr : String | OgnlInjection.java:39:31:39:34 | expr | OGNL expression might include input from $@. | OgnlInjection.java:35:26:35:50 | expr | this user input | diff --git a/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.java b/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.java new file mode 100644 index 00000000000..300583c6fc9 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.java @@ -0,0 +1,41 @@ +import ognl.Node; +import ognl.Ognl; + +import java.util.HashMap; + +import com.opensymphony.xwork2.ognl.OgnlUtil; + +import org.springframework.web.bind.annotation.RequestParam; + +public class OgnlInjection { + public void testOgnlParseExpression(@RequestParam String expr) throws Exception { + Object tree = Ognl.parseExpression(expr); + Ognl.getValue(tree, new HashMap<>(), new Object()); + Ognl.setValue(tree, new HashMap<>(), new Object()); + + Node node = (Node) tree; + node.getValue(null, new Object()); + node.setValue(null, new Object(), new Object()); + } + + public void testOgnlCompileExpression(@RequestParam String expr) throws Exception { + Node tree = Ognl.compileExpression(null, new Object(), expr); + Ognl.getValue(tree, new HashMap<>(), new Object()); + Ognl.setValue(tree, new HashMap<>(), new Object()); + + tree.getValue(null, new Object()); + tree.setValue(null, new Object(), new Object()); + } + + public void testOgnlDirectlyToGetSet(@RequestParam String expr) throws Exception { + Ognl.getValue(expr, new Object()); + Ognl.setValue(expr, new Object(), new Object()); + } + + public void testStruts(@RequestParam String expr) throws Exception { + OgnlUtil ognl = new OgnlUtil(); + ognl.getValue(expr, new HashMap<>(), new Object()); + ognl.setValue(expr, new HashMap<>(), new Object(), new Object()); + new OgnlUtil().callMethod(expr, new HashMap<>(), new Object()); + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.qlref new file mode 100644 index 00000000000..b72d532c765 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-917/OgnlInjection.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-917/options b/java/ql/test/experimental/query-tests/security/CWE-917/options new file mode 100644 index 00000000000..c5767a074fa --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-917/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/ognl-3.2.14:${testdir}/../../../stubs/struts2-core-2.5.22 diff --git a/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/JavaSource.java b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/JavaSource.java new file mode 100644 index 00000000000..0ca2ecb43a7 --- /dev/null +++ b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/JavaSource.java @@ -0,0 +1,3 @@ +package ognl; + +public interface JavaSource {} diff --git a/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/Node.java b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/Node.java new file mode 100644 index 00000000000..56d58f24d07 --- /dev/null +++ b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/Node.java @@ -0,0 +1,6 @@ +package ognl; + +public interface Node extends JavaSource { + public Object getValue(OgnlContext context, Object source) throws OgnlException; + public void setValue(OgnlContext context, Object target, Object value) throws OgnlException; +} diff --git a/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/Ognl.java b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/Ognl.java new file mode 100644 index 00000000000..1aa67646f92 --- /dev/null +++ b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/Ognl.java @@ -0,0 +1,26 @@ +package ognl; + +import java.util.*; + +public abstract class Ognl { + public static Object parseExpression(String expression) throws OgnlException { + return new Object(); + } + + public static Object getValue(Object tree, Map context, Object root) throws OgnlException { + return new Object(); + } + + public static void setValue(Object tree, Object root, Object value) throws OgnlException {} + + public static Node compileExpression(OgnlContext context, Object root, String expression) + throws Exception { + return null; + } + + public static Object getValue(String expression, Object root) throws OgnlException { + return new Object(); + } + + public static void setValue(String expression, Object root, Object value) throws OgnlException {} +} diff --git a/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/OgnlContext.java b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/OgnlContext.java new file mode 100644 index 00000000000..fad33eb8e80 --- /dev/null +++ b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/OgnlContext.java @@ -0,0 +1,71 @@ +package ognl; + +import java.util.*; + +public class OgnlContext extends Object implements Map { + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsKey(Object key) { + return true; + } + + @Override + public boolean containsValue(Object value) { + return true; + } + + @Override + public Object get(Object key) { + return new Object(); + } + + @Override + public Object put(Object key, Object value) { + return new Object(); + } + + @Override + public Object remove(Object key) { + return new Object(); + } + + @Override + public void putAll(Map t) { } + + @Override + public void clear() {} + + @Override + public Set keySet() { + return new HashSet(); + } + + @Override + public Collection values() { + return new HashSet(); + } + + @Override + public Set entrySet() { + return new HashSet(); + } + + @Override + public boolean equals(Object o) { + return true; + } + + @Override + public int hashCode() { + return 0; + } +} \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/OgnlException.java b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/OgnlException.java new file mode 100644 index 00000000000..447515aa58f --- /dev/null +++ b/java/ql/test/experimental/stubs/ognl-3.2.14/ognl/OgnlException.java @@ -0,0 +1,3 @@ +package ognl; + +public class OgnlException extends Exception {} \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/springframework-5.2.3/org/springframework/web/bind/annotation/RequestParam.java b/java/ql/test/experimental/stubs/springframework-5.2.3/org/springframework/web/bind/annotation/RequestParam.java new file mode 100644 index 00000000000..5ae52ad123f --- /dev/null +++ b/java/ql/test/experimental/stubs/springframework-5.2.3/org/springframework/web/bind/annotation/RequestParam.java @@ -0,0 +1,8 @@ +package org.springframework.web.bind.annotation; + +import java.lang.annotation.*; + +@Target(value=ElementType.PARAMETER) +@Retention(value=RetentionPolicy.RUNTIME) +@Documented +public @interface RequestParam { } diff --git a/java/ql/test/experimental/stubs/struts2-core-2.5.22/com/opensymphony/xwork2/ognl/OgnlUtil.java b/java/ql/test/experimental/stubs/struts2-core-2.5.22/com/opensymphony/xwork2/ognl/OgnlUtil.java new file mode 100644 index 00000000000..5b1d031cf21 --- /dev/null +++ b/java/ql/test/experimental/stubs/struts2-core-2.5.22/com/opensymphony/xwork2/ognl/OgnlUtil.java @@ -0,0 +1,16 @@ +package com.opensymphony.xwork2.ognl; + +import java.util.*; +import ognl.OgnlException; + +public class OgnlUtil { + public Object getValue(final String name, final Map context, final Object root) throws OgnlException { + return new Object(); + } + + public void setValue(final String name, final Map context, final Object root, final Object value) throws OgnlException {} + + public Object callMethod(final String name, final Map context, final Object root) throws OgnlException { + return new Object(); + } +} \ No newline at end of file From 40fcd4cbe5030ff53583b55628ac53bba85c5e76 Mon Sep 17 00:00:00 2001 From: Grzegorz Golawski Date: Sun, 19 Apr 2020 20:49:07 +0200 Subject: [PATCH 2/4] Fix references --- .../experimental/Security/CWE/CWE-917/OgnlInjection.qhelp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp index 66d04e41433..55ed5340c11 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp @@ -27,8 +27,7 @@ and validate the expressions before evaluation.

    -
  • Oracle: Java Naming and Directory Interface (JNDI).
  • -
  • Black Hat materials: A Journey from JNDI/LDAP Manipulation to Remote Code Execution Dream Land.
  • -
  • Veracode: Exploiting JNDI Injections in Java.
  • +
  • OGNL library: OGNL library.
  • +
  • Struts security: Proactively protect from OGNL Expression Injections attacks.
  • From 31a2972ecaa4d8aaf35fa99c1c740de107ef512b Mon Sep 17 00:00:00 2001 From: Grzegorz Golawski Date: Mon, 27 Apr 2020 23:32:48 +0200 Subject: [PATCH 3/4] Remove qlpack.yml as these are not needed --- java/ql/src/experimental/qlpack.yml | 4 ---- java/ql/test/experimental/qlpack.yml | 4 ---- .../query-tests/security/CWE-917/OgnlInjection.qlref | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 java/ql/src/experimental/qlpack.yml delete mode 100644 java/ql/test/experimental/qlpack.yml diff --git a/java/ql/src/experimental/qlpack.yml b/java/ql/src/experimental/qlpack.yml deleted file mode 100644 index bf76fc1b736..00000000000 --- a/java/ql/src/experimental/qlpack.yml +++ /dev/null @@ -1,4 +0,0 @@ -name: codeql-java-experimental -version: 0.0.0 -libraryPathDependencies: codeql-java -extractor: java diff --git a/java/ql/test/experimental/qlpack.yml b/java/ql/test/experimental/qlpack.yml deleted file mode 100644 index 4b7a7635a6c..00000000000 --- a/java/ql/test/experimental/qlpack.yml +++ /dev/null @@ -1,4 +0,0 @@ -name: codeql-java-experimental-tests -version: 0.0.0 -libraryPathDependencies: codeql-java-experimental -extractor: java diff --git a/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.qlref index b72d532c765..668f3bf2797 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.qlref +++ b/java/ql/test/experimental/query-tests/security/CWE-917/OgnlInjection.qlref @@ -1 +1 @@ -Security/CWE/CWE-917/OgnlInjection.ql +experimental/Security/CWE/CWE-917/OgnlInjection.ql From aff0e0eb25052f4af981d5c4d6909c781ca1f9a3 Mon Sep 17 00:00:00 2001 From: Grzegorz Golawski Date: Sat, 27 Jun 2020 18:30:36 +0200 Subject: [PATCH 4/4] Cleanup according to review comments. --- .../src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp | 2 +- .../src/experimental/Security/CWE/CWE-917/OgnlInjectionLib.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp index 55ed5340c11..e20d54f1d84 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjection.qhelp @@ -27,7 +27,7 @@ and validate the expressions before evaluation.

    -
  • OGNL library: OGNL library.
  • +
  • OGNL library.
  • Struts security: Proactively protect from OGNL Expression Injections attacks.
  • diff --git a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjectionLib.qll b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjectionLib.qll index faac234574b..569e18a29c3 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjectionLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-917/OgnlInjectionLib.qll @@ -49,7 +49,7 @@ class TypeOgnlUtil extends Class { */ predicate ognlSinkMethod(Method m, int index) { ( - m.getDeclaringType() instanceof TypeOgnl and index = 0 + m.getDeclaringType() instanceof TypeOgnl or m.getDeclaringType().getAnAncestor*() instanceof TypeNode ) and