Enabled default credentials - TypeScript

Enabled default credentials - TypeScript

Need

Implementation of strong, unique credentials for system resources

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();

// Default credentials
const defaultUsername = 'admin';
const defaultPassword = 'password';

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

  if (username === defaultUsername && password === defaultPassword) {
    // Successful login
    res.status(200).json({ message: 'Login successful' });
  } else {
    // Invalid credentials
    res.status(401).json({ message: 'Invalid credentials' });
  }
});

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

The vulnerability in this code is the use of default credentials for authentication. The default username and password are hardcoded in the code as "admin" and "password" respectively. This means that anyone who knows these default credentials can easily gain unauthorized access to the system resources or services.

The code receives a POST request to the "/login" endpoint and checks if the provided username and password match the default credentials. If they do, a successful login response is sent with a status code of 200. Otherwise, an invalid credentials response is sent with a status code of 401.

This vulnerability can be exploited by attackers who can easily guess or find out the default credentials. Once they have access, they can perform unauthorized actions, manipulate data, or even gain control over the entire system.

To mitigate this vulnerability, it is recommended to eliminate the use of default credentials. Instead, implement a secure authentication mechanism that requires users to set their own unique and strong passwords. Additionally, it is important to ensure that passwords are properly hashed and stored securely to prevent unauthorized access to sensitive information.

Steps

  • Remove the default credentials from the code
  • Implement a secure authentication mechanism, such as using a secure hash function to store passwords
  • Use a strong and unique password for each user
  • Consider implementing multi-factor authentication for additional security
  • Regularly update and patch the application and its dependencies to address any security vulnerabilities

Compliant code

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

const app = express();

app.use(express.json());

// User credentials
const users = [
  {
    username: 'admin',
    password: '$2b$10$yZ4v1O7c9f6wVY7yXfZ9Ue9Zr6ZS0Vl9B0g9F6X2T0Nv8h5v7g3ZG' // hashed password
  }
];

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

  const user = users.find(user => user.username === username);

  if (!user) {
    // User not found
    return res.status(401).json({ message: 'Invalid credentials' });
  }

  bcrypt.compare(password, user.password, (err, result) => {
    if (err) {
      // Error comparing passwords
      return res.status(500).json({ message: 'Internal server error' });
    }

    if (result) {
      // Successful login
      return res.status(200).json({ message: 'Login successful' });
    } else {
      // Invalid credentials
      return res.status(401).json({ message: 'Invalid credentials' });
    }
  });
});

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

The fixed code addresses the vulnerability by implementing secure password storage and authentication practices. Here's an explanation of the changes made:

1. The code imports the bcrypt library, which is a widely used library for hashing passwords.

2. The users array now stores the hashed password instead of the plain text password. This ensures that even if the database is compromised, the passwords cannot be easily obtained.

3. In the /login route, the user's input password is compared with the hashed password using the bcrypt.compare function. This function securely compares the two passwords without revealing the actual password.

4. If the comparison is successful, indicating that the passwords match, a successful login response is sent with a status code of 200 and a message of "Login successful".

5. If the comparison fails, indicating that the passwords do not match, an invalid credentials response is sent with a status code of 401 and a message of "Invalid credentials".

6. In case of any errors during the password comparison, an internal server error response is sent with a status code of 500 and a message of "Internal server error".

By using bcrypt to hash and compare passwords, the fixed code eliminates the use of default or low-strength credentials, ensuring that unauthorized access to resources or services is prevented.

References