Привет! Меня зовут Дмитрий Терёшин, я работаю в отделе AppSec в компании СберМаркет. Моя работа — обеспечивать безопасность наших онлайн сервисов для его клиентов и бизнеса в целом. Недавно мы запустили Bug Bounty программу на BI.ZONE, чтобы независимые багхантеры могли помочь нам в поиске уязвимостей и в честь этого хотим поделиться подборкой багов безопасности в e-com. Для СберМаркета эти уязвимости уже не актуальны, но, не будем скрывать, что некоторые из них мы встретили на своем пути, так что поделимся не только угрозами, но и методами защиты.  За отлов актуальных уязвимостей мы готовы награждать суммой до 250 000 рублей — прочитать подробнее про наш Bug Bounty можно вот тут. Поехали! Самый критичный функционал, который существует в интернет-магазинах, связан с оплатой, промоакциями и аутентификацией. Именно там злоумышленники чаще всего ищут уязвимости. Начну с кейсов фрода с различными механиками оплаты.  Уровень угрозы: Critical В любом интернет-магазине есть функциональность корзины: покупатель набирает в нее товары, размещает заказ, затем оплачивает его. Обычно магазин использует сторонний эквайринг, и, если его API уязвим или интеграция настроена некорректно, злоумышленник может перехватить запрос и в поле amount и подменить сумму в меньшую сторону, например, указать сумму 1 рубль вместо полной суммы и отправить запрос дальше. В итоге оплата произойдет на 1 рубль, но привезут мошеннику полный заказ. Меры защиты: корректно настраивать интеграцию с эквайрингом, проверять итоговую сумму заказа. Уровень угрозы: Critical Следующий кейс — фрод с отменой позиций. В стандартном флоу клиент собирает корзину через интерфейс сайта, далее заказ падает к сборщику — в магазин или на склад, где товары собирают с полок для доставки клиенту.  В функционал некоторых e-com проектов входит возможность отменить или заменить товарную позицию, если она не найдена на полке. В этом случае сборщик удаляет товар из заказа, либо меняет его на другой  — с большей или меньшей стоимостью. В этом случае конечная сумма оплаты появляется только после того как в итоге заказ валидирован сборщиком и клиентом. На этом этапе пользователь уже не должен иметь возможность удалять позиции из корзины, и кнопка «Удалить товар» отсутствует в интерфейсе. Однако злоумышленник может попробовать удалить позицию в тот момент, когда сборщик добавил ее в корзину прямым запросом в API. То есть он видит на сайте, какой товар уже добавлен, а какой еще нет, и, как только сборщик добавляет его, дергает за соответствующую ручку в API и удаляет из корзины, соответственно сумма заказа уменьшается — можно оставить один самый дешевый товар и оплатить только его, а привезут полный заказ. Меры защиты: продумывать возможные уязвимости во флоу заказа на этапе архитектуры сервиса, использовать меры защиты не только на клиенте, но и на сервере Одна из особенностей e-com в том, чтобы регулярно придумывать новые механики стимулирования спроса и возвращения клиентов. Здесь на сцену выходят различные промо. Сперва поговорим о промокодах — механике, которая давно стала общим местом в индустрии. Уровень угрозы: Low Маркетологи часто используют различные сезонные события и праздники как повод, чтобы запустить промо. Привязывая акции к этим событиям, значения промокодов нередко формируются по следующему принципу: предсказуемый префикс (например, на 1 сентября — school, на новый год — newyear) суффикс (короткое число в 3-5 цифр) Ориентируясь на это правило, можно попробовать перебирать промокоды и таким образом сделать себе скидку.  Другой кейс — попробовать какое-нибудь тестовое значение промокода, например, test123456 — иногда такое тоже попадает на прод.Меры защиты: генерировать длинные случайные значения промокодов и устанавливать систему лимитов для защиты от их перебора. Уровень угрозы: Low Следующая уязвимость — это утечки промокодов в сторонние сервисы. У любого интернет-магазина есть админка и доступ к ней как правило хорошо защищён, но если при навигации по админке в URL-ы попадают значения промокодов, то такая информация может утекать на сторону сервиса аналитики (если он забирает URL-ы). Так промокоды могут утекают в неизвестном направлении, и вы не имеете над ними контроль. Другой популярный способ вытащить промокоды и какие-нибудь персональные данные из админки вплоть до доступов админа — использовать stored-XSS в каком-то поле заказа, например «Комментарии к заказу». Если значение этого поля не валидируется, можно подкинуть payload, который заберет cookie админа и отправит её на чужой домен.Меры защиты: отключать аналитику для разделов просмотра промокодов. Уровень угрозы: Medium Эта группа уязвимостей включает в себя разные схемы по неоднократному использованию промокодов. Бизнес-логика любого интернет-магазина подразумевает, что вы применяете только один промокод к одному заказу и таких кейсов быть не должно, но если в бекенде системы лояльности есть уязвимости, то могут случиться следующие неприятные кейсы. Первый способ — зафиксировать ID заказа. Если кто-то знает конкретный промокод, допустим, на 100 рублей, то может попробовать параллельно запустить запрос в несколько потоков. Если промокоды просуммируются, с 10 одновременных запросов кто-то получит скидку на 1000 рублей.  Другой вариант — попробовать применить два разных промокода одновременно и получить двойную скидку. Меры защиты: использовать блокировки и транзакции при запросах в БД. Промокоды — не единственное, что могут рассылать клиентам для стимулирования продаж. Часто в рамках сезонных маркетинговых активностей  или для проверки гипотез по базе клиентов рассылают различные ссылки. Поговорим о том, какие уязвимости могут в них скрываться. Уровень угрозы: Low Часто бывает, что отделу маркетинга нужно  протестировать гипотезу и пользователям присылают ссылку на лендинг, где клиенту нужно в игровой форме выбрать варианты ответа, а в конце он получит подарок — промокод.  Если в эту ссылку, которую рассылают на почту или в sms-ках клиентам, прямо в url вставить промокод, догадливый пользователь может это заметить: скопировать его, вставить и применить — без лишних телодвижений. Меры защиты: отдавать промокод в конце прохождения игровой активности. Уровень угрозы: Medium Допустим, есть рекламный лендинг (например, новогодняя акция) с какой-то активностью (например, розыгрышем). Происходит массовая рассылка акции на клиентов: клиент получает ссылку, переходит по ней, ему предлагают зарегистрироваться по почте на этом лендинге, он вводит почту и ему говорят: «Перейдите по ссылке которая прислана вам на почту, чтобы подтвердить, что она вам принадлежит», — клиент переходит, задает пароль и регистрируется для участия в акции. Обратим внимание на ссылку в письме: внутри есть хвост в виде base64 последовательности. Если его декодировать, там два непредсказуемых параметра: ID пользователя, который инкрементально увеличивается на единичку, то есть это не какой-нибудь непредсказуемый UUID короткий код подтверждения — 6-8 символов. Это строчные латинские буквы с цифрами, то есть пространство перебора довольно небольшое.  На основании этой информации можно предположить следующий ID и зарегистрировать аккаунт на чужую почту. Аналогичная история с восстановлением пароля: если есть кнопка «Восстановить пароль», кто-то может декодировать base64 в конце и увидеть два параметра: код и логин (он же e-mail). Если человек будет знать, что какой-то конкретный e-mail зарегистрирован, он сможем попасть в его аккаунт, перебрав 8 символов, сменить пароль и войти под новым измененным паролем. Меры защиты: генерировать длинные случайные последовательности для ссылок подтверждения email-а/восстановления доступа, делать эти ссылки одноразовыми с коротким сроком жизни и устанавливать лимиты на количество попыток подтвердить почту/восстановить доступ. Уровень угрозы: Medium Для мобильных приложений маркетинговые рассылки часто происходят через sms или push-уведомления. При нажатии на них мобильное приложение поднимает диплинк, открывает во встроенном браузере WebView url, находящийся внутри, и, если там нет никакой валидации по белому списку, кто-то может подсунуть пользователям свою зловредную ссылку. Меры защиты: проверять передаваемые через диплинки url-ы по белому списку. Последнее, о чём хочется поговорить — это аутентификация. Здесь бизнесу всегда приходится идти на компромисс между безопасностью и скоростью для пользователя. Расскажу о нескольких схемах, от которых не сложно защититься при этом не ухудшив клиентский опыт. Уровень угрозы: Critical Пользователей интернет-магазинов обычно не заставляют задавать пароли, чтобы не усложнять им жизнь, то есть там есть только один фактор — вход по одноразовому паролю из sms. Обычно это 5 или 6 цифр. Если нет никаких лимитов по количеству попыток, злоумышленник может перебрать эти 6 символов и попасть в чужой аккаунт, после чего поменять адрес доставки и получать заказы за чужой счет. Другой способ — зафиксировать в sms конкретное значение otp и сделать горизонтальный перебор по номерам телефонов. Если у otp нет срока жизни и он не инвалидируется после использования, базу телефонных номеров можно перебрать и наткнуться на номер, которому этот otp подойдет.  Меры защиты: настроить систему лимитов для методов аутентификации, делать otp действительно одноразовым и с коротким сроком жизни. Уровень угрозы: High Кроме основного мобильного или веб-приложения магазина существуют сервисы для курьеров, сборщиков и других партнеров компании. Например, приложение, в которое будущий партнер загружает свои документы, чтобы передать их отделу кадров и службе безопасности.  Обычно для упрощения входа в такие приложения создают пин-код. Классически это реализуется так: клиент вводит свои креды, ему предлагается создать пин-код при первом входе, он задает его и далее он хранится и проверяется локально, то есть не отправляется на backend.  Соответственно, если есть кнопка «Не могу войти», и при этом там не проверяется старый пин-код, то есть лазейка создать там новый пин и войти. access токен будет успешно отправлен на сервер, и кто-то попадёт в чужой аккаунт. Меры защиты: реализовывать вход по пин-коду с участием бэкенда. Для сброса пин-кода отправлять пользователя на аутентификацию по кредам и делать логаут — инвалидировать текущий refresh токен и подчищать его на клиенте. Уровень угрозы:  Medium Некоторые компании в своих продуктах пытаются защитить свою API через подпись параметров запроса в надежде, что так их API будут абъюзить меньшее количество народа. Это может быть реализовано с помощью HMAC, просто хэша или более сложного алгоритма подписи от всех параметров запроса на клиенте —  подставлять его в запрос и проверять на сервере. Как правило это HMAC, ключ для которого зашит на клиенте. Я встречал такую ситуацию: есть url с параметром sig в конце (без него возвращается Bad Request). По его длине можно предположить, что это хеш MD5, у которого длина дайджеста 128 бит.  Если это мобильное приложение,можно декомпилировать его, посмотреть в исходниках алгоритм, найти функцию, которая формирует подпись, увидеть, что это просто конкатенация всех query параметров запроса с добавлением секретного ключа, который захардкожен в самом приложении, посчитать хеш и отправлять запросы в API. Если это веб-приложение, тоже можно посмотреть в исходниках самой веб-страницы — возможно, там будет зашит такой ключ. Меры защиты: не хардкодить ключи на клиенте. На этом у меня всё. Надеюсь, вы нашли эту статью интересной и смогли извлечь полезные для себя знания. А если вы найдете какую-нибудь уязвимость в СберМаркете, то знаете, куда можно её отправить: https://app.bugbounty.bi.zone/companies/sbermarket/main  Tech-команда СберМаркета завела соцсети с новостями и анонсами. Если хочешь узнать, что под капотом высоконагруженного e-commerce, следи за нами в Telegram и на  YouTube. А также слушай подкаст «Для tech и этих» от наших it-менеджеров.  Ведущий appsec специалист CберМаркете