Merge pull request #12458 from egregius313/egregius313/promote-insecure-ldap-authentication

Java: Promote LDAP Authentication Query
This commit is contained in:
Edward Minnix III
2023-03-28 10:39:17 -04:00
committed by GitHub
16 changed files with 330 additions and 390 deletions

View File

@@ -0,0 +1,128 @@
/** Provides classes to reason about insecure LDAP authentication. */
import java
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.frameworks.Networking
private import semmle.code.java.frameworks.Jndi
/**
* An expression that represents an insecure (non-SSL, non-private) LDAP URL.
*/
class InsecureLdapUrl extends Expr {
InsecureLdapUrl() {
this instanceof InsecureLdapUrlLiteral
or
// Concatentation of insecure protcol and non-private host:
// protocol + host + ...
exists(AddExpr e, CompileTimeConstantExpr protocol, Expr rest, Expr host |
e = this and
protocol = e.getLeftOperand() and
rest = e.getRightOperand() and
if rest instanceof AddExpr then host = rest.(AddExpr).getLeftOperand() else host = rest
|
protocol.getStringValue() = "ldap://" and
not exists(string hostString | hostString = getHostname(host) |
hostString.length() = 0 or // Empty host is loopback address
hostString instanceof PrivateHostName
)
)
}
}
/**
* A sink representing the construction of a `DirContextEnvironment`.
*/
class InsecureLdapUrlSink extends DataFlow::Node {
InsecureLdapUrlSink() {
exists(ConstructorCall cc |
cc.getConstructedType().getAnAncestor() instanceof TypeDirContext and
this.asExpr() = cc.getArgument(0)
)
}
}
/**
* Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`.
*/
predicate isBasicAuthEnv(MethodAccess ma) {
hasFieldValueEnv(ma, "java.naming.security.authentication", "simple") or
hasFieldNameEnv(ma, "SECURITY_AUTHENTICATION", "simple")
}
/**
* Holds if `ma` sets `java.naming.security.protocol` (also known as `Context.SECURITY_PROTOCOL`) to `ssl` in some `Hashtable`.
*/
predicate isSslEnv(MethodAccess ma) {
hasFieldValueEnv(ma, "java.naming.security.protocol", "ssl") or
hasFieldNameEnv(ma, "SECURITY_PROTOCOL", "ssl")
}
/**
* Holds if `ma` writes the `java.naming.provider.url` (also known as `Context.PROVIDER_URL`) key of a `Hashtable`.
*/
predicate isProviderUrlSetter(MethodAccess ma) {
ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and
ma.getMethod().hasName(["put", "setProperty"]) and
(
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "java.naming.provider.url"
or
exists(Field f |
ma.getArgument(0) = f.getAnAccess() and
f.hasName("PROVIDER_URL") and
f.getDeclaringType() instanceof TypeNamingContext
)
)
}
/**
* An insecure (non-SSL, non-private) LDAP URL string literal.
*/
private class InsecureLdapUrlLiteral extends StringLiteral {
InsecureLdapUrlLiteral() {
// Match connection strings with the LDAP protocol and without private IP addresses to reduce false positives.
exists(string s | this.getValue() = s |
s.regexpMatch("(?i)ldap://[\\[a-zA-Z0-9].*") and
not s.substring(7, s.length()) instanceof PrivateHostName
)
}
}
/** The class `java.util.Hashtable`. */
private class TypeHashtable extends Class {
TypeHashtable() { this.getSourceDeclaration().hasQualifiedName("java.util", "Hashtable") }
}
/** Get the string value of an expression representing a hostname. */
private string getHostname(Expr expr) {
result = expr.(CompileTimeConstantExpr).getStringValue() or
result =
expr.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue()
}
/**
* Holds if `ma` sets `fieldValue` to `envValue` in some `Hashtable`.
*/
bindingset[fieldValue, envValue]
private predicate hasFieldValueEnv(MethodAccess ma, string fieldValue, string envValue) {
// environment.put("java.naming.security.authentication", "simple")
ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and
ma.getMethod().hasName(["put", "setProperty"]) and
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = fieldValue and
ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue
}
/**
* Holds if `ma` sets attribute name `fieldName` to `envValue` in some `Hashtable`.
*/
bindingset[fieldName, envValue]
private predicate hasFieldNameEnv(MethodAccess ma, string fieldName, string envValue) {
// environment.put(Context.SECURITY_AUTHENTICATION, "simple")
ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and
ma.getMethod().hasName(["put", "setProperty"]) and
exists(Field f |
ma.getArgument(0) = f.getAnAccess() and
f.hasName(fieldName) and
f.getDeclaringType() instanceof TypeNamingContext
) and
ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue
}

