CodeQL query to detect JNDI injections

This commit is contained in:
Grzegorz Golawski
2020-04-17 21:45:42 +02:00
parent 86ba03bea8
commit af48bc3e57
16 changed files with 431 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
import javax.naming.Context;
import javax.naming.InitialContext;
public void jndiLookup(HttpServletRequest request) throws NamingException {
String name = request.getParameter("name");
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
env.put(Context.PROVIDER_URL, "rmi://trusted-server:1099");
InitialContext ctx = new InitialContext(env);
// BAD: User input used in lookup
ctx.lookup(name);
// GOOD: The name is validated before being used in lookup
if (isValid(name)) {
ctx.lookup(name);
} else {
// Reject the request
}
}

View File

@@ -0,0 +1,36 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The Java Naming and Directory Interface (JNDI) is a Java API for a directory service that allows
Java software clients to discover and look up data and resources (in the form of Java objects) via
a name. If the name being used to look up the data is controlled by the user, it can point to a
malicious server, which can return an arbitrary object. In the worst case, this can allow remote
code execution.</p>
</overview>
<recommendation>
<p>The general recommendation is to not pass untrusted data to the <code>InitialContext.lookup
</code> method. If the name being used to look up the object must be provided by the user, make
sure that it's not in the form of an absolute URL or that it's the URL pointing to a trused server.
</p>
</recommendation>
<example>
<p>In the following examples, the code accepts a name from the user, which it uses to look up an
object.</p>
<p>In the first example, the user provided name is used to look up an object.</p>
<p>The second example validates the name before using it to look up an object.</p>
<sample src="JndiInjection.java" />
</example>
<references>
<li>Oracle: <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jndi/">Java Naming and Directory Interface (JNDI)</a>.</li>
<li>Black Hat materials: <a href="https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE-wp.pdf">A Journey from JNDI/LDAP Manipulation to Remote Code Execution Dream Land</a>.</li>
<li>Veracode: <a href="https://www.veracode.com/blog/research/exploiting-jndi-injections-java">Exploiting JNDI Injections in Java</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,21 @@
/**
* @name JNDI lookup with user-controlled name
* @description Doing a JNDI lookup with user-controlled name can lead to download an untrusted
* object and to execution of arbitrary code.
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/jndi-injection
* @tags security
* external/cwe/cwe-074
*/
import java
import semmle.code.java.dataflow.FlowSources
import JndiInjectionLib
import DataFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, JndiInjectionFlowConfig conf
where conf.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "JNDI lookup might include name from $@.", source.getNode(),
"this user input"

View File

@@ -0,0 +1,91 @@
import java
import semmle.code.java.dataflow.FlowSources
import DataFlow
import experimental.semmle.code.java.frameworks.Jndi
import experimental.semmle.code.java.frameworks.spring.SpringJndi
import experimental.semmle.code.java.frameworks.Shiro
/**
* A taint-tracking configuration for unvalidated user input that is used in JNDI lookup.
*/
class JndiInjectionFlowConfig extends TaintTracking::Configuration {
JndiInjectionFlowConfig() { this = "JndiInjectionFlowConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof JndiInjectionSink }
override predicate isSanitizer(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
compositeNameStep(node1, node2)
}
}
/**
* JNDI sink for JNDI injection vulnerabilities, i.e. 1st argument to `lookup`, `lookupLink`,
* `doLookup`, `rename`, `list` or `listBindings` method from `InitialContext`.
*/
predicate jndiSinkMethod(Method m, int index) {
m.getDeclaringType().getAnAncestor() instanceof TypeInitialContext and
(
m.hasName("lookup") or
m.hasName("lookupLink") or
m.hasName("doLookup") or
m.hasName("rename") or
m.hasName("list") or
m.hasName("listBindings")
) and
index = 0
}
/**
* Spring sink for JNDI injection vulnerabilities, i.e. 1st argument to `lookup` method from
* Spring's `JndiTemplate`.
*/
predicate springSinkMethod(Method m, int index) {
m.getDeclaringType() instanceof TypeSpringJndiTemplate and
m.hasName("lookup") and
index = 0
}
/**
* Apache Shiro sink for JNDI injection vulnerabilities, i.e. 1st argument to `lookup` method from
* Shiro's `JndiTemplate`.
*/
predicate shiroSinkMethod(Method m, int index) {
m.getDeclaringType() instanceof TypeShiroJndiTemplate and
m.hasName("lookup") and
index = 0
}
/** Holds if parameter at index `index` in method `m` is JNDI injection sink. */
predicate jndiInjectionSinkMethod(Method m, int index) {
jndiSinkMethod(m, index) or
springSinkMethod(m, index) or
shiroSinkMethod(m, index)
}
/** A data flow sink for unvalidated user input that is used in JNDI lookup. */
class JndiInjectionSink extends DataFlow::ExprNode {
JndiInjectionSink() {
exists(MethodAccess ma, Method m, int index |
ma.getMethod() = m and
ma.getArgument(index) = this.getExpr() and
jndiInjectionSinkMethod(m, index)
)
}
}
/**
* Holds if `n1` to `n2` is a dataflow step that converts between `String` and `CompositeName`,
* i.e. `new CompositeName(tainted)`.
*/
predicate compositeNameStep(ExprNode n1, ExprNode n2) {
exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeCompositeName |
n1.asExpr() = cc.getAnArgument() and
n2.asExpr() = cc
)
}

