Skip to main content

Non-encrypted confidential information - LDAP

Need

Protection of confidential information through encryption

Context

  • Usage of Scala for building scalable and high-performance applications
  • Usage of javax.naming for accessing and managing naming and directory services in Java
  • Usage of javax.naming.directory for accessing and manipulating directory services in Java
  • Usage of java.util.Hashtable for storing key-value pairs in Java
  • Usage of com.sun.jndi.ldap.LdapCtxFactory for LDAP (Lightweight Directory Access Protocol) connection and operations
  • Usage of javax.naming.Context for accessing and managing naming and directory services in Java
  • Usage of javax.naming.directory.InitialDirContext for accessing and manipulating directory services

Description

Non compliant code

import javax.naming._
import javax.naming.directory._

val env = new java.util.Hashtable[String, String]
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory")
env.put(Context.PROVIDER_URL, "ldap://localhost:389/dc=example,dc=com")
env.put(Context.SECURITY_AUTHENTICATION, "simple")
env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=example,dc=com") // specify the username
env.put(Context.SECURITY_CREDENTIALS, "password") // specify the password in plain text

val ctx = new InitialDirContext(env)

The above code is a Scala implementation of a simple LDAP (Lightweight Directory Access Protocol) connection. The LDAP service credentials, such as the username and password, are exposed in plain text in the code, which is a significant security vulnerability.

In the above code, the Context.SECURITY_PRINCIPAL and Context.SECURITY_CREDENTIALS are set to the username and password, respectively. This information is then used to create a new InitialDirContext object, which establishes the connection to the LDAP server.

The vulnerability lies in the fact that the password is specified in plain text directly in the code. This is a major security risk as anyone who has access to the source code can easily see the password. This not only exposes the password to potential malicious actors but also makes it impossible to change the password without changing the source code.

In a real-world scenario, this could lead to unauthorized access to the LDAP server, data breaches, and potential compromise of the entire system. Therefore, it is crucial to fix this vulnerability by securely handling the LDAP service credentials.

Steps

  • Remove the hard-coded LDAP service credentials from the code.
  • Store the LDAP service credentials securely, such as in a configuration file or environment variables.
  • Encrypt the LDAP service credentials to ensure they are not exposed in plain text.
  • Update the code to retrieve the LDAP service credentials from the secure storage or environment variables.
  • Use a secure connection (LDAPS) when connecting to the LDAP server to ensure confidentiality of the information transmitted.

Compliant code

import javax.naming._
import javax.naming.directory._
import com.typesafe.config.ConfigFactory

val config = ConfigFactory.load()
val env = new java.util.Hashtable[String, String]
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory")
env.put(Context.PROVIDER_URL, config.getString("ldap.url"))
env.put(Context.SECURITY_AUTHENTICATION, "simple")
env.put(Context.SECURITY_PRINCIPAL, config.getString("ldap.principal"))
env.put(Context.SECURITY_CREDENTIALS, config.getString("ldap.credentials"))

val ctx = new InitialDirContext(env)

The updated code no longer contains hard-coded LDAP service credentials. Instead, it retrieves these credentials from a configuration file using the Typesafe Config library, which is a standard library for handling configurations in Scala applications.

The configuration file (usually application.conf in the resources folder) should look something like this:

ldap {
url = "ldaps://localhost:636/dc=example,dc=com"
principal = "cn=admin,dc=example,dc=com"
credentials = ${?LDAP_PASSWORD}
}

In this configuration file, the url is updated to use a secure LDAPS connection. The principal is the username for the LDAP service, and credentials is the password. The password is not stored directly in the configuration file. Instead, it is stored in an environment variable LDAP_PASSWORD. This way, the password is not exposed in the code or the configuration file.

When the application is started, it will load the configuration file and the environment variables. The ConfigFactory.load() method retrieves the configuration. The config.getString("ldap.url"), config.getString("ldap.principal"), and config.getString("ldap.credentials") methods retrieve the LDAP url, username, and password, respectively.

This approach ensures that the LDAP service credentials are stored securely and are not exposed in plain text in the code. It also ensures that a secure connection is used when connecting to the LDAP server.

References