Skip to main content

Non-encrypted confidential information - LDAP

Need

Secure storage and transmission of LDAP service credentials

Context

  • Usage of TypeScript for type-checking and compiling JavaScript code
  • Usage of Express for building web applications and APIs
  • Usage of ldapjs for LDAP (Lightweight Directory Access Protocol) operations

Description

Non compliant code

import express from 'express';
import ldap from 'ldapjs';

const app = express();

app.get('/login', (req, res) => {
const username = req.query.username;
const password = req.query.password;

const client = ldap.createClient({
url: 'ldap://example.com:389',
bindDN: `cn=${username},ou=users,dc=example,dc=com`,
bindCredentials: password,
});

client.bind((err) => {
if (err) {
res.status(401).send('Invalid credentials');
} else {
res.send('Login successful');
}
});
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The vulnerability in this code is that the LDAP service credentials, including the bindDN (Distinguished Name) and bindCredentials (password), are exposed in plain text in the code.

In the code, the bindDN is constructed using the username parameter from the request query string, and the bindCredentials is set to the password parameter from the request query string. These values are then used to create an LDAP client connection.

This means that anyone who has access to the code can easily view the LDAP service credentials, including the username and password, as they are not encrypted or protected in any way. This poses a security risk as it allows potential attackers to gain unauthorized access to the LDAP service and obtain confidential information.

To mitigate this vulnerability, it is recommended to use secure encryption methods to protect any sensitive information, such as the LDAP service credentials. This can include storing the credentials in a secure configuration file or using environment variables to store and retrieve the sensitive information securely.

Steps

  • Store the LDAP service credentials securely, such as in a configuration file or environment variables.
  • Encrypt the LDAP service credentials using a secure encryption method.
  • Retrieve the encrypted credentials from the secure storage.
  • Decrypt the credentials at runtime before using them in the code.
  • Update the code to use the decrypted credentials when creating the LDAP client.
  • Ensure that the decrypted credentials are not logged or exposed in any other way.
  • Test the updated code thoroughly to ensure it functions correctly and securely.

Compliant code

import express from 'express';
import ldap from 'ldapjs';
import { decryptCredentials } from './encryptionUtils';

const app = express();

app.get('/login', (req, res) => {
const username = req.query.username;
const encryptedPassword = req.query.password;

const password = decryptCredentials(encryptedPassword); // Decrypt the password

const client = ldap.createClient({
url: 'ldap://example.com:389',
bindDN: `cn=${username},ou=users,dc=example,dc=com`,
bindCredentials: password,
});

client.bind((err) => {
if (err) {
res.status(401).send('Invalid credentials');
} else {
res.send('Login successful');
}
});
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The fixed code addresses the vulnerability by implementing secure encryption methods to protect sensitive information, specifically LDAP service credentials.

  1. The code imports the necessary modules, including 'express' for creating the server and 'ldapjs' for interacting with the LDAP service. It also imports a function called 'decryptCredentials' from an 'encryptionUtils' module.

  2. The code creates an instance of the express server using the 'express()' function.

  3. It defines a route for the '/login' endpoint using the 'app.get()' method. This endpoint expects a username and an encrypted password as query parameters.

  4. The code then calls the 'decryptCredentials' function to decrypt the password obtained from the query parameters. This ensures that the password is not stored or transmitted in plain text.

  5. Next, the code creates an LDAP client using the 'ldap.createClient()' method. It specifies the LDAP server URL and the bindDN, which is constructed using the username obtained from the query parameters.

  6. The bindCredentials property is set to the decrypted password, ensuring that the password is securely provided to the LDAP service.

  7. The code then calls the 'client.bind()' method to attempt to authenticate the user with the LDAP service. If an error occurs during the bind process, the code sends a 401 status code with the message 'Invalid credentials'. Otherwise, it sends a 'Login successful' message.

  8. Finally, the code starts the server on port 3000 using the 'app.listen()' method and logs a message indicating that the server is running.

By encrypting the sensitive LDAP service credentials and decrypting them only when needed, the fixed code ensures that the credentials are not exposed in plain text, mitigating the vulnerability.

References