logo

Database

Need

Prevention of repeated requests causing service outages

Context

• Usage of TypeScript for statically typed JavaScript development

• Usage of Express for building web applications and APIs

Description

1. Non compliant code

import express from 'express';

const app = express();

app.get('/search', (req, res) => {
  const query = req.query.q;

  for (let i = 0; i < 1000000000; i++) {...

The vulnerability in the given code is a Symmetric Denial of Service (DoS) vulnerability. This vulnerability occurs because the server is performing a long-running computation in the request handler for the '/search' route. In the code, when a GET request is made to the '/search' route, the server receives a query parameter 'q' from the request. However, instead of immediately processing the query and sending the search results, the code simulates a long-running process by executing a for loop that performs heavy computation. This can lead to a denial of service situation because the server is unable to handle other requests while it is busy with the long-running computation. If multiple clients make simultaneous requests to the '/search' route, the server's resources can be exhausted, causing the server to become unresponsive or slow down significantly. An attacker can exploit this vulnerability by repeatedly sending requests to the '/search' route, effectively overwhelming the server and denying access to legitimate users. To mitigate this vulnerability, it is recommended to set a timeout for the long-running computation. This way, if the computation takes too long, the server can cancel it and respond with an appropriate error message or terminate the request.

2. Steps

• Analyze the code to identify the heavy computation that is causing the long-running process.

• Optimize the heavy computation to reduce the processing time.

• Implement a timeout mechanism to limit the maximum processing time for the search request.

• Return an appropriate response if the timeout is reached, indicating that the request took too long to process.

• Update the code to handle the timeout and return a response accordingly.

• Test the updated code to ensure it functions as expected and does not cause denial of service vulnerabilities.

3. Secure code example

import express from 'express';

const app = express();

app.get('/search', (req, res) => {
  const query = req.query.q;

  const timeout = setTimeout(() => {...

The fixed code addresses the vulnerability by implementing a timeout mechanism for long-running requests. In the code, we import the Express framework and create an instance of the application. We define a route for the '/search' endpoint using the HTTP GET method. Within the route handler, we first extract the query parameter from the request object. To prevent the server from becoming unresponsive due to a long-running process, we set a timeout of 5 seconds using the `setTimeout` function. If the request takes longer than 5 seconds to process, the timeout callback function will be executed. Next, we simulate a long-running process by using a for loop that performs heavy computation. This is where the actual processing of the request takes place. Before sending the response, we clear the timeout using the `clearTimeout` function. This ensures that if the request completes within the timeout period, the timeout callback function will not be executed. Finally, we send the response with the search results. By setting a timeout and clearing it before sending the response, we ensure that requests that take too long to process will be terminated and the server will not be overwhelmed.