Содержание статьи
Это исследование получило первое место на Pentest Award 2025 в категории «Hack the logic». Соревнование ежегодно проводится компанией Awillix.
warning
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Race Condition (состояние гонки) — это уязвимость в веб‑приложениях, которую относят к группе уязвимостей бизнес‑логики. Если ты аппсек, багхантер или пентестер, то тебе будет полезно в этом механизме разобраться.
Как эта уязвимость выглядит в реальных веб‑приложениях? В голову сразу приходит такой сценарий: у меня есть десять рублей, и товар стоит десять рублей, можно одновременно отправить два запроса на его оплату, чтобы веб‑приложение одновременно поработало с 10-рублевым балансом, и если оба пройдут, то получится два товара за десять рублей, итого — один бесплатный товар. Или, например, такое: в кино остался последний билет, а нас двое, можно отправить два запроса на покупку билета одновременно, и если все пройдет как надо, то в ответе будет два билета. По крайней мере такие сценарии и еще пару похожих мне предложил DeepSeek R1.
Такие сценарии работают за счет эксплуатации одной конечной точки (одного запроса), которая неправильно работает с нужными переменными — балансом кошелька или количеством непроданных билетов. Один обработчик запроса параллельно достает баланс или количество билетов из базы данных для двух запросов и видит, что для обоих запросов ему возвращается десять рублей или один последний билет, после чего он радостно идет выдавать покупку, так как денег хватает или билет остался. Профит!
С помощью такой уязвимости мы как бы перескакиваем барьер нулевого баланса и уводим переменную в отрицательные значения (в некоторых случаях наоборот — увеличиваем количество и перескакиваем верхнюю границу).
А что, если я скажу: это лишь вершина айсберга и меньшая часть потенциала уязвимости?
Заезд первый. Новичок в гонках забирает свой первый контракт
Мы привыкли использовать Race Condition, чтобы перепрыгнуть граничное состояние, где какая‑то переменная равна нулю, но, если действовать оперативно, можно перепрыгнуть целый кусок логики. Давай в качестве первого примера разберем простой и понятный сценарий, он поможет понять суть.

Наш первый заезд будет на трассе с оплатой корзины. Вот как происходит оплата.
- Пользователь добавляет в корзину или убирает оттуда товары на сайте интернет‑магазина, тем самым формируя заказ.
- Пользователь отправляет запрос на оплату корзины, и ему в ответ возвращается ссылка, по которой фронтенд перенаправляет его в сторону интернет‑эквайринга (прием онлайн‑платежей as a service).
- Магазин блокирует изменение статуса корзины (допустим, Waiting for payment) — ее наполнение теперь нельзя изменить.
- Пользователь оплачивает корзину, и эквайринг возвращает сайту информацию об успешной оплате.
- Получив подтверждение от эквайринга, сайт добавляет в личный кабинет пользователя оформленный заказ.
Вроде все хорошо, но давай посмотрим на процесс с другой стороны. Мы здесь можем повлиять только на первый и второй шаги, а именно изменение состояния корзины и отправку корзины на оплату. Будем считать, что с оплатой на четвертом шаге все окей, так как это сторонний сервис.
Но что, если в нашей гонке мы запустим одновременно добавление товара в корзину и ее оплату? Сможем ли мы между вторым и третьим шагом добавить свой товар так, чтобы состояние корзины изменилось за «мгновение» до отправки запроса в эквайринг? Сможет ли веб‑сайт успеть добавить в корзину товар и одновременно сделать так, чтобы в сумму, которую он передаст интернет‑эквайрингу, вошла стоимость этого товара?
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее