Skip to content

Commit 23f620d

Browse files
committed
Query to detect insecure LDAP endpoint configuration
1 parent 178c54e commit 23f620d

File tree

6 files changed

+175
-0
lines changed

6 files changed

+175
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
public class InsecureLdapEndpoint {
2+
public Hashtable<String, String> createConnectionEnv() {
3+
Hashtable<String, String> env = new Hashtable<String, String>();
4+
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
5+
env.put(Context.PROVIDER_URL, "ldaps://ad.your-server.com:636");
6+
7+
env.put(Context.SECURITY_AUTHENTICATION, "simple");
8+
env.put(Context.SECURITY_PRINCIPAL, "username");
9+
env.put(Context.SECURITY_CREDENTIALS, "secpassword");
10+
11+
// BAD - Test configuration with disabled SSL endpoint check.
12+
{
13+
System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
14+
}
15+
16+
// GOOD - No configuration to disable SSL endpoint check since it is enabled by default.
17+
{
18+
}
19+
20+
return env;
21+
}
22+
23+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>Java versions 8u181 or greater have enabled LDAPS endpoint identification by default. Nowadays infrastructure services like LDAP are commonly deployed behind load balancers therefore the LDAP server name can be different from the FQDN of the LDAPS endpoint. If a service certificate does not properly contain a matching DNS name as part of the certificate, Java will reject it by default.</p>
8+
<p>Instead of addressing the issue properly by having a compliant certificate deployed, frequently developers simply disable SSL endpoint check.</p>
9+
<p>This query checks whether LDAPS endpoint check is disabled in system properties.</p>
10+
</overview>
11+
12+
<recommendation>
13+
<p>Replace any non-conforming LDAP server certificates to include a DNS name in the subjectAltName field of the certificate that matches the FQDN of the service.</p>
14+
</recommendation>
15+
16+
<example>
17+
<p>The following two examples show two ways of configuring SSL endpoint. In the 'BAD' case,
18+
endpoint check is disabled. In the 'GOOD' case, endpoint check is left enabled through the default Java configuration.</p>
19+
<sample src="InsecureSSLEndpoint.java" />
20+
</example>
21+
22+
<references>
23+
<li>
24+
Oracle Java 8 Update 181 (8u181):
25+
<a href="https://www.java.com/en/download/help/release_changes.html">Endpoint identification enabled on LDAPS connections</a>
26+
</li>
27+
<li>
28+
IBM:
29+
<a href="https://www.ibm.com/support/pages/how-do-i-fix-ldap-ssl-error-%E2%80%9Cjavasecuritycertcertificateexception-no-subject-alternative-names-present%E2%80%9D-websphere-application-server">Fix this LDAP SSL error</a>
30+
</li>
31+
</references>
32+
</qhelp>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* @name Insecure LDAP Endpoint Configuration
3+
* @description Java application configured to disable LDAP endpoint identification does not validate the SSL certificate to properly ensure that it is actually associated with that host.
4+
* @kind problem
5+
* @id java/insecure-ldap-endpoint
6+
* @tags security
7+
* external/cwe-297
8+
*/
9+
10+
import java
11+
12+
/**
13+
* The method to set a system property.
14+
*/
15+
class SetSystemPropertyMethod extends Method {
16+
SetSystemPropertyMethod() {
17+
this.hasName("setProperty") and
18+
this.getDeclaringType().hasQualifiedName("java.lang", "System")
19+
}
20+
}
21+
22+
/**
23+
* The method to set Java properties.
24+
*/
25+
class SetPropertyMethod extends Method {
26+
SetPropertyMethod() {
27+
this.hasName("setProperty") and
28+
this.getDeclaringType().hasQualifiedName("java.util", "Properties")
29+
}
30+
}
31+
32+
/**
33+
* The method to set system properties.
34+
*/
35+
class SetSystemPropertiesMethod extends Method {
36+
SetSystemPropertiesMethod() {
37+
this.hasName("setProperties") and
38+
this.getDeclaringType().hasQualifiedName("java.lang", "System")
39+
}
40+
}
41+
42+
/** Holds if `MethodAccess` ma disables SSL endpoint check. */
43+
predicate isInsecureSSLEndpoint(MethodAccess ma) {
44+
(
45+
ma.getMethod() instanceof SetSystemPropertyMethod and
46+
(
47+
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() =
48+
"com.sun.jndi.ldap.object.disableEndpointIdentification" and
49+
ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = "true" //com.sun.jndi.ldap.object.disableEndpointIdentification=true
50+
)
51+
or
52+
ma.getMethod() instanceof SetSystemPropertiesMethod and
53+
exists(MethodAccess ma2 |
54+
ma2.getMethod() instanceof SetPropertyMethod and
55+
ma2.getArgument(0).(CompileTimeConstantExpr).getStringValue() =
56+
"com.sun.jndi.ldap.object.disableEndpointIdentification" and
57+
ma2.getArgument(1).(CompileTimeConstantExpr).getStringValue() = "true" and //com.sun.jndi.ldap.object.disableEndpointIdentification=true
58+
ma2.getQualifier().(VarAccess).getVariable().getAnAccess() = ma.getArgument(0) // systemProps.setProperties(properties)
59+
)
60+
)
61+
}
62+
63+
from MethodAccess ma
64+
where isInsecureSSLEndpoint(ma)
65+
select ma, "SSL configuration allows insecure endpoint configuration"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| InsecureLdapEndpoint.java:17:9:17:92 | setProperty(...) | SSL configuration allows insecure endpoint configuration |
2+
| InsecureLdapEndpoint.java:48:3:48:34 | setProperties(...) | SSL configuration allows insecure endpoint configuration |
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import java.util.Hashtable;
2+
import java.util.Properties;
3+
import javax.naming.Context;
4+
5+
public class InsecureLdapEndpoint {
6+
// BAD - Test configuration with disabled SSL endpoint check.
7+
public Hashtable<String, String> createConnectionEnv() {
8+
Hashtable<String, String> env = new Hashtable<String, String>();
9+
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
10+
env.put(Context.PROVIDER_URL, "ldaps://ad.your-server.com:636");
11+
12+
env.put(Context.SECURITY_AUTHENTICATION, "simple");
13+
env.put(Context.SECURITY_PRINCIPAL, "username");
14+
env.put(Context.SECURITY_CREDENTIALS, "secpassword");
15+
16+
// Disable SSL endpoint check
17+
System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
18+
19+
return env;
20+
}
21+
22+
// GOOD - Test configuration without disabling SSL endpoint check.
23+
public Hashtable<String, String> createConnectionEnv2() {
24+
Hashtable<String, String> env = new Hashtable<String, String>();
25+
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
26+
env.put(Context.PROVIDER_URL, "ldaps://ad.your-server.com:636");
27+
28+
env.put(Context.SECURITY_AUTHENTICATION, "simple");
29+
env.put(Context.SECURITY_PRINCIPAL, "username");
30+
env.put(Context.SECURITY_CREDENTIALS, "secpassword");
31+
32+
return env;
33+
}
34+
35+
// BAD - Test configuration with disabled SSL endpoint check.
36+
public Hashtable<String, String> createConnectionEnv3() {
37+
Hashtable<String, String> env = new Hashtable<String, String>();
38+
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
39+
env.put(Context.PROVIDER_URL, "ldaps://ad.your-server.com:636");
40+
41+
env.put(Context.SECURITY_AUTHENTICATION, "simple");
42+
env.put(Context.SECURITY_PRINCIPAL, "username");
43+
env.put(Context.SECURITY_CREDENTIALS, "secpassword");
44+
45+
// Disable SSL endpoint check
46+
Properties properties = new Properties();
47+
properties.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
48+
System.setProperties(properties);
49+
50+
return env;
51+
}
52+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
experimental/Security/CWE/CWE-297/InsecureLdapEndpoint.ql

0 commit comments

Comments
 (0)