Дисклеймер: Статья носит исключительно информационный характер и не является инструкцией или призывом к совершению противоправных действий. Названия методов и функционала немного видоизменена, чтобы сервис нельзя было угадать. Будем считать, что в городе N уезда K произошла следующая ошибка.
Всем привет. Меня зовут Аня (SavAnna) я работаю AppSec и как хобби занимаюсь багбаунти. Хочу рассказать историю, когда сочетание простых багов, которые может найти каждый приводило к высокому импакту.
В одном сервисе, где можно было создавать и оплачивать заказы были найдены IDOR CRUD счета на оплату (далее инвойс) и особенности связи инвойса с созданным заказом.

Было проверено, что метод не только отдает 200, но и отдает/меняет/удаляет чужие сущности.
Начало исследования
Пользователь создает заказ и может оплатить его в любой удобный момент. После оплаты заказ начинает обрабатываться или пользователь получит оплаченную услугу (например премиум и тд).
Было найдено IDOR удаления заказа и его инвойса DELETE /remove?userid=1334&orderid=1212. Так как идентификаторы userid и orderid int и инкрементные их легко перебрать и очистить заказы в корзине у всех пользователей. Где 1 баг - там и другой и я стала смотреть дальше.
По идентификатору заказа orderid можно было снова добавить его пользователю через создание нового инвойса и попытаться оплатить. Причем был ли уже ранее оплачен заказ или нет - не проверялось. Выставить новый счет на оплату можно было и старых заказов.
Проверила все возможные способы оплаты.

Оплата завершилась корректно. Метод POST /invoice не проверял принадлежность orderid пользователю. Этот метод так же отдавал информацию по заказу стоимость (что позже пригодится нам для атаки), фио первоначального пользователя создавшего заказ и другие его данные.

Я заметила, что в платежных документах прикрепленных к заказу - будет фигурировать фио атакующего, который повторно добавил инвойс. Также метод POST /invoice позволял манипулировать суммой заказа. Была теория, что можно манипулировать суммой заказа и сделать заказ дешевле чем он есть (например набрать на 1000 рублей товаров, а оплатить за 1 рубль), но после оплаты приходило сообщение, что “не весь заказ был оплачен из-за технической ошибки - попробуйте отменить заказ и снова оплатить. Сумма вернется на кошелек”. Инвойс напрямую связан с кошельком и балансом того, кто создал инвойс. Итак рождается сценарий атаки.
Проверенный сценарий атаки на 1 рубле кражи денег у других пользователей:
Злоумышленник удаляет инвойс жертвы - это нужно, чтобы жертва не заподозрила ничего, увидя 2 одинаковых оплаты немного отличающихся по сумме. Шаг можно пропустить, особенно если у жертвы не 1 созданный заказ, а несколько и оплата хакера будет самой последней.
Злоумышленник добавляет снова оплату чужого заказа по orderid и суммой меньше изначального платежа, например, если у него товаров на сумму 3799, то можно создать 3798 - он создастся у того, кто изначально создавал заказ.
Так как заказ и инвойс связаны. Заказ добавляется на аккаунте жертвы, а инвойс (оплата) прикрепляется к аккаунту хакера (можно убедится проверив документы заказа на стороне жертвы и историю на стороне хакера). Жертва при этом может нажать “оплатить” и провалится в инвойс созданный хакеров (данных хакера в нем нет)
Жертва оплачивает свой заказ
Так как сумма меньше платежа, то заказ не будет полностью оплачен
Биллинг системы не дает доплатить и предлагает отменить операцию жертве
Жертва отменяет платеж - деньги зачисляются на аккаунт хакера, а не плательщика
Сценарий был протестирован на двух тестовых аккаунтах хакере и жертве.
На сколько это реалистично?
Так как orderid int, то можно повторить сценарии для всех существующих заказов и ждать, что кто-то ошибется. Закидываем удочку и ждем денег. Задумайтесь как часто вы перепроверяете сумму после заказа товара на маркетплейсе, увидите ли вы разницу на 1 рубль меньше? Не посчитаете ли что это применился промокод? Атака рассчитана на действия пользователя, но проста в эксплуатации. Если бы это была платежная система, то можно было выводить ошибочные платежи. Но в данном случае можно было набрать товаров в той же системе и ждать, что успеешь быстрее чем заметит антифрод. Вывод средств биллингом предусмотрен не был.
В качестве вывода
Если был найден простой баг - не торопитесь его сдавать, возможно его можно использовать в любопытном векторе атаки. Всем спасибо за внимание.
ArtemiiZ
До сих пор умиляет, когда в 2025 г. видишь userid и orderid в int. Но, подозреваю, скоро таких примеров станет ещё больше.
tuxi
Проблема не в инкременте, а в том, что не проверяется принадлежность. Ее надо проверять энивей, хоть у вас идентификатор в виде гуид, хоть в виде лонга. Это сама по себе большая дырка, и гораздо более опасная.
ArtemiiZ
Естественно это главная проблема, однако каждый раз, в срочном порядке запиливая новую фичу к существующему функционалу, такие дыры возникают повсеместно. Но, при непредсказуемых id этими дырами крайне сложно воспользоваться. Что помогает поправить эту ошибку в будущем без потерь для компании.
tuxi
Все так, но все же любой чувствительный сервис надо начинать писать с аутентификации/авторизации (области доступности к данным, возможности выполнять те или иные операции), иначе брутфорс творит чудеса, да и создание какой-либо сущности часто не требует никакого ID, так как она создается.
ArtemiiZ
Полностью согласен. Но IDOR одна из самых "популярных" уязвимостей и по сей день.
xSVPx
Разве проблема не в том, что вместо отмены транзакции деньги куда-то возвращают ? Да еще не туда откуда получили, а куда-то еще.
tuxi
Это тоже проблема.