View File

@@ -0,0 +1,4 @@
name: codeql-java-experimental
version: 0.0.0
libraryPathDependencies: codeql-java
extractor: java

View File

@@ -0,0 +1,11 @@
import java
/** The class `javax.naming.InitialContext`. */
class TypeInitialContext extends Class {
TypeInitialContext() { this.hasQualifiedName("javax.naming", "InitialContext") }
}
/** The class `javax.naming.CompositeName`. */
class TypeCompositeName extends Class {
TypeCompositeName() { this.hasQualifiedName("javax.naming", "CompositeName") }
}

View File

@@ -0,0 +1,6 @@
import java
/** The class `org.apache.shiro.jndi.JndiTemplate`. */
class TypeShiroJndiTemplate extends Class {
TypeShiroJndiTemplate() { this.hasQualifiedName("org.apache.shiro.jndi", "JndiTemplate") }
}

View File

@@ -0,0 +1,6 @@
import java
/** The class `org.springframework.jndi.JndiTemplate`. */
class TypeSpringJndiTemplate extends Class {
TypeSpringJndiTemplate() { this.hasQualifiedName("org.springframework.jndi", "JndiTemplate") }
}

View File

@@ -0,0 +1,4 @@
name: codeql-java-experimental-tests
version: 0.0.0
libraryPathDependencies: codeql-java-experimental
extractor: java

View File