View File

@@ -0,0 +1,59 @@
/** Provides dataflow configurations to reason about insecure LDAP authentication. */
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.Jndi
import semmle.code.java.security.InsecureLdapAuth
/**
* A taint-tracking configuration for `ldap://` URL in LDAP authentication.
*/
module InsecureLdapUrlConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof InsecureLdapUrl }
predicate isSink(DataFlow::Node sink) { sink instanceof InsecureLdapUrlSink }
/** Method call of `env.put()`. */
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(MethodAccess ma |
pred.asExpr() = ma.getArgument(1) and
isProviderUrlSetter(ma) and
succ.asExpr() = ma.getQualifier()
)
}
}
module InsecureLdapUrlFlow = TaintTracking::Global<InsecureLdapUrlConfig>;
/**
* A taint-tracking configuration for `simple` basic-authentication in LDAP configuration.
*/
private module BasicAuthConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
exists(MethodAccess ma |
isBasicAuthEnv(ma) and
ma.getQualifier() = src.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr()
)
}
predicate isSink(DataFlow::Node sink) { sink instanceof InsecureLdapUrlSink }
}
module BasicAuthFlow = DataFlow::Global<BasicAuthConfig>;
/**
* A taint-tracking configuration for `ssl` configuration in LDAP authentication.
*/
private module RequiresSslConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
exists(MethodAccess ma |
isSslEnv(ma) and
ma.getQualifier() = src.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr()
)
}
predicate isSink(DataFlow::Node sink) { sink instanceof InsecureLdapUrlSink }
}
module RequiresSslFlow = DataFlow::Global<RequiresSslConfig>;

View File

@@ -0,0 +1,51 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
When using the Java LDAP API to perform LDAPv3-style extended operations
and controls, a context with connection properties including user
credentials is started. Transmission of LDAP credentials in cleartext
allows remote attackers to obtain sensitive information by sniffing the
network.
</p>
</overview>
<recommendation>
<p>
Use the <code>ldaps://</code> protocol to send credentials through SSL or
use SASL authentication.
</p>
</recommendation>
<example>
<p>
In the following (bad) example, a <code>ldap://</code> URL is used and
credentials will be sent in plaintext.
</p>
<sample src="LdapAuthUseLdap.java"/>
<p>
In the following (good) example, a <code>ldaps://</code> URL is used so
credentials will be encrypted with SSL.
</p>
<sample src="LdapAuthUseLdaps.java"/>
<p>
In the following (good) example, a <code>ldap://</code> URL is used, but
SASL authentication is enabled so that the credentials will be encrypted.
</p>
<sample src="LdapEnableSasl.java"/>
</example>
<references>
<li>
Oracle:
<a href="https://docs.oracle.com/javase/jndi/tutorial/ldap/misc/url.html">LDAP and LDAPS URLs</a>
</li>
<li>
Oracle:
<a href="https://docs.oracle.com/javase/tutorial/jndi/ldap/simple.html">Simple authentication</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,25 @@
/**
* @name Insecure LDAP authentication
* @description LDAP authentication with credentials sent in cleartext makes sensitive information vulnerable to remote attackers
* @kind path-problem
* @problem.severity warning
* @security-severity 8.8
* @precision medium
* @id java/insecure-ldap-auth
* @tags security
* experimental
* external/cwe/cwe-522
* external/cwe/cwe-319
*/
import java
import semmle.code.java.security.InsecureLdapAuthQuery
import InsecureLdapUrlFlow::PathGraph
from InsecureLdapUrlFlow::PathNode source, InsecureLdapUrlFlow::PathNode sink
where
InsecureLdapUrlFlow::flowPath(source, sink) and
BasicAuthFlow::flowTo(sink.getNode()) and
not RequiresSslFlow::flowTo(sink.getNode())
select sink.getNode(), source, sink, "Insecure LDAP authentication from $@.", source.getNode(),
"LDAP connection string"

