Перейти к содержимому
← Каталог nodejs SSTI

ReDoS: catastrophic backtracking в URL-валидаторе профиля

Express SecureShop валидирует адрес персонального сайта пользователя через регулярное выражение с вложенными квантификаторами в последней метке хоста. Тщательно подобранная строка вызывает catastrophic backtracking движка V8: event loop блокируется на секунды, инцидент фиксируется в журнале и admin-эндпоинт выдаёт флаг.

hardnodejsPro
Задача
# SecureShop: блокировка event loop через регулярное выражение в валидаторе URL профиля ## Что это за уязвимость **SecureShop** — внутренний Express-магазин на Node.js с разделом профиля пользователя. У каждого пользователя есть поле «домашняя страница» (`website`), и перед сохранением сервер «проверяет корректность» этого URL. Кажется безобидной валидацией, но регулярное выражение в этом месте написано так, что движок V8 при специально подобранной строке уходит в экспоненциальное число шагов — и пока он там «думает», поток событий Node.js полностью заморожен и никакой другой запрос на этом процессе не обслуживается. Это и есть Regular Expression Denial of Service (ReDoS) в варианте *catastrophic backtracking*. В отличие от классических DoS-атак на сетевой канал или память, здесь достаточно одного маленького HTTP-запроса с тщательно подобранной короткой строкой, чтобы воркер встал колом на секунды. На однопроцессной Node-инсталляции это эквивалентно «выключи продакшен на минуту одним запросом из обычного пользовательского аккаунта». В лабе сделано так, что событие «валидация заняла слишком много времени» само по себе считается incident по доступности: сервер фиксирует факт в таблице инцидентов и публикует справочный токен (CTF-флаг) в админ-эндпоинте отчёта об инцидентах. На реальном сервисе там вместо токена была бы ссылка в SIEM и pager на on-call инженера — для лабы этого вектора достаточно, чтобы у студента был чёткий маркер успешной эксплуатации. ## Где искать После входа на платформе доступны: - `GET /profile` — страница профиля, форма «Save website». - `POST /api/profile/website` — REST-эндпоинт обновления, принимает JSON `{ "website": "..." }`, отвечает `{ "valid": boolean, "duration_ms": number, ... }`. Именно этот хэндлер выполняет уязвимую регулярную проверку перед записью значения в БД. - `GET /admin/dos-incident` — отчёт о зафиксированных инцидентах доступности. После первого детектирования ReDoS возвращает поле `flag` с токеном формата `flag{...}`. Учётная запись для входа: `demo` / `demo`. ## Что важно понимать - Движок регулярных выражений V8 (как и большинство традиционных backtracking-движков) — NFA: при неоднозначной грамматике он перебирает все альтернативные разбиения, пока не найдёт совпадение или окончательно не откажет. - Опасный признак — *неоднозначность*: один и тот же символ может быть «съеден» разными частями шаблона. Канонические сигнатуры — `(a+)+`, `(a|a)+`, любой вложенный `+`/`*` внутри ещё одного `+`/`*`. - Event loop в Node.js однопоточный: пока V8 backtrack-ит, сервер не отвечает никому из других клиентов на этом процессе. Локальная задержка валидации превращается в DoS уровня всего инстанса. - Для эксплуатации не нужны привилегии: атакующему достаточно валидного аккаунта и одного HTTP-запроса. Триггер — сам факт затянувшейся валидации, который сервер фиксирует как инцидент. ## Что нужно сделать 1. Авторизуйтесь как `demo` / `demo` и откройте страницу профиля. 2. Сформируйте такое значение «website», чтобы серверная валидация заняла секунды (а не миллисекунды) и зафиксировала incident — `duration_ms` в ответе будет больше порога фиксации. 3. Откройте отчёт об инцидентах. В JSON-ответе появится поле `flag` формата `flag{...}` — это и есть флаг лабораторной. Уязвимость живёт целиком на сервере, в одном файле — обработчике профиля. Никаких сложных payload'ов, протоколов или цепочек не требуется: суть атаки умещается в одну особую строку и понимание того, как backtracking-движок исследует пространство сопоставлений.
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru