mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Enhance the query and update qldoc
This commit is contained in:
@@ -8,16 +8,11 @@ public class InsecureLdapEndpoint {
|
||||
env.put(Context.SECURITY_PRINCIPAL, "username");
|
||||
env.put(Context.SECURITY_CREDENTIALS, "secpassword");
|
||||
|
||||
// BAD - Test configuration with disabled SSL endpoint check.
|
||||
{
|
||||
System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
|
||||
}
|
||||
|
||||
// GOOD - No configuration to disable SSL endpoint check since it is enabled by default.
|
||||
{
|
||||
}
|
||||
// BAD - Test configuration with disabled SSL endpoint check.
|
||||
{
|
||||
System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
<overview>
|
||||
<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>
|
||||
<p>Instead of addressing the issue properly by having a compliant certificate deployed, frequently developers simply disable SSL endpoint check.</p>
|
||||
<p>This query checks whether LDAPS endpoint check is disabled in system properties.</p>
|
||||
<p>Instead of addressing the issue properly by having a compliant certificate deployed, frequently developers simply disable LDAPS endpoint check.</p>
|
||||
<p>Failing to validate the certificate makes the SSL session susceptible to a man-in-the-middle attack. This query checks whether LDAPS endpoint check is disabled in system properties.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
@@ -14,9 +14,10 @@
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>The following two examples show two ways of configuring SSL endpoint. In the 'BAD' case,
|
||||
<p>The following two examples show two ways of configuring LDAPS endpoint. In the 'BAD' case,
|
||||
endpoint check is disabled. In the 'GOOD' case, endpoint check is left enabled through the default Java configuration.</p>
|
||||
<sample src="InsecureSSLEndpoint.java" />
|
||||
<sample src="InsecureLdapEndpoint.java" />
|
||||
<sample src="InsecureLdapEndpoint2.java" />>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
/**
|
||||
* @name Insecure LDAP Endpoint Configuration
|
||||
* @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.
|
||||
* @name Insecure LDAPS Endpoint Configuration
|
||||
* @description Java application configured to disable LDAPS endpoint identification does not validate the SSL certificate to properly ensure that it is actually associated with that host.
|
||||
* @kind problem
|
||||
* @id java/insecure-ldap-endpoint
|
||||
* @id java/insecure-ldaps-endpoint
|
||||
* @tags security
|
||||
* external/cwe-297
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
/**
|
||||
* The method to set a system property.
|
||||
*/
|
||||
/** The method to set a system property. */
|
||||
class SetSystemPropertyMethod extends Method {
|
||||
SetSystemPropertyMethod() {
|
||||
this.hasName("setProperty") and
|
||||
@@ -19,19 +17,22 @@ class SetSystemPropertyMethod extends Method {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The method to set Java properties.
|
||||
*/
|
||||
class SetPropertyMethod extends Method {
|
||||
SetPropertyMethod() {
|
||||
this.hasName("setProperty") and
|
||||
this.getDeclaringType().hasQualifiedName("java.util", "Properties")
|
||||
}
|
||||
/** The class `java.util.Hashtable`. */
|
||||
class TypeHashtable extends Class {
|
||||
TypeHashtable() { this.getSourceDeclaration().hasQualifiedName("java.util", "Hashtable") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The method to set system properties.
|
||||
* The method to set Java properties either through `setProperty` declared in the class `Properties` or `put` declared in its parent class `HashTable`.
|
||||
*/
|
||||
class SetPropertyMethod extends Method {
|
||||
SetPropertyMethod() {
|
||||
this.getDeclaringType().getAnAncestor() instanceof TypeHashtable and
|
||||
this.hasName(["put", "setProperty"])
|
||||
}
|
||||
}
|
||||
|
||||
/** The method to set system properties. */
|
||||
class SetSystemPropertiesMethod extends Method {
|
||||
SetSystemPropertiesMethod() {
|
||||
this.hasName("setProperties") and
|
||||
@@ -39,27 +40,62 @@ class SetSystemPropertiesMethod extends Method {
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if an expression is evaluated to the string literal `com.sun.jndi.ldap.object.disableEndpointIdentification`. */
|
||||
predicate isPropertyDisableLdapEndpointId(Expr expr) {
|
||||
expr.(CompileTimeConstantExpr).getStringValue() =
|
||||
"com.sun.jndi.ldap.object.disableEndpointIdentification"
|
||||
or
|
||||
exists(Field f |
|
||||
expr = f.getAnAccess() and
|
||||
f.getAnAssignedValue().(StringLiteral).getValue() =
|
||||
"com.sun.jndi.ldap.object.disableEndpointIdentification"
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if an expression is evaluated to the boolean value true. */
|
||||
predicate isBooleanTrue(Expr expr) {
|
||||
expr.(CompileTimeConstantExpr).getStringValue() = "true" // "true"
|
||||
or
|
||||
expr.(BooleanLiteral).getBooleanValue() = true // true
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
expr = ma and
|
||||
ma.getMethod().hasName("toString") and
|
||||
ma.getQualifier().(FieldAccess).getField().hasName("TRUE") and
|
||||
ma.getQualifier()
|
||||
.(FieldAccess)
|
||||
.getField()
|
||||
.getDeclaringType()
|
||||
.hasQualifiedName("java.lang", "Boolean") // Boolean.TRUE.toString()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `ma` is in a test class or method. */
|
||||
predicate isTestMethod(MethodAccess ma) {
|
||||
ma.getMethod() instanceof TestMethod or
|
||||
ma.getEnclosingCallable().getDeclaringType().getPackage().getName().matches("%test%") or
|
||||
ma.getEnclosingCallable().getDeclaringType().getName().toLowerCase().matches("%test%")
|
||||
}
|
||||
|
||||
/** Holds if `MethodAccess` ma disables SSL endpoint check. */
|
||||
predicate isInsecureSSLEndpoint(MethodAccess ma) {
|
||||
(
|
||||
ma.getMethod() instanceof SetSystemPropertyMethod and
|
||||
(
|
||||
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() =
|
||||
"com.sun.jndi.ldap.object.disableEndpointIdentification" and
|
||||
ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = "true" //com.sun.jndi.ldap.object.disableEndpointIdentification=true
|
||||
)
|
||||
isPropertyDisableLdapEndpointId(ma.getArgument(0)) and
|
||||
isBooleanTrue(ma.getArgument(1)) //com.sun.jndi.ldap.object.disableEndpointIdentification=true
|
||||
or
|
||||
ma.getMethod() instanceof SetSystemPropertiesMethod and
|
||||
exists(MethodAccess ma2 |
|
||||
ma2.getMethod() instanceof SetPropertyMethod and
|
||||
ma2.getArgument(0).(CompileTimeConstantExpr).getStringValue() =
|
||||
"com.sun.jndi.ldap.object.disableEndpointIdentification" and
|
||||
ma2.getArgument(1).(CompileTimeConstantExpr).getStringValue() = "true" and //com.sun.jndi.ldap.object.disableEndpointIdentification=true
|
||||
isPropertyDisableLdapEndpointId(ma2.getArgument(0)) and
|
||||
isBooleanTrue(ma2.getArgument(1)) and //com.sun.jndi.ldap.object.disableEndpointIdentification=true
|
||||
ma2.getQualifier().(VarAccess).getVariable().getAnAccess() = ma.getArgument(0) // systemProps.setProperties(properties)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from MethodAccess ma
|
||||
where isInsecureSSLEndpoint(ma)
|
||||
select ma, "SSL configuration allows insecure endpoint configuration"
|
||||
where
|
||||
isInsecureSSLEndpoint(ma) and
|
||||
not isTestMethod(ma)
|
||||
select ma, "LDAPS configuration allows insecure endpoint identification"
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
public class InsecureLdapEndpoint2 {
|
||||
public Hashtable<String, String> createConnectionEnv() {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
env.put(Context.PROVIDER_URL, "ldaps://ad.your-server.com:636");
|
||||
|
||||
env.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||
env.put(Context.SECURITY_PRINCIPAL, "username");
|
||||
env.put(Context.SECURITY_CREDENTIALS, "secpassword");
|
||||
|
||||
// GOOD - No configuration to disable SSL endpoint check since it is enabled by default.
|
||||
{
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,5 @@
|
||||
| InsecureLdapEndpoint.java:17:9:17:92 | setProperty(...) | SSL configuration allows insecure endpoint configuration |
|
||||
| InsecureLdapEndpoint.java:48:3:48:34 | setProperties(...) | SSL configuration allows insecure endpoint configuration |
|
||||
| InsecureLdapEndpoint.java:19:9:19:92 | setProperty(...) | LDAPS configuration allows insecure endpoint identification |
|
||||
| InsecureLdapEndpoint.java:50:9:50:40 | setProperties(...) | LDAPS configuration allows insecure endpoint identification |
|
||||
| InsecureLdapEndpoint.java:68:9:68:40 | setProperties(...) | LDAPS configuration allows insecure endpoint identification |
|
||||
| InsecureLdapEndpoint.java:84:9:84:94 | setProperty(...) | LDAPS configuration allows insecure endpoint identification |
|
||||
| InsecureLdapEndpoint.java:102:9:102:40 | setProperties(...) | LDAPS configuration allows insecure endpoint identification |
|
||||
|
||||
@@ -3,7 +3,9 @@ import java.util.Properties;
|
||||
import javax.naming.Context;
|
||||
|
||||
public class InsecureLdapEndpoint {
|
||||
// BAD - Test configuration with disabled SSL endpoint check.
|
||||
private static String PROP_DISABLE_LDAP_ENDPOINT_IDENTIFICATION = "com.sun.jndi.ldap.object.disableEndpointIdentification";
|
||||
|
||||
// BAD - Test configuration with disabled LDAPS endpoint check using `System.setProperty()`.
|
||||
public Hashtable<String, String> createConnectionEnv() {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
@@ -19,7 +21,7 @@ public class InsecureLdapEndpoint {
|
||||
return env;
|
||||
}
|
||||
|
||||
// GOOD - Test configuration without disabling SSL endpoint check.
|
||||
// GOOD - Test configuration without disabling LDAPS endpoint check.
|
||||
public Hashtable<String, String> createConnectionEnv2() {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
@@ -32,7 +34,7 @@ public class InsecureLdapEndpoint {
|
||||
return env;
|
||||
}
|
||||
|
||||
// BAD - Test configuration with disabled SSL endpoint check.
|
||||
// BAD - Test configuration with disabled LDAPS endpoint check using `System.setProperties()`.
|
||||
public Hashtable<String, String> createConnectionEnv3() {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
@@ -49,4 +51,56 @@ public class InsecureLdapEndpoint {
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
// BAD - Test configuration with disabled LDAPS endpoint check using `HashTable.put()`.
|
||||
public Hashtable<String, String> createConnectionEnv4() {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
env.put(Context.PROVIDER_URL, "ldaps://ad.your-server.com:636");
|
||||
|
||||
env.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||
env.put(Context.SECURITY_PRINCIPAL, "username");
|
||||
env.put(Context.SECURITY_CREDENTIALS, "secpassword");
|
||||
|
||||
// Disable SSL endpoint check
|
||||
Properties properties = new Properties();
|
||||
properties.put("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
|
||||
System.setProperties(properties);
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
// BAD - Test configuration with disabled LDAPS endpoint check using the `TRUE` boolean field.
|
||||
public Hashtable<String, String> createConnectionEnv5() {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
env.put(Context.PROVIDER_URL, "ldaps://ad.your-server.com:636");
|
||||
|
||||
env.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||
env.put(Context.SECURITY_PRINCIPAL, "username");
|
||||
env.put(Context.SECURITY_CREDENTIALS, "secpassword");
|
||||
|
||||
// Disable SSL endpoint check
|
||||
System.setProperty(PROP_DISABLE_LDAP_ENDPOINT_IDENTIFICATION, Boolean.TRUE.toString());
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
// BAD - Test configuration with disabled LDAPS endpoint check using a boolean value.
|
||||
public Hashtable<String, String> createConnectionEnv6() {
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
env.put(Context.PROVIDER_URL, "ldaps://ad.your-server.com:636");
|
||||
|
||||
env.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||
env.put(Context.SECURITY_PRINCIPAL, "username");
|
||||
env.put(Context.SECURITY_CREDENTIALS, "secpassword");
|
||||
|
||||
// Disable SSL endpoint check
|
||||
Properties properties = new Properties();
|
||||
properties.put("com.sun.jndi.ldap.object.disableEndpointIdentification", true);
|
||||
System.setProperties(properties);
|
||||
|
||||
return env;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user