|
1 | 1 | /** Provides classes to reason about JNDI injection vulnerabilities. */ |
2 | 2 |
|
3 | 3 | import java |
4 | | -import semmle.code.java.dataflow.DataFlow |
5 | | -import semmle.code.java.dataflow.DataFlow2 |
6 | | -import semmle.code.java.dataflow.ExternalFlow |
7 | | -import semmle.code.java.frameworks.Jndi |
8 | | -import semmle.code.java.frameworks.SpringLdap |
| 4 | +private import semmle.code.java.dataflow.DataFlow |
| 5 | +private import semmle.code.java.dataflow.ExternalFlow |
| 6 | +private import semmle.code.java.frameworks.Jndi |
| 7 | +private import semmle.code.java.frameworks.SpringLdap |
9 | 8 |
|
10 | 9 | /** A data flow sink for unvalidated user input that is used in JNDI lookup. */ |
11 | 10 | abstract class JndiInjectionSink extends DataFlow::Node { } |
@@ -48,19 +47,6 @@ private class ConditionedJndiInjectionSink extends JndiInjectionSink, DataFlow:: |
48 | 47 | } |
49 | 48 | } |
50 | 49 |
|
51 | | -/** |
52 | | - * A method that does a JNDI lookup when it receives a `SearchControls` argument with `setReturningObjFlag` = `true` |
53 | | - */ |
54 | | -private class UnsafeSearchControlsSink extends JndiInjectionSink { |
55 | | - UnsafeSearchControlsSink() { |
56 | | - exists(UnsafeSearchControlsConf conf, MethodAccess ma | |
57 | | - conf.hasFlowTo(DataFlow::exprNode(ma.getAnArgument())) |
58 | | - | |
59 | | - this.asExpr() = ma.getArgument(0) |
60 | | - ) |
61 | | - } |
62 | | -} |
63 | | - |
64 | 50 | /** |
65 | 51 | * Tainted value passed to env `Hashtable` as the provider URL by calling |
66 | 52 | * `env.put(Context.PROVIDER_URL, tainted)` or `env.setProperty(Context.PROVIDER_URL, tainted)`. |
@@ -93,10 +79,10 @@ private class DefaultJndiInjectionSinkModel extends SinkModelCsv { |
93 | 79 | [ |
94 | 80 | "javax.naming;Context;true;lookup;;;Argument[0];jndi-injection", |
95 | 81 | "javax.naming;Context;true;lookupLink;;;Argument[0];jndi-injection", |
96 | | - "javax.naming;Context;true;doLookup;;;Argument[0];jndi-injection", |
97 | 82 | "javax.naming;Context;true;rename;;;Argument[0];jndi-injection", |
98 | 83 | "javax.naming;Context;true;list;;;Argument[0];jndi-injection", |
99 | 84 | "javax.naming;Context;true;listBindings;;;Argument[0];jndi-injection", |
| 85 | + "javax.naming;InitialContext;true;doLookup;;;Argument[0];jndi-injection", |
100 | 86 | "javax.management.remote;JMXConnector;true;connect;;;Argument[-1];jndi-injection", |
101 | 87 | "javax.management.remote;JMXConnectorFactory;false;connect;;;Argument[0];jndi-injection", |
102 | 88 | // Spring |
@@ -137,87 +123,6 @@ private class DefaultJndiInjectionSinkModel extends SinkModelCsv { |
137 | 123 | } |
138 | 124 | } |
139 | 125 |
|
140 | | -/** |
141 | | - * Find flows between a `SearchControls` object with `setReturningObjFlag` = `true` |
142 | | - * and an argument of a `LdapOperations.search` or `DirContext.search` call. |
143 | | - */ |
144 | | -private class UnsafeSearchControlsConf extends DataFlow2::Configuration { |
145 | | - UnsafeSearchControlsConf() { this = "UnsafeSearchControlsConf" } |
146 | | - |
147 | | - override predicate isSource(DataFlow2::Node source) { source instanceof UnsafeSearchControls } |
148 | | - |
149 | | - override predicate isSink(DataFlow2::Node sink) { sink instanceof UnsafeSearchControlsArgument } |
150 | | -} |
151 | | - |
152 | | -/** |
153 | | - * An argument of type `SearchControls` of a a `LdapOperations.search` or `DirContext.search` call. |
154 | | - */ |
155 | | -private class UnsafeSearchControlsArgument extends DataFlow2::ExprNode { |
156 | | - UnsafeSearchControlsArgument() { |
157 | | - exists(MethodAccess ma, Method m | |
158 | | - ma.getMethod() = m and |
159 | | - ma.getAnArgument() = this.asExpr() and |
160 | | - this.asExpr().getType() instanceof TypeSearchControls and |
161 | | - m.hasName("search") |
162 | | - | |
163 | | - m.getDeclaringType().getASourceSupertype*() instanceof TypeLdapOperations or |
164 | | - m.getDeclaringType().getASourceSupertype*() instanceof TypeDirContext |
165 | | - ) |
166 | | - } |
167 | | -} |
168 | | - |
169 | | -/** |
170 | | - * A `SearchControls` object with `setReturningObjFlag` = `true`. |
171 | | - */ |
172 | | -private class UnsafeSearchControls extends DataFlow2::ExprNode { |
173 | | - UnsafeSearchControls() { |
174 | | - exists(MethodAccess ma | |
175 | | - ma.getMethod() instanceof SetReturningObjFlagMethod and |
176 | | - ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = true and |
177 | | - this.asExpr() = ma.getQualifier() |
178 | | - ) |
179 | | - or |
180 | | - exists(ConstructorCall cc | |
181 | | - cc.getConstructedType() instanceof TypeSearchControls and |
182 | | - cc.getArgument(4).(CompileTimeConstantExpr).getBooleanValue() = true and |
183 | | - this.asExpr() = cc |
184 | | - ) |
185 | | - } |
186 | | -} |
187 | | - |
188 | | -/** |
189 | | - * The method `SearchControls.setReturningObjFlag`. |
190 | | - */ |
191 | | -private class SetReturningObjFlagMethod extends Method { |
192 | | - SetReturningObjFlagMethod() { |
193 | | - this.getDeclaringType() instanceof TypeSearchControls and |
194 | | - this.hasName("setReturningObjFlag") |
195 | | - } |
196 | | -} |
197 | | - |
198 | | -/** |
199 | | - * The class `javax.naming.directory.SearchControls` |
200 | | - */ |
201 | | -private class TypeSearchControls extends Class { |
202 | | - TypeSearchControls() { this.hasQualifiedName("javax.naming.directory", "SearchControls") } |
203 | | -} |
204 | | - |
205 | | -/** |
206 | | - * The interface `org.springframework.ldap.core.LdapOperations` or |
207 | | - * `org.springframework.ldap.LdapOperations` |
208 | | - */ |
209 | | -private class TypeLdapOperations extends Interface { |
210 | | - TypeLdapOperations() { |
211 | | - this.hasQualifiedName(["org.springframework.ldap.core", "org.springframework.ldap"], |
212 | | - "LdapOperations") |
213 | | - } |
214 | | -} |
215 | | - |
216 | | -/** The class `java.util.Hashtable`. */ |
217 | | -private class TypeHashtable extends Class { |
218 | | - TypeHashtable() { this.getSourceDeclaration().hasQualifiedName("java.util", "Hashtable") } |
219 | | -} |
220 | | - |
221 | 126 | /** A set of additional taint steps to consider when taint tracking JNDI injection related data flows. */ |
222 | 127 | private class DefaultJndiInjectionAdditionalTaintStep extends JndiInjectionAdditionalTaintStep { |
223 | 128 | override predicate step(DataFlow::Node node1, DataFlow::Node node2) { |
@@ -294,3 +199,8 @@ private predicate rmiConnectorStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) |
294 | 199 | n2.asExpr() = cc |
295 | 200 | ) |
296 | 201 | } |
| 202 | + |
| 203 | +/** The class `java.util.Hashtable`. */ |
| 204 | +private class TypeHashtable extends Class { |
| 205 | + TypeHashtable() { this.getSourceDeclaration().hasQualifiedName("java.util", "Hashtable") } |
| 206 | +} |
0 commit comments