Symmetric denial of service
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.
References
• 003. Symmetric denial of service