Technical information leak - Errors - TypeScript

Technical information leak - Errors - TypeScript

Need

Prevention of technical information leaks through error messages

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

app.get('/api/user/:id', (req, res) => {
  const userId = req.params.id;
  const user = getUserById(userId);

  if (!user) {
    throw new Error('User not found');
  }

  res.json(user);
});

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

function getUserById(id: string) {
  // Fetch user from the database based on the given ID
  // This is just a placeholder function
  return {
    id,
    name: 'John Doe',
    email: 'john.doe@example.com',
    password: 'password123',
  };
}
        
        

The vulnerability in this code is a technical information leak. When the server receives a request to the /api/user/:id endpoint, it retrieves the user information based on the provided id parameter. If the user is not found, the code throws an error with the message 'User not found'.

The problem is that this error message reveals sensitive technical information about the server implementation. It exposes details about the error and potentially exposes the structure of the code, such as the function name and the fact that the server is using Express.

An attacker could exploit this vulnerability by sending massive requests to the endpoint or by sending a large amount of characters in the request body. This could potentially cause the server to throw multiple errors, leaking more technical information with each error.

To mitigate this vulnerability, it is recommended to use generic error messages instead of providing specific technical information. This way, the error messages do not reveal any sensitive details about the server implementation and make it harder for attackers to gather information.

Steps

  • Remove the line that throws an error with specific information ('throw new Error('User not found')')
  • Instead of throwing an error, send a generic error response to the client `('res.status(404).json({ error: 'User not found' })')`
  • Update the getUserById function to handle errors gracefully and return null if the user is not found

Compliant code

        import express from 'express';

const app = express();

app.get('/api/user/:id', (req, res) => {
  const userId = req.params.id;
  const user = getUserById(userId);

  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }

  res.json(user);
});

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

function getUserById(id: string) {
  // Fetch user from the database based on the given ID
  // This is just a placeholder function
  const user = {
    id,
    name: 'John Doe',
    email: 'john.doe@example.com',
    password: 'password123',
  };

  if (!user) {
    return null;
  }

  return user;
}
        
        

The fixed code addresses the vulnerability by implementing the following measures:

1. The code uses the Express framework to create a server and handle HTTP requests.

2. The /api/user/:id endpoint is defined as a GET request handler. It expects a parameter id in the URL path.

3. Inside the request handler, the getUserById function is called to fetch the user from the database based on the provided id. This function is a placeholder and needs to be implemented to interact with the actual database.

4. If the user object is not found (i.e., null), the code returns a JSON response with a 404 status code and a generic error message: "User not found". This prevents leaking any technical information about the error.

5. If the user object is found, it is returned as a JSON response with a 200 status code. Again, no technical information is exposed in the response.

6. The server is set to listen on port 3000, and a console log message is printed to indicate that the server is running.

By using generic error messages and avoiding the inclusion of technical information in the response, the code mitigates the risk of leaking sensitive information to potential attackers.

References