Lab Exercise ReDoS

This is a lab exercise on developing secure software. For more information, see the introduction to the labs.

Task

Learn how to identify and fix a code susceptible to ReDoS attack

Background

Regular expressions are a way to do input validation, checking whether data matches a specific pattern. Poorly designed regular expressions may result in a vulnerability to regular expression denial-of-service (ReDoS) attacks. This attack exploits the fact that most Regular Expression implementations may reach extreme situations, so an attacker can force situations where the regular expression implementation will run for an extremely long time, often exponentially increasing time based on the input size.

In this exercise we are going to fix an input validation that uses regular expressions but is susceptible to a ReDoS attack.

Task Information

The code below sets up handlers for a get request on path /parts. This code could be triggered, for example, by requesting http://localhost:3000/part?id=AB123 (if it was running at localhost and responding to port 3000). If there are no validation errors, the code is supposed to show the part id. If there is a validation error, it responds with HTTP error code 422 ("Unprocessable Content"), a status code suggesting that the request was invalid for some reason, along with an error message.

For this lab we want to fix a regex that is susceptible to a ReDoS attack, applying these countermeasures:

  1. Limit the maximum length of input strings and check the input length first.
    1. After selecting the id parameter (query('id')), use the validation requirement isLength() to limit the string size. We'll need to use the maximum optional parameter to set the maximum size required: isLength({max: YOUR_MAXIMUM})
  2. Modify the regex so that it doesn’t have the worst-case behavior. Be especially wary of any group “(...)” that contains a branch and/or ends with a repeat and is itself repeated.

Use the “hint” and “give up” buttons if necessary.

Interactive Lab ()

Change the code below, adding the mitigation steps to avoid ReDoS:

  1. Limit the maximum length of input strings so the query parameter id is only accepted if it's no longer than 50 characters
  2. Modify the regex so that it doesn’t have the worst-case behavior. The regex should meet this application's part id format requirement that is: one or more uppercase alphanumeric characters.
// Set up Express framework and express-validator library
  const express = require("express");
  const app = express();
  const { query, matchedData, validationResult } =
      require('express-validator');
  
  // Implement requests, e.g., http://localhost:3000/parts?id=1
  app.get('/parts',
  
    (req, res) => { // Execute this code if /parts seen
      const result = validationResult(req); // Retrieve errors
      if (result.isEmpty()) { // No errors
        const data = matchedData(req); // Retrieve matching data
        return res.send(`You requested part id ${data.id}!`);
      }
      res.status(422).send(`Invalid input`);
    })
  


This lab was developed by Camila Vilarinho.