View File

@@ -0,0 +1,9 @@
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);

View File

@@ -0,0 +1,9 @@
String ldapUrl = "ldaps://ad.your-server.com:636";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);

View File

@@ -0,0 +1,9 @@
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* The query `java/insecure-ldap-auth` has been promoted from experimental to the main query pack. This query detects transmission of cleartext credentials in LDAP authentication. Insecure LDAP authentication causes sensitive information to be vulnerable to remote attackers. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/4854)

View File

@@ -1,24 +0,0 @@
public class InsecureLdapAuth {
/** LDAP authentication */
public DirContext ldapAuth(String ldapUserName, String password) {
{
// BAD: LDAP authentication in cleartext
String ldapUrl = "ldap://ad.your-server.com:389";
}
{
// GOOD: LDAPS authentication over SSL
String ldapUrl = "ldaps://ad.your-server.com:636";
}
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);
return dirContext;
}
}

View File

@@ -1,27 +0,0 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>When using the Java LDAP API to perform LDAPv3-style extended operations and controls, a context with connection properties including user credentials is started. Transmission of LDAP credentials in cleartext allows remote attackers to obtain sensitive information by sniffing the network.</p>
</overview>
<recommendation>
<p>Use LDAPS to send credentials through SSL or use SASL authentication.</p>
</recommendation>
<example>
<p>The following example shows two ways of using LDAP authentication. In the 'BAD' case, the credentials are transmitted in cleartext. In the 'GOOD' case, the credentials are transmitted over SSL.</p>
<sample src="InsecureLdapAuth.java" />
</example>
<references>
<li>
Oracle:
<a href="https://docs.oracle.com/javase/jndi/tutorial/ldap/misc/url.html">LDAP and LDAPS URLs</a>
</li>
<li>
Oracle:
<a href="https://docs.oracle.com/javase/tutorial/jndi/ldap/simple.html">Simple authentication</a>
</li>
</references>
</qhelp>

View File

