Skip to main content

Business information leak - Credentials

Need

Protection of business credentials and sensitive information from unauthorized access and leakage

Context

  • Usage of TypeScript for type-checking and compiling JavaScript code
  • Usage of Express for building web applications and APIs

Description

Non compliant code

import express from 'express';

const app = express();

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

// Authenticate user with the provided credentials
if (username === 'admin' && password === 'password') {
res.send('Login successful');
} else {
res.send('Invalid credentials');
}
});

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

The vulnerability in this code is a business information leak related to credentials. The code receives the username and password as query parameters in the '/login' endpoint. However, it does not implement any secure authentication mechanism to protect the credentials.

The code compares the received username and password with hardcoded values ('admin' and 'password') to authenticate the user. This approach is highly insecure as it exposes the credentials directly in the code. An attacker can easily discover these credentials by inspecting the source code or by intercepting the network traffic.

This vulnerability allows an attacker to perform credential stuffing attacks, where they can use leaked credentials from other sources to attempt to gain unauthorized access to user accounts. Additionally, if an attacker gains access to the 'admin' account, they can potentially compromise sensitive data, internal systems, and perform unauthorized actions.

To address this vulnerability, it is recommended to implement a secure authentication mechanism such as using a strong hashing algorithm to store passwords, salting the passwords, and comparing the hashed values during authentication. Additionally, implementing measures like multi-factor authentication, strong password policies, and regular review of network security and access controls can further enhance the security of the application.

Steps

  • Avoid storing credentials in plain text in the code. Instead, use a secure method to store and retrieve credentials, such as environment variables or a configuration file.
  • Implement a secure authentication mechanism, such as using a secure hashing algorithm to store and compare passwords.
  • Use a secure communication protocol, such as HTTPS, to protect the transmission of credentials over the network.
  • Implement rate limiting and account lockout mechanisms to prevent brute-force attacks.
  • Implement multi-factor authentication to add an extra layer of security.
  • Regularly review and update the authentication mechanism to address any new vulnerabilities or security best practices.
  • Consider using a dedicated authentication service or library that has undergone security testing and has a strong track record of security.

Compliant code

import express from 'express';

const app = express();

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

// Authenticate user with the provided credentials
if (authenticate(username, password)) {
res.send('Login successful');
} else {
res.send('Invalid credentials');
}
});

function authenticate(username: string, password: string): boolean {
// Implement secure authentication mechanism here
// Use a secure hashing algorithm to store and compare passwords
// Retrieve stored credentials from a secure source (e.g., environment variables or a configuration file)
const storedUsername = process.env.USERNAME;
const storedPassword = process.env.PASSWORD;

// Compare the provided credentials with the stored credentials
if (username === storedUsername && password === storedPassword) {
return true;
} else {
return false;
}
}

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

The fixed code addresses the vulnerability by implementing secure authentication mechanisms and following best practices for handling credentials. Here's an explanation of the changes made:

  1. The code imports the 'express' module and creates an instance of the Express application.

  2. The '/login' route is defined using the app.get() method. This route handles the login request and expects the username and password to be passed as query parameters.

  3. The authenticate() function is called to validate the provided credentials. It takes the username and password as parameters and returns a boolean value indicating whether the authentication was successful or not.

  4. Inside the authenticate() function, the stored username and password are retrieved from secure sources, such as environment variables (process.env). This ensures that the credentials are not hardcoded in the code and can be securely managed.

  5. The provided username and password are then compared with the stored credentials using the === operator. This ensures that the comparison is strict and prevents any potential type coercion vulnerabilities.

  6. If the provided credentials match the stored credentials, the authenticate() function returns true, indicating a successful authentication. Otherwise, it returns false.

  7. In the '/login' route, the authenticate() function is called with the provided username and password. If the authentication is successful, the server responds with 'Login successful'. Otherwise, it responds with 'Invalid credentials'.

  8. The server starts listening on port 3000 using the app.listen() method.

By implementing secure authentication mechanisms, securely storing credentials, and following best practices, the fixed code mitigates the risk of business information leaks due to credential vulnerabilities.

References