Weak credential policy - Password Change Limit - TypeScript

Weak credential policy - Password Change Limit - TypeScript

Need

Enforce a password change limit policy

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.post('/change-password', (req, res) => {
  // Code to change the password
  
  res.send('Password changed successfully');
});

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

The vulnerability in this code is that it does not implement any mechanism to limit the number of password change requests that can be made in a day. The code simply listens for a POST request to the '/change-password' endpoint and changes the password without any restrictions.

This means that an attacker can repeatedly send password change requests to the server, potentially denying access to the original user. For example, an attacker could automate the process of sending multiple password change requests in a short period of time, effectively locking out the legitimate user from accessing their account.

To mitigate this vulnerability, it is recommended to implement a mechanism that rejects multiple password change requests on the same day. This can be done by tracking the number of password change requests made by a user within a certain time frame, such as within a day, and rejecting any additional requests once the limit is reached.

Steps

  • Implement a mechanism to track the number of password change requests made by a user in a day
  • Add a check to verify if the user has already made a password change request in the same day
  • If the user has already made a password change request, reject the new request and send an appropriate response
  • If the user has not made a password change request, proceed with changing the password and send a success response

Compliant code

        import express from 'express';

const app = express();

// Track the number of password change requests made by a user in a day
const passwordChangeRequests = new Map();

app.post('/change-password', (req, res) => {
  const userId = req.body.userId;
  
  // Check if the user has already made a password change request in the same day
  if (passwordChangeRequests.has(userId)) {
    const lastChangeRequestTime = passwordChangeRequests.get(userId);
    const currentTime = new Date().getTime();
    const timeDifference = currentTime - lastChangeRequestTime;
    const hoursDifference = Math.floor(timeDifference / (1000 * 60 * 60));
    
    // Reject the new request if the user has already made a password change request in the same day
    if (hoursDifference < 24) {
      return res.status(429).send('Too many password change requests. Please try again later.');
    }
  }
  
  // Update the password change request time for the user
  passwordChangeRequests.set(userId, new Date().getTime());
  
  // Code to change the password
  
  return res.send('Password changed successfully');
});

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

The fixed code addresses the vulnerability by implementing a mechanism to limit the number of password change requests that can be made in a day. Here's how the code works:

1. The code imports the necessary dependencies, including the Express framework.

2. An instance of the Express application is created.

3. The code initializes a Map called passwordChangeRequests to keep track of the number of password change requests made by each user in a day.

4. The code defines a route handler for the /change-password endpoint using the app.post method. This endpoint is responsible for handling password change requests.

5. Inside the route handler, the code extracts the userId from the request body.

6. The code checks if the user has already made a password change request in the same day by using the passwordChangeRequests map. If the map contains an entry for the user, it means that a password change request has already been made.

7. If a password change request has been made, the code calculates the time difference between the last change request and the current time. It uses this difference to determine if the user has made multiple requests within a 24-hour period.

8. If the user has made multiple requests within 24 hours, the code returns a 429 Too Many Requests status code along with an error message indicating that too many password change requests have been made. This prevents an attacker from repeatedly changing the password and denying access to the original user.

9. If the user has not made multiple requests within 24 hours, the code updates the password change request time for the user in the passwordChangeRequests map.

10. Finally, the code includes the logic to change the password and sends a success response if the password change is successful.

11. The code starts the Express server and listens on port 3000.

By implementing this mechanism, the code ensures that multiple password change requests from the same user within a 24-hour period are rejected, mitigating the vulnerability.

References