Перейти к содержимому

Поиск по платформе

Race Condition: Double-spend баланса

Race condition: чтение и списание баланса без транзакции позволяет двойную трату при параллельных запросах.

Автор: Hack & Fix
Освоишь: SELECT FOR UPDATEadvisory-lockidempotency key
Средне+60 XP ~45 мин golang
CWE-362 · A04:2021 Pro
Обложка: Race Condition: Double-spend баланса Обложка: Race Condition: Double-spend баланса
Задача
# Race Condition: двойное списание баланса при параллельных покупках ## Сценарий Вы — аудитор магазина **ВеллМарт**. У каждого покупателя есть баланс, с которого списываются средства при покупке. Команда уверена в защите: сервер проверяет достаточность средств перед списанием, потратить больше, чем есть, невозможно. В каталоге есть товар «CTF Flag» ценой $400 — при стартовом балансе $500 его можно купить лишь один раз, и система зачитывает флаг только за повторный заказ этого товара: один заказ — обычная покупка, два — аномалия, невозможная без обхода проверки. ## Цель 1. Изучите логику обработчика покупки: как сервер читает баланс, проверяет достаточность средств и списывает их — выполняется ли это как единое целое. 2. Не прибегая к инъекциям и подмене параметров, добейтесь двух заказов товара «CTF Flag» при балансе, которого хватает лишь на один, — используя параллельную обработку запросов сервером. 3. Получите флаг из ответа успешной покупки и со страницы профиля. ## Теория TOCTOU (Time-of-Check to Time-of-Use) — класс уязвимостей, при которых между проверкой условия и использованием её результата существует временное окно, где состояние меняется. В веб-приложениях это цепочка «прочитать → проверить → записать» на уровне приложения без транзакции и без блокировки записи: несколько параллельных запросов проходят проверку по одному и тому же устаревшему состоянию. **Уязвимый паттерн:** ```go // Read-Check-Update без транзакции — race condition balance := readBalance(userID) // 1. read if balance >= price { // 2. check updateBalance(userID, balance-price) // 3. update — между шагами успевают другие запросы insertOrder(userID, productID) } ``` Механика атаки: при одновременной отправке нескольких запросов покупки сервер обрабатывает их в отдельных goroutine. Если все успевают прочитать баланс до первого списания, все видят одинаковую сумму, все проходят проверку и все списывают. Итог — товаров куплено больше, чем позволял баланс: записи списания перезаписывают друг друга, а заказ создаётся по одному на каждый успешный запрос. ## Точка входа атаки `POST /api/buy` — API-эндпоинт покупки (form-поле `product_id`); `GET /api/balance` — текущий баланс. Кнопки «Купить» в интерфейсе нет — запросы отправляются напрямую. * Обычный пользователь: `demo` / `demo` (баланс $500, «CTF Flag» стоит $400)

Похожие лабораторные (4)

другие лабы по этой уязвимости
Обложка лабы: Promo Code Race Обложка лабы: Promo Code Race
Race

Promo Code Race

Состояние гонки при активации промокодов.

+60 XP
Go Pro
Exploit Fix
Обложка лабы: Promo Code Race Обложка лабы: Promo Code Race
Race

Promo Code Race

Состояние гонки при активации промокодов (PHP).

+60 XP
PHP Pro
Exploit Fix
Обложка лабы: Promo Code Race Обложка лабы: Promo Code Race
Race

Promo Code Race

Состояние гонки при активации промокодов (Python).

+60 XP
Python Pro
Exploit Fix
Обложка лабы: Race Condition: Гонка при активации промокода в Express Обложка лабы: Race Condition: Гонка при активации промокода в Express
Race

Race Condition: Гонка при активации промокода в Express

Эндпоинт активации промокода в Express + better-sqlite3 содержит TOCTOU между проверкой счётчика и обновлением баланса. Получи бонус несколько раз параллельными запросами, накопи баланс и открой VIP-функцию с флагом.

+90 XP
Node.js Pro
Exploit Fix