@@ -1,211 +0,0 @@
/**
* @name Insecure LDAP authentication
* @description LDAP authentication with credentials sent in cleartext.
* @kind path-problem
* @problem.severity warning
* @precision medium
* @id java/insecure-ldap-auth
* @tags security
* experimental
* external/cwe/cwe-522
* external/cwe/cwe-319
*/
import java
import DataFlow
import semmle.code.java.frameworks.Jndi
import semmle.code.java.frameworks.Networking
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
/**
* Insecure (non-SSL, non-private) LDAP URL string literal.
*/
class InsecureLdapUrlLiteral extends StringLiteral {
InsecureLdapUrlLiteral() {
// Match connection strings with the LDAP protocol and without private IP addresses to reduce false positives.
exists(string s | this.getValue() = s |
s.regexpMatch("(?i)ldap://[\\[a-zA-Z0-9].*") and
not s.substring(7, s.length()) instanceof PrivateHostName
)
}
}
/** The class `java.util.Hashtable`. */
class TypeHashtable extends Class {
TypeHashtable() { this.getSourceDeclaration().hasQualifiedName("java.util", "Hashtable") }
}
/**
* Holds if a non-private LDAP string is concatenated from both protocol and host.
*/
predicate concatInsecureLdapString(Expr protocol, Expr host) {
protocol.(CompileTimeConstantExpr).getStringValue() = "ldap://" and
not exists(string hostString |
hostString = host.(CompileTimeConstantExpr).getStringValue() or
hostString =
host.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue()
|
hostString.length() = 0 or // Empty host is loopback address
hostString instanceof PrivateHostName
)
}
/** Gets the leftmost operand in a concatenated string */
Expr getLeftmostConcatOperand(Expr expr) {
if expr instanceof AddExpr
then result = getLeftmostConcatOperand(expr.(AddExpr).getLeftOperand())
else result = expr
}
/**
* String concatenated with `InsecureLdapUrlLiteral`.
*/
class InsecureLdapUrl extends Expr {
InsecureLdapUrl() {
this instanceof InsecureLdapUrlLiteral
or
concatInsecureLdapString(this.(AddExpr).getLeftOperand(),
getLeftmostConcatOperand(this.(AddExpr).getRightOperand()))
}
}
/**
* Holds if `ma` writes the `java.naming.provider.url` (also known as `Context.PROVIDER_URL`) key of a `Hashtable`.
*/
predicate isProviderUrlSetter(MethodAccess ma) {
ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and
ma.getMethod().hasName(["put", "setProperty"]) and
(
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "java.naming.provider.url"
or
exists(Field f |
ma.getArgument(0) = f.getAnAccess() and
f.hasName("PROVIDER_URL") and
f.getDeclaringType() instanceof TypeNamingContext
)
)
}
/**
* Holds if `ma` sets `fieldValue` to `envValue` in some `Hashtable`.
*/
bindingset[fieldValue, envValue]
predicate hasFieldValueEnv(MethodAccess ma, string fieldValue, string envValue) {
// environment.put("java.naming.security.authentication", "simple")
ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and
ma.getMethod().hasName(["put", "setProperty"]) and
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = fieldValue and
ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue
}
/**
* Holds if `ma` sets attribute name `fieldName` to `envValue` in some `Hashtable`.
*/
bindingset[fieldName, envValue]
predicate hasFieldNameEnv(MethodAccess ma, string fieldName, string envValue) {
// environment.put(Context.SECURITY_AUTHENTICATION, "simple")
ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and
ma.getMethod().hasName(["put", "setProperty"]) and
exists(Field f |
ma.getArgument(0) = f.getAnAccess() and
f.hasName(fieldName) and
f.getDeclaringType() instanceof TypeNamingContext
) and
ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue
}
/**
* Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`.
*/
predicate isBasicAuthEnv(MethodAccess ma) {
hasFieldValueEnv(ma, "java.naming.security.authentication", "simple") or
hasFieldNameEnv(ma, "SECURITY_AUTHENTICATION", "simple")
}
/**
* Holds if `ma` sets `java.naming.security.protocol` (also known as `Context.SECURITY_PROTOCOL`) to `ssl` in some `Hashtable`.
*/
predicate isSslEnv(MethodAccess ma) {
hasFieldValueEnv(ma, "java.naming.security.protocol", "ssl") or
hasFieldNameEnv(ma, "SECURITY_PROTOCOL", "ssl")
}
/**
* A taint-tracking configuration for `ldap://` URL in LDAP authentication.
*/
class InsecureUrlFlowConfig extends TaintTracking::Configuration {
InsecureUrlFlowConfig() { this = "InsecureLdapAuth:InsecureUrlFlowConfig" }
/** Source of `ldap://` connection string. */
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof InsecureLdapUrl }
/** Sink of directory context creation. */
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc |
cc.getConstructedType().getAnAncestor() instanceof TypeDirContext and
sink.asExpr() = cc.getArgument(0)
)
}
/** Method call of `env.put()`. */
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(MethodAccess ma |
pred.asExpr() = ma.getArgument(1) and
isProviderUrlSetter(ma) and
succ.asExpr() = ma.getQualifier()
)
}
}
/**
* A taint-tracking configuration for `simple` basic-authentication in LDAP configuration.
*/
class BasicAuthFlowConfig extends DataFlow::Configuration {
BasicAuthFlowConfig() { this = "InsecureLdapAuth:BasicAuthFlowConfig" }
/** Source of `simple` configuration. */
override predicate isSource(DataFlow::Node src) {
exists(MethodAccess ma |
isBasicAuthEnv(ma) and ma.getQualifier() = src.(PostUpdateNode).getPreUpdateNode().asExpr()
)
}
/** Sink of directory context creation. */
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc |
cc.getConstructedType().getAnAncestor() instanceof TypeDirContext and
sink.asExpr() = cc.getArgument(0)
)
}
}
/**
* A taint-tracking configuration for `ssl` configuration in LDAP authentication.
*/
class SslFlowConfig extends DataFlow::Configuration {
SslFlowConfig() { this = "InsecureLdapAuth:SSLFlowConfig" }
/** Source of `ssl` configuration. */
override predicate isSource(DataFlow::Node src) {
exists(MethodAccess ma |
isSslEnv(ma) and ma.getQualifier() = src.(PostUpdateNode).getPreUpdateNode().asExpr()
)
}
/** Sink of directory context creation. */
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc |
cc.getConstructedType().getAnAncestor() instanceof TypeDirContext and
sink.asExpr() = cc.getArgument(0)
)
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, InsecureUrlFlowConfig config
where
config.hasFlowPath(source, sink) and
exists(BasicAuthFlowConfig bc | bc.hasFlowTo(sink.getNode())) and
not exists(SslFlowConfig sc | sc.hasFlowTo(sink.getNode()))
select sink.getNode(), source, sink, "Insecure LDAP authentication from $@.", source.getNode(),
"LDAP connection string"

