Skip to main content

Cracked weak credentials

Need

Enhancement of password security

Context

  • Usage of TypeScript for statically typed JavaScript development
  • Usage of Express for building web applications and APIs
  • Usage of bcrypt for password hashing and encryption

Description

Non compliant code

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

const app = express();
const port = 3000;

app.use(express.json());

app.post('/login', (req, res) => {
const { username, password } = req.body;

// Insecure password hashing with low complexity
const hashedPassword = bcrypt.hashSync(password, 1);

// Authenticate user
if (username === 'admin' && bcrypt.compareSync(password, hashedPassword)) {
res.status(200).json({ message: 'Login successful' });
} else {
res.status(401).json({ message: 'Invalid credentials' });
}
});

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

The vulnerability in this code lies in the insecure password hashing mechanism used. The bcrypt library is used to hash the password, but the complexity factor used in the hash function is set to 1, which is a very low value.

A low complexity factor significantly reduces the time required to crack the hashed passwords. This means that an attacker can easily guess or crack weak passwords stored in the database.

Additionally, the code does not perform sufficient data validation. It assumes that the username is always 'admin' and only checks if the entered password matches the hashed password. This can lead to unauthorized access if an attacker guesses the correct username and cracks the weak password.

To mitigate this vulnerability, it is recommended to increase the complexity factor used in the bcrypt hash function. A higher complexity factor, such as a minimum size of 256 bits, would make it much more difficult and time-consuming for an attacker to crack the passwords.

Furthermore, proper data validation should be implemented to ensure that the entered username and password are valid and match the expected format before attempting to authenticate the user.

Steps

  • Increase the complexity of the password hashing algorithm
  • Use a salt when hashing the password
  • Ensure that the password summary has a minimum size of 256 bits
  • Implement proper data validation and input sanitization

Compliant code

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

const app = express();
const port = 3000;

app.use(express.json());

app.post('/login', (req, res) => {
const { username, password } = req.body;

// Increase password hashing complexity
const hashedPassword = bcrypt.hashSync(password, 10);

// Authenticate user
if (username === 'admin' && bcrypt.compareSync(password, hashedPassword)) {
res.status(200).json({ message: 'Login successful' });
} else {
res.status(401).json({ message: 'Invalid credentials' });
}
});

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

The fixed code addresses the vulnerability by increasing the complexity of the password hashing process using the bcrypt library. Here's an explanation of the code:

  1. The code imports the necessary modules, including express for creating the server and bcrypt for password hashing.
  2. The code creates an instance of the express application and sets the port to 3000.
  3. The code uses the express.json() middleware to parse incoming JSON requests.
  4. The code defines a POST route for the '/login' endpoint.
  5. Inside the route handler, the code extracts the username and password from the request body.
  6. The code then uses bcrypt.hashSync() to hash the password with a complexity factor of 10. Increasing the complexity factor makes it computationally expensive to crack the password hash.
  7. The code compares the hashed password with the provided password using bcrypt.compareSync(). This ensures that the password is validated securely without exposing the actual password.
  8. If the username is 'admin' and the password is successfully validated, the code sends a response with a status code of 200 and a JSON message indicating a successful login.
  9. If the credentials are invalid, the code sends a response with a status code of 401 and a JSON message indicating invalid credentials.
  10. The code starts the server and listens on the specified port, logging a message to the console.

By using bcrypt to hash and compare passwords, the fixed code significantly increases the complexity of the password hashing process, making it more difficult for attackers to crack weak credentials.

References