🏁 Race Condition: Когда миллисекунды решают всё

Кратко: Состояние гонки (Race Condition) — это ситуация, когда результат работы системы зависит от того, какой из двух параллельных процессов выполнится первым. Злоумышленник отправляет два запроса почти одновременно, и сервер не успевает обработать первый до того, как придёт второй. В итоге проверка «достаточно ли денег на счете» или «остался ли последний товар» срабатывает дважды, а система списывает деньги или резервирует товар два раза. Актуально для платежей, бонусных систем, тикет-сервисов и любого места, где есть состояние, которое меняется.

▫️ Как это работает Представьте интернет-магазин. На счете пользователя 1000 рублей, товар стоит 1000. Пользователь нажимает «Купить». Система проверяет баланс (1000 >= 1000 → true), затем списывает деньги и отдаёт товар. А теперь пользователь отправляет два запроса на покупку одновременно. В идеальном мире запросы обрабатываются один за другим. Но в высоконагруженной системе с параллельными потоками второй запрос может начать проверку баланса до того, как первый успел списать деньги. Оба запроса видят 1000 рублей, оба считают, что денег достаточно, оба списывают по 1000. Баланс становится -1000, а товар ушёл дважды.

▫️ Реальные примеры Лимитированные скидки: На сайте акция «Первый 100 покупателей получают скидку 50%». Вместо того чтобы стоять в очереди, хакер отправляет 200 запросов одновременно. Система не успевает посчитать, сколько уже активировало, и начисляет скидку всем.

Одноразовый купон: Купон на 500 рублей. В обычной жизни сработал один раз — система его помечает. При состоянии гонки два запроса одновременно проверяют купон, оба видят, что он ещё активен, и оба дают скидку.

Регистрация уникального имени: Имя пользователя «admin» ещё не занято. Хакер отправляет 50 запросов на регистрацию с этим именем. Один из них успевает, остальные падают с ошибкой «уже занято». Но если проверить в момент гонки — несколько запросов могут пройти.

Банковский перевод: Снимаем деньги со счета А и кладём на счёт Б. Если параллельно запустить два перевода с А на Б, можно уйти в минус.

▫️ Где искать · Платежные шлюзы · Системы лояльности и скидочные купоны · Вывод средств · Тикет-системы с ограниченным количеством мест · Регистрация аккаунтов с уникальными именами · Системы голосования (один человек — один голос)

▫️ Как защищаться 1. Блокировки на уровне БД — SELECT ... FOR UPDATE. Перед проверкой баланса блокируем строку с пользователем. Второй запрос подождёт, пока первый не завершится. 2. Атомарные операции — UPDATE users SET balance = balance - 1000 WHERE id = 1 AND balance >= 1000. Одна операция проверяет и списывает одновременно. 3. Уникальные токены — генерируем для каждой операции уникальный идентификатор (nonce). Если второй запрос пришёл с тем же nonce — отклоняем. 4. Оптимистичная блокировка — добавляем поле version в таблицу. При обновлении проверяем, что версия не изменилась. Если изменилась — повторяем операцию с новой версией. 5. Ограничение частоты запросов (Rate Limiting) — от одного пользователя не больше одного запроса в секунду.

▫️ Культурный феномен · «Гонка на грани» — состояние гонки сложно воспроизвести, но легко обнаружить автоматическими инструментами. · Time-of-check to time-of-use (TOCTOU) — классическая проблема. Проверили — прошло время — использовали. За эту микросекунду всё могло измениться. · Тестирование через Burp Intruder — отправляем 20 запросов одновременно с одинаковыми параметрами. Если прошли два — дыра есть.

▫️ Современное положение (2026) Состояние гонки до сих пор находят в крупных программах Bug Bounty. Особенно уязвимы микросервисные архитектуры, где нет единой базы данных, а запросы ходят по сети. MongoDB без транзакций и Redis для кэша — зона риска. Главный вывод: Race Condition — это ошибка проектирования, а не реализации. Если система предполагает конкуренцию за ресурс, она должна быть спроектирована с блокировками или атомарными операциями. Проверка баланса — это не страховка, если следующий запрос придёт раньше, чем списание. #racecondition #состояниегонки #веббезопасность #пентест #багбаунти #тоc

🏁 Race Condition: Когда миллисекунды решают всё | Сетка — социальная сеть от hh.ru