Offering my REDOS tools
See original GitHub issueSummary
I’m a PhD student at Virginia Tech. I’ve just finished polishing up a release of the tools I used in a recent project studying the incidence of REDOS in practice. I’d like to suggest that these tools should be used during CI in any server-side module or application.
Motivation
To give a sense of why we should think about this as a best practice, let me summarize what I found in my study:
- Two vulnerabilities in Node v4 (vuln 1, vuln 2).
- Three vulnerabilities in Python core (vulns 1 and 2, vuln 3)
- A bunch more in npm and pypi (e.g. affecting Marked, Hapi, Django, and MongoDB).
I’ve got an academic paper under submission with all the gory details.
Tools
Here are the tools I’ve developed:
- General repo (includes detectors and a
bin/*
for testing a regex/file/tree/URL). - The vuln-regex-detector npm module to test a regex. This is a “dumb client” and queries a server, see below.
- The eslint-plugin-vuln-regex-detector “eslint plugin”. Uses the vuln-regex-detector module. This “plugin” is really intended for use as a separate CI stage. I just found eslint’s infrastructure useful.
Infrastructure
I’m hosting a server at toybox.cs.vt.edu:8000 that answers queries from the npm modules. The server is documented here.
What I’d like to see
I envision adding this to package.json
of any module that might be used server-side (potential REDOS):
"test:regex": "eslint --plugin vuln-regex-detector --rule '\"vuln-regex-detector/no-vuln-regex\": 2' FILES_YOU_CARE_ABOUT"
and including it during the CI process. Then REDOS issues would be caught by Travis instead of by @ChALkeR.
Issues
While I would love to see these tools adopted by everyone, there are a few potential hiccups if a lot of people start using it:
- The server does not support batched queries, so users have to run separate queries for every regex. This may be a performance issue for clients, especially those with many regexes (like useragent modules).
- The server validates results with a single thread. Some regexes take awhile to validate (performance issue); malicious clients can deliberately craft hard-to-validate regexes (DoS concern).
- The server is currently a single desktop here at Virginia Tech. It might not scale well.
I welcome PRs and suggestions/help with DevOps.
In addition, there are some “whodunnit” questions that might arise if a project starts using these tools during CI. See this discussion, especially this point by @styfle. One concern is that incorporating this into CI might accidentally disclose previously-undiscovered REDOS issues that exist in production.
Documentation
I’ve tried to be thorough in the documentation, but let me know if anything is confusing or seems wrong.
How is this different from safe-regex
?
Existing safe regex detectors (e.g. eslint-plugin-security’s detect-unsafe-regex rule) all rely on the safe-regex module.
The safe-regex
module uses “star height” (nested quantifiers, e.g. /(a+)+/
) as a heuristic to identify vulnerable regexes.
Unfortunately, safe-regex
has three issues:
- It’s unmaintained but implemented incorrectly.
- It is prone to false positives. all regexes with star height > 1 are vulnerable. In my research I found that, in practice, most aren’t.
- More critically, it is also prone to false negatives. In my research I found that most regexes that suffer from catastrophic backtracking do not have star height > 1.
My project only uses detectors that suggest an attack string, and it confirms that the attack string triggers catastrophic backtracking in the language you request (JS-Node, Perl, PHP, Ruby, Python). Look ma, no false positives! But note that if the regex in question is not reachable by client input, then it’s a possible time bomb but not a current REDOS problem.
My project may have false negatives:
- If you extract regexes statically (like the eslint plugin does) then any dynamically-declared regexes (e.g.
new RegExp(p)
) won’t be tested. - If the detectors can’t handle the regex, then the server currently marks the regex as safe.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:15
- Comments:16 (9 by maintainers)
I’m afraid I mostly have library code as well.
These use dynamic RegExps.
@davisjam
Given a source tree,
/.../
style RegExps are easy to find but I wonder if we could get dynamically created RegExps in test-covered code to your analyzer.If a project uses
mocha
to run tests, might a wrapper aroundmocha
do something like the below before running tests so that a posttest script could fire up your analyzer:Using a proxy makes it transparent to
instanceof
so that things like the following behave the same regardless of whether it’s installed.This won’t cover regular expressions created by attacker controlled strings.
It also won’t cover builtins that use the builtin RegExp under the hood like
"string".match('[str]*')
but they could be with more instrumenting.@MarcinHoppe fyi.