View File

@@ -1,111 +0,0 @@
edges
| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl : String |
| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:20:49:20:59 | environment |
| InsecureLdapAuth.java:15:3:15:13 | environment [post update] [<map.value>] : String | InsecureLdapAuth.java:20:49:20:59 | environment |
| InsecureLdapAuth.java:15:41:15:47 | ldapUrl : String | InsecureLdapAuth.java:15:3:15:13 | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:17:3:17:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:20:49:20:59 | environment |
| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl : String |
| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:34:49:34:59 | environment |
| InsecureLdapAuth.java:29:3:29:13 | environment [post update] [<map.value>] : String | InsecureLdapAuth.java:34:49:34:59 | environment |
| InsecureLdapAuth.java:29:41:29:47 | ldapUrl : String | InsecureLdapAuth.java:29:3:29:13 | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:31:3:31:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:34:49:34:59 | environment |
| InsecureLdapAuth.java:45:3:45:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:48:49:48:59 | environment |
| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | InsecureLdapAuth.java:57:41:57:47 | ldapUrl : String |
| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | InsecureLdapAuth.java:63:49:63:59 | environment |
| InsecureLdapAuth.java:57:3:57:13 | environment [post update] [<map.value>] : String | InsecureLdapAuth.java:63:49:63:59 | environment |
| InsecureLdapAuth.java:57:41:57:47 | ldapUrl : String | InsecureLdapAuth.java:57:3:57:13 | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:59:3:59:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:63:49:63:59 | environment |
| InsecureLdapAuth.java:62:3:62:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:63:49:63:59 | environment |
| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:72:41:72:47 | ldapUrl : String |
| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:77:49:77:59 | environment |
| InsecureLdapAuth.java:72:3:72:13 | environment [post update] [<map.value>] : String | InsecureLdapAuth.java:77:49:77:59 | environment |
| InsecureLdapAuth.java:72:41:72:47 | ldapUrl : String | InsecureLdapAuth.java:72:3:72:13 | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:88:3:88:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:91:49:91:59 | environment |
| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:41:100:47 | ldapUrl : String |
| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:105:59:105:69 | environment |
| InsecureLdapAuth.java:100:3:100:13 | environment [post update] [<map.value>] : String | InsecureLdapAuth.java:105:59:105:69 | environment |
| InsecureLdapAuth.java:100:41:100:47 | ldapUrl : String | InsecureLdapAuth.java:100:3:100:13 | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:102:3:102:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:105:59:105:69 | environment |
| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:115:47:115:53 | ldapUrl : String |
| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:120:49:120:59 | environment |
| InsecureLdapAuth.java:115:3:115:13 | environment [post update] [<map.value>] : String | InsecureLdapAuth.java:120:49:120:59 | environment |
| InsecureLdapAuth.java:115:47:115:53 | ldapUrl : String | InsecureLdapAuth.java:115:3:115:13 | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:117:3:117:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:120:49:120:59 | environment |
| InsecureLdapAuth.java:124:3:124:5 | env [post update] : Hashtable | InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable |
| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable |
| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable |
| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | InsecureLdapAuth.java:140:41:140:47 | ldapUrl : String |
| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | InsecureLdapAuth.java:142:50:142:60 | environment |
| InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | InsecureLdapAuth.java:142:50:142:60 | environment |
| InsecureLdapAuth.java:140:3:140:13 | environment [post update] [<map.value>] : String | InsecureLdapAuth.java:142:50:142:60 | environment |
| InsecureLdapAuth.java:140:41:140:47 | ldapUrl : String | InsecureLdapAuth.java:140:3:140:13 | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | InsecureLdapAuth.java:142:50:142:60 | environment |
| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:151:41:151:47 | ldapUrl : String |
| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:153:50:153:60 | environment |
| InsecureLdapAuth.java:151:3:151:13 | environment [post update] [<map.value>] : String | InsecureLdapAuth.java:153:50:153:60 | environment |
| InsecureLdapAuth.java:151:41:151:47 | ldapUrl : String | InsecureLdapAuth.java:151:3:151:13 | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | InsecureLdapAuth.java:153:50:153:60 | environment |
nodes
| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String |
| InsecureLdapAuth.java:15:3:15:13 | environment [post update] [<map.value>] : String | semmle.label | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:15:41:15:47 | ldapUrl : String | semmle.label | ldapUrl : String |
| InsecureLdapAuth.java:17:3:17:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:20:49:20:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:20:49:20:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | semmle.label | ... + ... : String |
| InsecureLdapAuth.java:29:3:29:13 | environment [post update] [<map.value>] : String | semmle.label | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:29:41:29:47 | ldapUrl : String | semmle.label | ldapUrl : String |
| InsecureLdapAuth.java:31:3:31:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:34:49:34:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:34:49:34:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:45:3:45:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:48:49:48:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | semmle.label | "ldap://ad.your-server.com:636" : String |
| InsecureLdapAuth.java:57:3:57:13 | environment [post update] [<map.value>] : String | semmle.label | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:57:41:57:47 | ldapUrl : String | semmle.label | ldapUrl : String |
| InsecureLdapAuth.java:59:3:59:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:62:3:62:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String |
| InsecureLdapAuth.java:72:3:72:13 | environment [post update] [<map.value>] : String | semmle.label | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:72:41:72:47 | ldapUrl : String | semmle.label | ldapUrl : String |
| InsecureLdapAuth.java:77:49:77:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:88:3:88:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:91:49:91:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String |
| InsecureLdapAuth.java:100:3:100:13 | environment [post update] [<map.value>] : String | semmle.label | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:100:41:100:47 | ldapUrl : String | semmle.label | ldapUrl : String |
| InsecureLdapAuth.java:102:3:102:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:105:59:105:69 | environment | semmle.label | environment |
| InsecureLdapAuth.java:105:59:105:69 | environment | semmle.label | environment |
| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String |
| InsecureLdapAuth.java:115:3:115:13 | environment [post update] [<map.value>] : String | semmle.label | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:115:47:115:53 | ldapUrl : String | semmle.label | ldapUrl : String |
| InsecureLdapAuth.java:117:3:117:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:120:49:120:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:120:49:120:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:124:3:124:5 | env [post update] : Hashtable | semmle.label | env [post update] : Hashtable |
| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | semmle.label | env [post update] : Hashtable |
| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | semmle.label | ... + ... : String |
| InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:140:3:140:13 | environment [post update] [<map.value>] : String | semmle.label | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:140:41:140:47 | ldapUrl : String | semmle.label | ldapUrl : String |
| InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment |
| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment |
| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment |
| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | semmle.label | ... + ... : String |
| InsecureLdapAuth.java:151:3:151:13 | environment [post update] [<map.value>] : String | semmle.label | environment [post update] [<map.value>] : String |
| InsecureLdapAuth.java:151:41:151:47 | ldapUrl : String | semmle.label | ldapUrl : String |
| InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:153:50:153:60 | environment | semmle.label | environment |
| InsecureLdapAuth.java:153:50:153:60 | environment | semmle.label | environment |
subpaths
#select
| InsecureLdapAuth.java:20:49:20:59 | environment | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:20:49:20:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" | LDAP connection string |
| InsecureLdapAuth.java:34:49:34:59 | environment | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:34:49:34:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:25:20:25:39 | ... + ... | LDAP connection string |
| InsecureLdapAuth.java:105:59:105:69 | environment | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:105:59:105:69 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" | LDAP connection string |
| InsecureLdapAuth.java:120:49:120:59 | environment | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:120:49:120:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" | LDAP connection string |
| InsecureLdapAuth.java:153:50:153:60 | environment | InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:153:50:153:60 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:147:20:147:39 | ... + ... | LDAP connection string |

