Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regular expression injection - (ReDos) #316

Open
RashidKhanPathan opened this issue Jul 13, 2024 · 0 comments
Open

Regular expression injection - (ReDos) #316

RashidKhanPathan opened this issue Jul 13, 2024 · 0 comments

Comments

@RashidKhanPathan
Copy link

Regular expression injection

Constructing a regular expression with unsanitized user input is dangerous as a malicious user may be able to modify the meaning of the expression. In particular, such a user may be able to provide a regular expression fragment that takes exponential time in the worst case, and use that to perform a Denial of Service attack.

  • benchmarks/index.js:41
function start() {
  var re = process.argv[2] ? new RegExp(process.argv[2], 'i') : /./; //  Vulnerable Code

  benchmarks.filter(function(b) {
    return re.test(b.name);
  }).forEach(function(b) {
    b.start();
  });
}

PoC

/*
- ReDos PoC
Note: running this poc on system can cause hang or crash try on vm
also this is just for testing vulnerable the regular expression code
*/

const { exec } = require('child_process');

function start() {
  var re = process.argv[2] ? new RegExp(process.argv[2], 'i') : /./;

  const benchmarks = [
    { name: 'benchmark1' },
    { name: 'benchmark2' },
    { name: 'benchmark3' }
  ];

  benchmarks.filter(function(b) {
    return re.test(b.name);
  }).forEach(function(b) {
    console.log(b.name);
  });
}

// PoC for ReDoS attack
if (require.main === module) {
  const complexRegex = '^(a+)+$';
  exec(`node ${process.argv[1]} "${complexRegex}"`, (error, stdout, stderr) => {
    if (error) {
      console.error(`exec error: ${error}`);
      return;
    }
    console.log(`stdout: ${stdout}`);
    console.error(`stderr: ${stderr}`);
  });
}

start();
More Example

The following example shows a HTTP request parameter that is used to construct a regular expression without sanitizing it first

var express = require('express');
var app = express();

app.get('/findKey', function(req, res) {
  var key = req.param("key"), input = req.param("input");

  // BAD: Unsanitized user input is used to construct a regular expression
  var re = new RegExp("\\b" + key + "=(.*)\n");
});

Instead, the request parameter should be sanitized first, for example using the function _.escapeRegExp from the lodash package. This ensures that the user cannot insert characters which have a special meaning in regular expressions.

var express = require('express');
var _ = require('lodash');
var app = express();

app.get('/findKey', function(req, res) {
  var key = req.param("key"), input = req.param("input");

  // GOOD: User input is sanitized before constructing the regex
  var safeKey = _.escapeRegExp(key);
  var re = new RegExp("\\b" + safeKey + "=(.*)\n");
});

or you can use safe-regex to avoid this issue

const safeRegex = require('safe-regex');

function start() {
  var reInput = process.argv[2];
  var re;

  if (reInput && safeRegex(new RegExp(reInput, 'i'))) {
    re = new RegExp(reInput, 'i');
  } else {
    re = /./;
  }

  const benchmarks = [
    { name: 'benchmark1' },
    { name: 'benchmark2' },
    { name: 'benchmark3' }
  ];

  benchmarks.filter(function(b) {
    return re.test(b.name);
  }).forEach(function(b) {
    console.log(b.name);
  });
}

start();
Recommendation

Before embedding user input into a regular expression, use a sanitization function such as lodash's _.escapeRegExp to escape meta-characters that have special meaning.

References

ReDos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant