FlawOpen

flawopen.com/Что такое ReDoS/Explained

Что такое ReDoS (катастрофический возврат)?

CWE-1333: Inefficient Regular Expression ComplexityСправочная страница
Краткий ответ

Механизм регулярных выражений с возвратом может проверять разные способы разделить одну строку после неудачного совпадения. Для некоторых неоднозначных шаблонов число попыток растёт экспоненциально с длиной ввода. Задержка зависит от шаблона, механизма, размера ввода, параллелизма и ограничений ресурсов; повторные дорогие запросы могут исчерпать возможности сервиса.

УЯЗВИМЫЕ ШАБЛОНЫ
# Nested quantifier
^(a+)+$

# Overlapping alternatives, quantified
^(a|aa)+$

# A long matching prefix plus a final mismatch can
# force extensive retries in vulnerable engines.
# Do not benchmark this with attacker-sized input.
БЕЗОПАСНЕЕ
# Bound input before matching, then use a simple
# full-string identifier rule with no nested ambiguity.
import re

IDENTIFIER = re.compile(r"[a-z0-9]{1,64}\Z")

def valid_identifier(value: str) -> bool:
    if not isinstance(value, str) or len(value) > 64:
        return False
    return IDENTIFIER.fullmatch(value) is not None

# A bound reduces worst-case work; still set request
# size, concurrency, and execution-time limits.

Почему возврат резко увеличивается

Шаблон вроде ^(a+)+$ неоднозначен для механизма с возвратом: aaaa можно разделить между вложенными квантификаторами несколькими способами. Завершающий несовпадающий символ может заставить механизм перебрать варианты, прежде чем он отклонит всю строку.

Для таких шаблонов число проверяемых путей может экспоненциально расти с длиной совпавшего префикса перед несовпадением. Это зависит от конкретной пары «шаблон — механизм», а не от любых регулярных выражений или сбоев. При параллельных запросах важны и короткие строки; ограничивайте размер ввода, параллелизм и время.

Где недоверенные данные попадают в регулярные выражения

Проверка ввода — очевидный случай, но риск также скрыт в обработке User-Agent и других заголовков, журналов, Markdown и подсветки синтаксиса, маршрутизации URL, фильтров контента и правил WAF, а также в библиотеках, применяющих regex к переданным полям. Популярные пакеты публиковали уведомления о ReDoS, поэтому зависимости важны не меньше собственных шаблонов.

Частые вопросы

Which languages are affected?

Риск зависит от механизма и шаблона, а не только от языка. Некоторые механизмы с возвратом для отдельных шаблонов проверяют чрезмерное число вариантов. Документация Go для regexp гарантирует линейное время по длине ввода. Библиотека Rust regex указывает O(m·n) для одного поиска (m — размер шаблона, n — размер ввода), то есть линейно по n при фиксированном шаблоне; у итераторов повторного поиска другие худшие оценки. Эти механизмы не поддерживают, например, обратные ссылки, мешающие таким гарантиям.

Is a length limit enough on its own?

Ограничение уменьшает возможный объём работы, но безопасное значение зависит от шаблона, механизма, частоты запросов и бюджета сервиса. Исправляйте неоднозначные шаблоны и вводите лимиты до разбора или сопоставления.

How do I find vulnerable patterns?

Используйте статический анализатор с проверкой ReDoS и сверяйте результаты с фактическим механизмом. Ищите повторяемые группы с вложенными повторениями или альтернативами с общими префиксами; затем тестируйте ограниченные данные со строгим таймаутом в изолированной среде.

Can I add a timeout instead?

Поддержка таймаутов зависит от среды выполнения и API. В .NET задавайте явный таймаут для сопоставления с недоверенным вводом. В остальных случаях проверяйте документацию конкретного механизма; выберите более безопасный механизм или переработайте шаблон, если применимого таймаута нет. Таймаут дополняет ограничения размера и параллелизма, но не делает неоднозначный шаблон эффективным.

Источники

См. также ReDoS в Node.js: регулярные выражения и CVE-2026-83606