View File

@@ -1 +0,0 @@
experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql

View File

@@ -11,13 +11,13 @@ public class InsecureLdapAuth {
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);
DirContext dirContext = new InitialDirContext(environment); // $ hasInsecureLdapAuth
}
// BAD - Test LDAP authentication in cleartext using `DirContext`.
@@ -25,13 +25,13 @@ public class InsecureLdapAuth {
String ldapUrl = "ldap://"+serverName+":389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);
DirContext dirContext = new InitialDirContext(environment); // $ hasInsecureLdapAuth
}
// GOOD - Test LDAP authentication over SSL.
@@ -39,7 +39,7 @@ public class InsecureLdapAuth {
String ldapUrl = "ldaps://ad.your-server.com:636";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
@@ -53,7 +53,7 @@ public class InsecureLdapAuth {
String ldapUrl = "ldap://ad.your-server.com:636";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
@@ -68,7 +68,7 @@ public class InsecureLdapAuth {
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI");
@@ -82,7 +82,7 @@ public class InsecureLdapAuth {
String ldapUrl = "ldap://localhost:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
@@ -96,14 +96,14 @@ public class InsecureLdapAuth {
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
InitialLdapContext ldapContext = new InitialLdapContext(environment, null);
}
InitialLdapContext ldapContext = new InitialLdapContext(environment, null); // $ hasInsecureLdapAuth
}
// BAD - Test LDAP authentication in cleartext using `DirContext` and string literals.
@@ -111,13 +111,13 @@ public class InsecureLdapAuth {
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put("java.naming.factory.initial",
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put("java.naming.provider.url", ldapUrl);
environment.put("java.naming.referral", "follow");
environment.put("java.naming.security.authentication", "simple");
environment.put("java.naming.security.principal", ldapUserName);
environment.put("java.naming.security.credentials", password);
DirContext dirContext = new InitialDirContext(environment);
DirContext dirContext = new InitialDirContext(environment); // $ hasInsecureLdapAuth
}
private void setSSL(Hashtable env) {
@@ -136,7 +136,7 @@ public class InsecureLdapAuth {
Hashtable<String, String> environment = new Hashtable<String, String>();
setSSL(environment);
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
setBasicAuth(environment, ldapUserName, password);
DirContext dirContext = new InitialLdapContext(environment, null);
@@ -147,9 +147,9 @@ public class InsecureLdapAuth {
String ldapUrl = "ldap://"+serverName+":389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
setBasicAuth(environment, ldapUserName, password);
DirContext dirContext = new InitialLdapContext(environment, null);
DirContext dirContext = new InitialLdapContext(environment, null); // $ hasInsecureLdapAuth
}
}

View File

@@ -0,0 +1,20 @@
import java
import semmle.code.java.security.InsecureLdapAuthQuery
import TestUtilities.InlineExpectationsTest
class InsecureLdapAuthenticationTest extends InlineExpectationsTest {
InsecureLdapAuthenticationTest() { this = "InsecureLdapAuthentication" }
override string getARelevantTag() { result = "hasInsecureLdapAuth" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasInsecureLdapAuth" and
exists(DataFlow::Node sink | InsecureLdapUrlFlow::flowTo(sink) |
BasicAuthFlow::flowTo(sink) and
not RequiresSslFlow::flowTo(sink) and
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}