@@ -0,0 +1,116 @@
edges
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:16:16:16:22 | nameStr |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:17:20:17:26 | nameStr |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:18:29:18:35 | nameStr |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:19:16:19:22 | nameStr |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:20:14:20:20 | nameStr |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:21:22:21:28 | nameStr |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:23:16:23:19 | name |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:24:20:24:23 | name |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:25:29:25:32 | name |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:26:16:26:19 | name |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:27:14:27:17 | name |
| JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:28:22:28:25 | name |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:35:16:35:22 | nameStr |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:36:20:36:26 | nameStr |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:37:16:37:22 | nameStr |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:38:14:38:20 | nameStr |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:39:22:39:28 | nameStr |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:41:16:41:19 | name |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:42:20:42:23 | name |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:43:16:43:19 | name |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:44:14:44:17 | name |
| JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:45:22:45:25 | name |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:52:16:52:22 | nameStr |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:53:20:53:26 | nameStr |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:54:16:54:22 | nameStr |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:55:14:55:20 | nameStr |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:56:22:56:28 | nameStr |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:58:16:58:19 | name |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:59:20:59:23 | name |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:60:16:60:19 | name |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:61:14:61:17 | name |
| JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:62:22:62:25 | name |
| JndiInjection.java:65:42:65:69 | nameStr : String | JndiInjection.java:68:16:68:22 | nameStr |
| JndiInjection.java:65:42:65:69 | nameStr : String | JndiInjection.java:69:16:69:22 | nameStr |
| JndiInjection.java:72:41:72:68 | nameStr : String | JndiInjection.java:75:16:75:22 | nameStr |
| JndiInjection.java:72:41:72:68 | nameStr : String | JndiInjection.java:76:16:76:22 | nameStr |
nodes
| JndiInjection.java:12:38:12:65 | nameStr : String | semmle.label | nameStr : String |
| JndiInjection.java:16:16:16:22 | nameStr | semmle.label | nameStr |
| JndiInjection.java:17:20:17:26 | nameStr | semmle.label | nameStr |
| JndiInjection.java:18:29:18:35 | nameStr | semmle.label | nameStr |
| JndiInjection.java:19:16:19:22 | nameStr | semmle.label | nameStr |
| JndiInjection.java:20:14:20:20 | nameStr | semmle.label | nameStr |
| JndiInjection.java:21:22:21:28 | nameStr | semmle.label | nameStr |
| JndiInjection.java:23:16:23:19 | name | semmle.label | name |
| JndiInjection.java:24:20:24:23 | name | semmle.label | name |
| JndiInjection.java:25:29:25:32 | name | semmle.label | name |
| JndiInjection.java:26:16:26:19 | name | semmle.label | name |
| JndiInjection.java:27:14:27:17 | name | semmle.label | name |
| JndiInjection.java:28:22:28:25 | name | semmle.label | name |
| JndiInjection.java:31:41:31:68 | nameStr : String | semmle.label | nameStr : String |
| JndiInjection.java:35:16:35:22 | nameStr | semmle.label | nameStr |
| JndiInjection.java:36:20:36:26 | nameStr | semmle.label | nameStr |
| JndiInjection.java:37:16:37:22 | nameStr | semmle.label | nameStr |
| JndiInjection.java:38:14:38:20 | nameStr | semmle.label | nameStr |
| JndiInjection.java:39:22:39:28 | nameStr | semmle.label | nameStr |
| JndiInjection.java:41:16:41:19 | name | semmle.label | name |
| JndiInjection.java:42:20:42:23 | name | semmle.label | name |
| JndiInjection.java:43:16:43:19 | name | semmle.label | name |
| JndiInjection.java:44:14:44:17 | name | semmle.label | name |
| JndiInjection.java:45:22:45:25 | name | semmle.label | name |
| JndiInjection.java:48:42:48:69 | nameStr : String | semmle.label | nameStr : String |
| JndiInjection.java:52:16:52:22 | nameStr | semmle.label | nameStr |
| JndiInjection.java:53:20:53:26 | nameStr | semmle.label | nameStr |
| JndiInjection.java:54:16:54:22 | nameStr | semmle.label | nameStr |
| JndiInjection.java:55:14:55:20 | nameStr | semmle.label | nameStr |
| JndiInjection.java:56:22:56:28 | nameStr | semmle.label | nameStr |
| JndiInjection.java:58:16:58:19 | name | semmle.label | name |
| JndiInjection.java:59:20:59:23 | name | semmle.label | name |
| JndiInjection.java:60:16:60:19 | name | semmle.label | name |
| JndiInjection.java:61:14:61:17 | name | semmle.label | name |
| JndiInjection.java:62:22:62:25 | name | semmle.label | name |
| JndiInjection.java:65:42:65:69 | nameStr : String | semmle.label | nameStr : String |
| JndiInjection.java:68:16:68:22 | nameStr | semmle.label | nameStr |
| JndiInjection.java:69:16:69:22 | nameStr | semmle.label | nameStr |
| JndiInjection.java:72:41:72:68 | nameStr : String | semmle.label | nameStr : String |
| JndiInjection.java:75:16:75:22 | nameStr | semmle.label | nameStr |
| JndiInjection.java:76:16:76:22 | nameStr | semmle.label | nameStr |
#select
| JndiInjection.java:16:16:16:22 | nameStr | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:16:16:16:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:17:20:17:26 | nameStr | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:17:20:17:26 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:18:29:18:35 | nameStr | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:18:29:18:35 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:19:16:19:22 | nameStr | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:19:16:19:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:20:14:20:20 | nameStr | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:20:14:20:20 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:21:22:21:28 | nameStr | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:21:22:21:28 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:23:16:23:19 | name | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:23:16:23:19 | name | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:24:20:24:23 | name | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:24:20:24:23 | name | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:25:29:25:32 | name | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:25:29:25:32 | name | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:26:16:26:19 | name | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:26:16:26:19 | name | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:27:14:27:17 | name | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:27:14:27:17 | name | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:28:22:28:25 | name | JndiInjection.java:12:38:12:65 | nameStr : String | JndiInjection.java:28:22:28:25 | name | JNDI lookup might include name from $@. | JndiInjection.java:12:38:12:65 | nameStr | this user input |
| JndiInjection.java:35:16:35:22 | nameStr | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:35:16:35:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:36:20:36:26 | nameStr | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:36:20:36:26 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:37:16:37:22 | nameStr | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:37:16:37:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:38:14:38:20 | nameStr | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:38:14:38:20 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:39:22:39:28 | nameStr | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:39:22:39:28 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:41:16:41:19 | name | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:41:16:41:19 | name | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:42:20:42:23 | name | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:42:20:42:23 | name | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:43:16:43:19 | name | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:43:16:43:19 | name | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:44:14:44:17 | name | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:44:14:44:17 | name | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:45:22:45:25 | name | JndiInjection.java:31:41:31:68 | nameStr : String | JndiInjection.java:45:22:45:25 | name | JNDI lookup might include name from $@. | JndiInjection.java:31:41:31:68 | nameStr | this user input |
| JndiInjection.java:52:16:52:22 | nameStr | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:52:16:52:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:53:20:53:26 | nameStr | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:53:20:53:26 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:54:16:54:22 | nameStr | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:54:16:54:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:55:14:55:20 | nameStr | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:55:14:55:20 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:56:22:56:28 | nameStr | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:56:22:56:28 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:58:16:58:19 | name | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:58:16:58:19 | name | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:59:20:59:23 | name | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:59:20:59:23 | name | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:60:16:60:19 | name | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:60:16:60:19 | name | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:61:14:61:17 | name | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:61:14:61:17 | name | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:62:22:62:25 | name | JndiInjection.java:48:42:48:69 | nameStr : String | JndiInjection.java:62:22:62:25 | name | JNDI lookup might include name from $@. | JndiInjection.java:48:42:48:69 | nameStr | this user input |
| JndiInjection.java:68:16:68:22 | nameStr | JndiInjection.java:65:42:65:69 | nameStr : String | JndiInjection.java:68:16:68:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:65:42:65:69 | nameStr | this user input |
| JndiInjection.java:69:16:69:22 | nameStr | JndiInjection.java:65:42:65:69 | nameStr : String | JndiInjection.java:69:16:69:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:65:42:65:69 | nameStr | this user input |
| JndiInjection.java:75:16:75:22 | nameStr | JndiInjection.java:72:41:72:68 | nameStr : String | JndiInjection.java:75:16:75:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:72:41:72:68 | nameStr | this user input |
| JndiInjection.java:76:16:76:22 | nameStr | JndiInjection.java:72:41:72:68 | nameStr : String | JndiInjection.java:76:16:76:22 | nameStr | JNDI lookup might include name from $@. | JndiInjection.java:72:41:72:68 | nameStr | this user input |

