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

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

