Дисклеймер: Статья носит исключительно информационный характер и не является инструкцией или призывом к совершению противоправных действий. Названия методов и функционала немного видоизменена, чтобы сервис нельзя было угадать. Будем считать, что в городе 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 рубле кражи денег у других пользователей:

  1. Злоумышленник удаляет инвойс жертвы - это нужно, чтобы жертва не заподозрила ничего, увидя 2 одинаковых оплаты немного отличающихся по сумме. Шаг можно пропустить, особенно если у жертвы не 1 созданный заказ, а несколько и оплата хакера будет самой последней.

  2. Злоумышленник добавляет снова оплату чужого заказа по orderid и суммой меньше изначального платежа, например, если у него товаров на сумму 3799, то можно создать 3798 - он создастся у того, кто изначально создавал заказ.

  3. Так как заказ и инвойс связаны. Заказ добавляется на аккаунте жертвы, а инвойс (оплата) прикрепляется к аккаунту хакера (можно убедится проверив документы заказа на стороне жертвы и историю на стороне хакера). Жертва при этом может нажать “оплатить” и провалится в инвойс созданный хакеров (данных хакера в нем нет)

  4. Жертва оплачивает свой заказ

  5. Так как сумма меньше платежа, то заказ не будет полностью оплачен

  6. Биллинг системы не дает доплатить и предлагает отменить операцию жертве

  7. Жертва отменяет платеж - деньги зачисляются на аккаунт хакера, а не плательщика

Сценарий был протестирован на двух тестовых аккаунтах хакере и жертве.

На сколько это реалистично?

Так как orderid int, то можно повторить сценарии для всех существующих заказов и ждать, что кто-то ошибется. Закидываем удочку и ждем денег. Задумайтесь как часто вы перепроверяете сумму после заказа товара на маркетплейсе, увидите ли вы разницу на 1 рубль меньше? Не посчитаете ли что это применился промокод? Атака рассчитана на действия пользователя, но проста в эксплуатации. Если бы это была платежная система, то можно было выводить ошибочные платежи. Но в данном случае можно было набрать товаров в той же системе и ждать, что успеешь быстрее чем заметит антифрод. Вывод средств биллингом предусмотрен не был.

В качестве вывода

Если был найден простой баг - не торопитесь его сдавать, возможно его можно использовать в любопытном векторе атаки. Всем спасибо за внимание.

Комментарии (7)


  1. ArtemiiZ
    07.10.2025 16:06

    До сих пор умиляет, когда в 2025 г. видишь userid и orderid в int. Но, подозреваю, скоро таких примеров станет ещё больше.


    1. tuxi
      07.10.2025 16:06

      Проблема не в инкременте, а в том, что не проверяется принадлежность. Ее надо проверять энивей, хоть у вас идентификатор в виде гуид, хоть в виде лонга. Это сама по себе большая дырка, и гораздо более опасная.


      1. ArtemiiZ
        07.10.2025 16:06

        Естественно это главная проблема, однако каждый раз, в срочном порядке запиливая новую фичу к существующему функционалу, такие дыры возникают повсеместно. Но, при непредсказуемых id этими дырами крайне сложно воспользоваться. Что помогает поправить эту ошибку в будущем без потерь для компании.


        1. tuxi
          07.10.2025 16:06

          Все так, но все же любой чувствительный сервис надо начинать писать с аутентификации/авторизации (области доступности к данным, возможности выполнять те или иные операции), иначе брутфорс творит чудеса, да и создание какой-либо сущности часто не требует никакого ID, так как она создается.


          1. ArtemiiZ
            07.10.2025 16:06

            Полностью согласен. Но IDOR одна из самых "популярных" уязвимостей и по сей день.


      1. xSVPx
        07.10.2025 16:06

        Разве проблема не в том, что вместо отмены транзакции деньги куда-то возвращают ? Да еще не туда откуда получили, а куда-то еще.


        1. tuxi
          07.10.2025 16:06

          Это тоже проблема.