Skip to main content

Non-encrypted confidential information - Base 64

Need

Secure storage of confidential information

Context

  • Usage of TypeScript for type-checking and compiling JavaScript code
  • Usage of Express for building web applications and APIs
  • Usage of base-64 for encoding and decoding data in base64 format

Description

Non compliant code

import express from 'express';
import * as base64 from 'base-64';

const app = express();

const credentials = {
username: 'admin',
password: 'password123'
};

app.get('/login', (req, res) => {
const encodedCredentials = base64.encode(`${credentials.username}:${credentials.password}`);
res.send(encodedCredentials);
});

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

The vulnerability in this code is that the credentials (username and password) are stored in plain text in the source code. These credentials are then encoded using Base64 and sent as a response when the '/login' endpoint is accessed.

Storing credentials in plain text in the source code is a security risk because anyone with access to the code can easily obtain the credentials. In this case, the credentials are encoded using Base64, but Base64 encoding is not a form of encryption. It is a simple encoding scheme that can be easily reversed, so the credentials can still be easily obtained by decoding the Base64 string.

An attacker who gains access to the source code or intercepts the response containing the encoded credentials can easily decode the Base64 string and obtain the username and password. This can lead to unauthorized access to the service or sensitive information.

To fix this vulnerability, it is recommended to remove the credentials from the source code and store them securely. This can be done by using a secure storage mechanism such as a key vault service or by using encrypted configuration files. Additionally, it is important to ensure that the sensitive data is not stored in version control systems like Git, as recommended in the provided recommendation.

Steps

  • Remove the import statement for the 'base-64' module.
  • Instead of encoding the credentials using base64, use a secure encryption algorithm like bcrypt to hash the password.
  • Store the hashed password in a secure location, such as a database or a key vault service.
  • When authenticating the user, compare the hashed password with the user input using the same encryption algorithm.
  • Update the recommendation to include the steps mentioned above.

Compliant code

import express from 'express';
import bcrypt from 'bcrypt';

const app = express();

const credentials = {
username: 'admin',
password: 'password123'
};

app.get('/login', async (req, res) => {
const hashedPassword = await bcrypt.hash(credentials.password, 10);
res.send(hashedPassword);
});

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

The fixed code addresses the vulnerability by not storing the credentials directly in the source code. Instead, it uses a bcrypt library to securely hash the password before sending it as a response.

Here's a breakdown of the fixed code:

  1. The code imports the necessary modules, including the 'express' framework and the 'bcrypt' library for password hashing.

  2. An instance of the express application is created using the 'express()' function and assigned to the 'app' variable.

  3. The credentials object is defined, which contains the username and password. Note that this is just for demonstration purposes and should not be used in a production environment.

  4. The app defines a GET route '/login' using the 'app.get()' method. This route handles the login functionality.

  5. Inside the route handler, the password is securely hashed using the 'bcrypt.hash()' method. The password from the credentials object is passed as the first argument, and the number of salt rounds (10 in this case) is passed as the second argument. The hashing process is asynchronous and returns a hashed password.

  6. The hashed password is then sent as a response using the 'res.send()' method.

  7. The app listens on port 3000 using the 'app.listen()' method, and a console log message is printed to indicate that the server is running.

By using bcrypt to hash the password, the fixed code ensures that the password is not stored in plain text and is more secure against unauthorized access.

References