Hacktricks-skills redos-pentest
Use this skill whenever you need to identify, test, or exploit Regular Expression Denial of Service (ReDoS) vulnerabilities. Trigger this skill when analyzing regex patterns for security issues, testing web applications for ReDoS, generating ReDoS payloads, or auditing code for vulnerable regex patterns. Use it for CTF challenges, bug bounty hunting, or security assessments involving regular expressions.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/regular-expression-denial-of-service-redos/SKILL.MDReDoS Pentesting Skill
A skill for identifying, testing, and exploiting Regular Expression Denial of Service (ReDoS) vulnerabilities in applications and codebases.
What is ReDoS?
Regular Expression Denial of Service (ReDoS) occurs when crafted input causes a regex engine to perform catastrophic backtracking, consuming excessive CPU time and potentially freezing or crashing the application. This happens when:
- The regex contains nested or overlapping quantifiers (e.g.,
,(a+)+
)(.*a){100} - The input creates many ambiguous matching paths
- The engine must backtrack through exponential possibilities before failing
When to Use This Skill
Use this skill when:
- You need to audit regex patterns for security vulnerabilities
- You're testing a web application for ReDoS susceptibility
- You're working on a CTF challenge involving regex injection
- You need to generate ReDoS payloads for penetration testing
- You want to measure the severity of a suspected ReDoS vulnerability
- You're reviewing code that processes user input with regex
Identifying Vulnerable Patterns
Classic Evil Regex Patterns
These patterns are commonly vulnerable to ReDoS:
| Pattern | Why It's Vulnerable |
|---|---|
| Nested quantifiers on same character |
| Repetition with overlapping alternation |
| `(a | aa)+` |
| `(a | a?)+` |
(x > 10) | Large repetition of greedy match |
| Multiple quantifiers with overlap |
Red Flags to Look For
- Nested quantifiers:
,(a+)+((.*)*)* - Quantified groups with quantifiers inside:
([a-z]+)* - Alternation with overlap:
,(a|aa)+(a|a?)+ - Large repetition counts:
(.*a){100} - Multiple quantifiers in sequence:
\w*_*\w*$
Testing for ReDoS
Step 1: Generate Test Payloads
Use the timing harness script to test if a pattern is vulnerable:
python scripts/redos_timing_test.py "(a+)+$" "aaaaaaaaaaaaaaaaaaaaaaaa!"
Or test with increasing input lengths to observe exponential growth:
python scripts/redos_timing_test.py "(\w*_)*\w*$" --lengths 8 10 12 14 16 18 20
Step 2: Analyze Results
- Safe: Linear or constant time growth
- Vulnerable: Exponential or high-polynomial growth (time doubles or more with small input increases)
- Critical: Pattern freezes or times out with moderate input (50+ characters)
Step 3: Verify with Tools
Use automated tools to scan codebases:
# Install regexploit pip install regexploit # Scan Python code regexploit-py /path/to/code/ # Scan JavaScript code regexploit-js /path/to/code/ # Interactive analysis regexploit
ReDoS Payload Generation
When You Control Both Input and Regex
Use these generic payloads to test vulnerable patterns:
// Test payloads const payloads = [ "(a|a?)+$", "(\\w*)+$", "(a*)+$", "(.*a){100}$", "([a-zA-Z]+)*$", "(a+)*$" ]; // Test input const testInput = "aaaaaaaaaaaaaaaaaaaaaaaaaa!";
String Exfiltration via ReDoS (Blind Regex Injection)
When you control the regex but not the input (e.g., flag validation), use timing-based exfiltration:
Pattern 1 (PortSwigger technique):
^(?=<flag>)((.*)*)*salt$
Pattern 2 (CTF technique):
<flag>(((((((.*)*)*)*)*)*)*)!
Pattern 3 (Simple brute force):
^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$
How it works:
- The regex matches the flag prefix
- If the guess is correct, the nested quantifiers cause catastrophic backtracking
- The page freezes or times out
- If the guess is wrong, the regex fails quickly
- Use timing differences to exfiltrate characters one by one
Engine-Specific Notes
JavaScript (Browser/Node.js)
- Built-in
is backtracking and commonly exploitableRegExp - Works when both regex and input are attacker-influenced
- Browser tabs can freeze, Node.js processes can hang
Python
module is backtrackingre- Long ambiguous runs + failing tail = catastrophic backtracking
- Use
module orregex
for safer alternativesre2
Java
is backtrackingjava.util.regex- If you control input: look for complex validators
- If you control patterns: ReDoS is usually trivial
- Use
for linear-time alternativesRE2J
Safe Engines (ReDoS-Resilient)
- RE2 (C++, Java, Go, JavaScript ports)
- Rust regex crate
- Hyperscan
- These use finite automata and guarantee linear time
Fixing Vulnerable Patterns
Strategy 1: Use Atomic Groups
# Vulnerable (a+)+ # Fixed (if engine supports atomic groups) (a++)+
Strategy 2: Use Possessive Quantifiers
# Vulnerable (a+)+ # Fixed (a++)+
Strategy 3: Simplify the Pattern
# Vulnerable ([a-zA-Z]+)* # Fixed [a-zA-Z]+
Strategy 4: Use Non-Backtracking Engines
- Replace
withre
module in Pythonregex - Use
in Java/Go/JavaScriptRE2 - Use Rust's
crateregex
Strategy 5: Add Length Limits
# Before processing if len(user_input) > 1000: raise ValueError("Input too long")
Quick Reference
Common Vulnerable Patterns
| Pattern | Fix |
|---|---|
| or |
| |
| `(a | aa)+` |
| Limit input length |
| |
Testing Commands
# Test single pattern python scripts/redos_timing_test.py "(a+)+$" "aaaaaaaaaaaaaaaaaaaaaaaa!" # Test with length progression python scripts/redos_timing_test.py "(\w*_)*\w*$" --lengths 8 10 12 14 16 18 20 # Scan codebase regexploit-py /path/to/code/ regexploit-js /path/to/code/