Skip to main content

Non-encrypted confidential information - Credentials

Need

Secure storage of credentials

Context

  • Usage of TypeScript for statically typed JavaScript development
  • 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;

// Vulnerability: Storing passwords in plain text
const storedPassword = 'secretpassword';

if (password === storedPassword) {
res.send('Login successful');
} else {
res.send('Invalid credentials');
}
});

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

The vulnerability in this code is that the passwords are stored in plain text in the source code. In the app.get('/login') route handler, the code retrieves the username and password from the query parameters of the request. It then compares the password with a stored password, which is hardcoded as 'secretpassword'.

Storing passwords in plain text is a security risk because if an attacker gains access to the source code or the server, they can easily view the passwords without any encryption. This allows them to obtain sensitive information and potentially compromise resources or services.

To mitigate this vulnerability, it is recommended to avoid storing sensitive information, such as passwords, in the source code. Instead, sensitive information should be stored securely, such as in a separate configuration file or a database, and accessed securely when needed. Additionally, it is important to ensure that sensitive information is not included in the source code repository or exposed in any other way.

Steps

  • Remove the plain text password stored in the code
  • Implement a secure password storage mechanism such as hashing and salting
  • Use a secure authentication method such as bcrypt to compare passwords
  • Consider using a secure session management library for handling user sessions
  • Ensure that sensitive information, API keys, and passwords are not included in the source code or online code repositories

Compliant code

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

const app = express();

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

// Secure password storage using bcrypt
const hashedPassword = '$2b$10$Y5W4Nz3Xz6i6q4Z0OJ5z7eG1f2R3X5Z6C7V8b9N0M1L2K3J4H5G6F7E8D9C0B';

bcrypt.compare(password, hashedPassword, (err, result) => {
if (err) {
res.send('Error occurred during login');
} else if (result) {
res.send('Login successful');
} else {
res.send('Invalid credentials');
}
});
});

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

The fixed code addresses the vulnerability by securely storing passwords using the bcrypt library. Here's an explanation of the changes made:

  1. The code imports the necessary modules, express and bcrypt, to handle the server and password hashing respectively.

  2. The code creates an instance of the Express application using express().

  3. The code defines a route for the /login endpoint using app.get('/login', ...). This route handles the login functionality.

  4. Inside the route handler, the code retrieves the username and password from the query parameters of the request.

  5. The code securely stores the hashed password in a variable called hashedPassword. This hashed password is a placeholder and should be replaced with the actual hashed password stored in a secure manner (e.g., in a database).

  6. The code uses the bcrypt.compare() function to compare the provided password with the hashed password. This function takes care of the password comparison securely, using the bcrypt algorithm.

  7. Inside the callback function of bcrypt.compare(), the code checks for any errors that might occur during the comparison. If an error occurs, it sends an error response to the client.

  8. If the comparison is successful (i.e., the passwords match), the code sends a "Login successful" response to the client.

  9. If the comparison fails (i.e., the passwords do not match), the code sends an "Invalid credentials" response to the client.

  10. The code starts the server by calling app.listen(3000, ...), which listens for incoming requests on port 3000.

  11. Finally, the code logs a message to the console indicating that the server is running.

By using bcrypt to securely hash and compare passwords, the fixed code ensures that sensitive information, such as passwords, is not stored in plain text and is protected against unauthorized access.

References