View File

@@ -0,0 +1,78 @@
import javax.naming.CompositeName;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
import javax.naming.ldap.InitialLdapContext;
import org.springframework.jndi.JndiTemplate;
import org.springframework.web.bind.annotation.RequestParam;
public class JndiInjection {
public void testInitialContextBad1(@RequestParam String nameStr) throws NamingException {
Name name = new CompositeName(nameStr);
InitialContext ctx = new InitialContext();
ctx.lookup(nameStr);
ctx.lookupLink(nameStr);
InitialContext.doLookup(nameStr);
ctx.rename(nameStr, "");
ctx.list(nameStr);
ctx.listBindings(nameStr);
ctx.lookup(name);
ctx.lookupLink(name);
InitialContext.doLookup(name);
ctx.rename(name, null);
ctx.list(name);
ctx.listBindings(name);
}
public void testInitialDirContextBad1(@RequestParam String nameStr) throws NamingException {
Name name = new CompositeName(nameStr);
InitialDirContext ctx = new InitialDirContext();
ctx.lookup(nameStr);
ctx.lookupLink(nameStr);
ctx.rename(nameStr, "");
ctx.list(nameStr);
ctx.listBindings(nameStr);
ctx.lookup(name);
ctx.lookupLink(name);
ctx.rename(name, null);
ctx.list(name);
ctx.listBindings(name);
}
public void testInitialLdapContextBad1(@RequestParam String nameStr) throws NamingException {
Name name = new CompositeName(nameStr);
InitialLdapContext ctx = new InitialLdapContext();
ctx.lookup(nameStr);
ctx.lookupLink(nameStr);
ctx.rename(nameStr, "");
ctx.list(nameStr);
ctx.listBindings(nameStr);
ctx.lookup(name);
ctx.lookupLink(name);
ctx.rename(name, null);
ctx.list(name);
ctx.listBindings(name);
}
public void testSpringJndiTemplateBad1(@RequestParam String nameStr) throws NamingException {
JndiTemplate ctx = new JndiTemplate();
ctx.lookup(nameStr);
ctx.lookup(nameStr, null);
}
public void testShiroJndiTemplateBad1(@RequestParam String nameStr) throws NamingException {
org.apache.shiro.jndi.JndiTemplate ctx = new org.apache.shiro.jndi.JndiTemplate();
ctx.lookup(nameStr);
ctx.lookup(nameStr, null);
}
}

View File

@@ -0,0 +1 @@
Security/CWE/CWE-074/JndiInjection.ql

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/shiro-core-1.5.2

View File

@@ -0,0 +1,13 @@
package org.apache.shiro.jndi;
import javax.naming.NamingException;
public class JndiTemplate {
public Object lookup(final String name) throws NamingException {
return new Object();
}
public Object lookup(String name, Class requiredType) throws NamingException {
return new Object();
}
}

View File

@@ -0,0 +1,14 @@
package org.springframework.jndi;
import javax.naming.NamingException;
public class JndiTemplate {
public Object lookup(final String name) throws NamingException {
return new Object();
}
@SuppressWarnings("unchecked")
public <T> T lookup(String name, Class<T> requiredType) throws NamingException {
return (T) new Object();
}
}

View File

@@ -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 { }