Предисловие
Как известно, в России почти каждая первая финансовая организация позиционирует себя как софтверную IT-компанию, а не просто как "банк" или "платежная система". Сегодня речь пойдет о ЮМани — подразделении Сбера, IT-гиганта всея руси.
До того, как ЮМани стал тем, чем он сейчас является, сервис долгое время существовал как продукт Яндекса под названием Яндекс.Деньги — в те времена у меня был очень приятный опыт взаимодействия с техническим руководством компании, я неоднократно (будучи security researcher'ом) сообщал им об уязвимостях, а они, в свою очередь, оперативно это исправляли, давали обратную связь и вознаграждали за такую работу, аналогично тому, как это делали и зарубежные крупные IT-компании в рамках взаимодействия с white-hat хакерами. Такая вот IT-компания здорового человека. Но с тем, как Сбербанк поглотил Яндекс.Деньги и провёл ребрендинг, проект стал превращаться, скорее, в IT-компанию курильщика: взаимодействовать с представителями проекта в соц. сетях стало практически невозможно, какие-либо данные на страницах о Bug Bounty программах были удалены и даже ни одного email-адреса не оставили в качестве средства связи для сообщения об уязвимостях.
Пару месяцев назад я обнаружил уязвимость в сервисе ЮМани (о ней чуть позже) и сразу же решил сообщить о ней. Однако никаких релевантных этому форм связи, email-адресов и т.д. я не обнаружил — способов безопасно сообщить о такой уязвимости элементарно не было на официальном сайте сервиса. Я попытался связаться с людьми, работающими в ЮМани, однако, опять же, я не получил никакой обратной связи. На этом моменте я, что называется, "забил", в надежде, что ошибку исправят и без меня, ведь не может же такая дырень оставаться незамеченной долго, правда? Спойлер: может.
В один из прекрасных летних вечеров я воспользовался этой платежной системой в очередной раз, ну и, в рамках праздного интереса, решил проверить, "а не исправили ли". Как выяснилось, нет. Не исправили. И вот получается, что уже на протяжении очень продолжительного периода времени (около 2 месяцев) мне известно о критической уязвимости в сервисе, которую исправить можно было бы за 1-2 минуты (буквально). И тут я решаю связаться хоть каким-то способом с кем-то из этой организации. Кое-как откопал контакты HR-менеджера, с которой состоялся диалог:
Как можно догадаться из переписки выше, я отправил отчёт об уязвимости в ЮМани через этот очень сомнительный сервис. Но о нём позже. Пока поговорим о самой уязвимости.
Примечание: На момент написания этой статьи уязвимость исправлена, поэтому её публичное раскрытие не несёт угрозы для сервиса и/или его пользователей, а скорее наоброт — дает конкретное представление о масштабах халатности и том, как Сбербанк/ЮМани относится к тем, кто делает за них важную работу по поиску брешей в безопасности.
Уязвимость
Для поддержания сессии пользователя, сервис ЮМани использует Cookie, по которым идентифицирует учетную запись в системе и возвращает соответствующие пользовательские данные. Если мы зайдем на главную страницу сервиса и войдем в учетную запись, то мы окажемся в личном кабинете по адресу yoomoney.ru/main
:
На странице присутствует базовая информация, такая как: последние 4 цифры имеющихся банковских карт, информация о балансе, номер телефона и информация о последних операциях по счету. Ничего особенного. При взаимодействии с интерфейсом, веб-приложение ходит к yoomoney.ru/api
, откуда получает всю необходимую информацию. Казалось бы, этот API и будет нашим основным интересом в плане security research. При этом на данном API-эндпоинте корректно настроен CORS, запрещающий браузерам обращаться к API откуда-либо, кроме как с yoomoney.ru
.
Прежде чем обратиться к серверу, браузер посылает Preflight-запрос — вызывая через HTTP методом OPTIONS удаленный сервер, запрашивая заголовки CORS. В такой запрос, как правило, включается заголовок Referrer
, сообщающий, с какой странички делается запрос, а заголовки ответа выглядят примерно так:
access-control-allow-credentials: true
access-control-allow-origin: https://example.com
В данном примере сервер ответил, что запросы к нему можно делать только с сайта example.com
.
Так вот если на /api
CORS, конечно же, настроен правильно и отвечает, что обращаться к нему можно только с yoomoney.ru
, то на страницах ЮМани /main
(главная страница), /settings
(настройки) и /cards
(информация о картах) — ситуация совсем другая. В заголовке access-control-allow-origin
сервис отвечал всегда тем, что присылалось в Referrer
.
Например представим, что я поднял страничку privet-ya-luntik.ru
и обращаюсь с помощью XHR-запроса в JS-коде этой страницы на yoomoney.ru/main
. Мой браузер сделает запрос:
OPTIONS https://yoomoney.ru/main
Referrer: https://privet-ya-luntik.ru
А ЮМани любезно ответит:
access-control-allow-credentials: true
access-control-allow-origin: https://privet-ya-luntik.ru
т.е., позволит мне делать запросы к этим ресурсам на их сервере и получать их содержимое. Более того, запрашиваться эти ресурсы будут от имени авторизованного пользователя, т.к. заголовок access-control-allow-credentials
подразумевает, что браузер может передавать оригинальные Cookie от ЮМани с каждым моим запросом.
Но что мы можем там найти? Это же простой интерфейс, а всё загружается с API. Бесполезная какая-то находка, правда? Я тоже так сначала подумал, но нет. Заглянем, например, в код страницы /main
:
Как выяснилось, ЮМани встраивает пользовательские данные в изначально отдаваемую пользователю страницу, дабы тот не ждал лишние несколько мгновений, пока данные подгрузятся из API. Все эти данные заботливо упакованы в JS-объект window.__data__
, который, в свою очередь, лежит в одном из тэгов <script>
. Сразу в глаза бросается наличие в объекте моего номера телефона, адреса эл. почты, текущего баланса. После более тщательного исследования, выяснилось, что в целом из страницы можно вычленить:
баланс пользователя;
email пользователя;
телефон пользователя;
статус идентификации;
ID аккаунта;
ID пользователя;
дату регистрации;
информацию о привязанных картах;
информацию о выпущенных картах;
информацию о текущих настройках безопасности;
секретный ключ (его можно потом использовать отдельно для действий от имени пользователя);
информацию о привязанных аккаунтах (ГосУслуги, ВК, Сбер);
историю транзакций с датами, суммами и типами;
Я решил не долго думать и написал свой Proof-of-Concept. Вот что получилось:
Нажимаешь кнопочку на моей сторонней (вообще не имеющем к ЮМани отношения) страничке и всё — все данные аккаунта в платежной системе (да и доступ к нему) у меня в руках.
Мой пример довольно "вегетарианский" — он просто отображает украденные данные. Однако абсолютно ничего не мешает злоумышленнику создать страницу с идентичным JS-кодом, который будет делать запросы к ЮМани, получать оттуда данные, пересылать их на сервер злоумышленника и затем переадресовывать пользователя куда-то дальше. Конечный пользователь даже не узнает о том, что его данные и доступ к аккаунту были украдены.
Примечание: Разумеется, я не публиковал PoC в открытом доступе, доступ к моей страничке был защищен паролем, которым я позднее поделился с самим ЮМани.
Дальнейшее взаимодействие с ЮМани
Как мне и предложила HR, я направил багрепорт через BugBounty.ru — сервис, при использовании которого возникают очень странные ощущения. На самом ресурсе нет никакой вводной информации о том, кому он принадлежит, кем разработан и как поддерживается. Складывалось впечатление, что он написан кем-то на коленке за пачку сока (возможно, так и было, судя по тому, как развивались события дальше). Ну бог с ним. Зарегистрировался, захожу в раздел "Программы", ожидаю увидеть обширный список того, кто предлагает репортить уязвимости через эту платформу.
Програм всего три штуки: ЮМани, ВКонтакте и какой-то неоплачиваемый "Мой Полк", (что бы это ни было) запущенный самим сервисом BugBounty.ru — сомнительно, но окей. Захожу, пишу и отправляю отчет в начале рабочего дня, 26 августа 2024 года:
Сообщаю об этом той HR, которая изначально выдала мне ссылку на эту платформу. Через несколько минут в отчете появляется комментарий сотрудника:
«Окей» подумал я. Уязвимость критическая, исправить её легко, в любой нормальной организации её исправят за считанные часы — не нужно иметь пять высших образований и IQ выше 300 чтобы поправить header'ы CORS или просто их убрать (при их отсутствии будут применяться стандартные политики безопасности, которые были бы достаточными и при этом никак не сломали бы работу сервиса).
Проходит рабочий день, решаю поинтересоваться, как успехи:
В ответ тишина. Всё это время уязвимость на месте, по прежнему эксплатируема как и раньше. Статус отчета по прежнему "Рассмотрение". Уточню также, что дополнительно написал CEO ЮМани Ивану Глазачеву: "...через bugbounty.ru сообщил о критической уязвимости в ЮМани, с помощью которой злоумышленники могут получить неограниченный доступ к данным и кошельку пользователей сервиса <...> уязвимость по прежнему на месте. Хотел бы сообщить об этом Вам, дабы избежать ситуации когда из-за промедлений кто-то кроме меня найдет это и решит воспользоваться в преступных намерениях".
И вот спустя два месяца, ночью с 3 на 4 сентября я обнаружил, что уязвимость, наконец, закрыли. Захожу в BugBounty.ru, вижу, что репорт все еще висит в статусе "Рассмотрение". Пишу комментарий:
На следующие сутки на репорт отвечает сотрудник ЮМани:
Отчёт закрывается с переводом в статус "Дубликат" и всё. Мне, тем временем, предлагается поверить, что на протяжении 2 месяцев критическая уязвимость была на их сайте, им якобы об этом было известно и они не предпринимали абсолютно никаких мер по её устранению, пока я не направил им отчёт. А потом совершенно случайно так совпало, что я им написал и они закрыли эту уязвимость. При этом никаких ссылок не приводится, а общее число отчетов на сайте сервиса для баг-репортинга не изменилось. При этом до закрытия уязвимости отчет в статус "Дубликат" никто не переводил, в том числе, сотрудник, принявший отчет в работу изначально.
При этом в условиях программы обещается до 400 тысяч рублей за предоставленную информацию о критической уязвимости.
Отличная схема, скажу я вам. Заводите bugbounty программу на стороннем ресурсе без внешнего аудита и какой-либо репутации, получаете бесплатно репорты об уязвимостях, закрываете их, а сообщившим говорите "дубликат, денег не будет" и всё. Такой вот сайберсекьюрити на бесплатном аутсорсе. Мне кажется, смахивает на мошенничество.
Итог
Из вышесказанного можно делать выводы. Подобное отношение к bug bounty программе у Сбера/ЮМани показывает, чего стоят безопасность пользователей, их данных и денег для сервисов таких компаний. Дискредитируя такими действиями программы репортинга уязвимостей, они создают условия, в которых независимые исследователи не будут проводить исследования т.к. они заведомо будут знать о том, что вознаграждения они не увидят. Зато этим займутся злоумышленники, которые в лучшем случае, продадут информацию третьим лицам, а в худшем — украдут ваши деньги и личные данные.
Такие дела.
Обновлено 09.09.2024:
Как и ожидалось, никаких подтверждений того, что действительно уязвимость была ранее известна — не представили. Вместо этого сказали "это подтверждается нашими внутренними документами" и всё, а документы мы вам не покажем, поверьте нам на слово :-)
Обнародовали ли они хотя бы какое-то косвенное подтверждение сказанного? Нет. Ни скриншотов, ни самих документов, ни тикетов, ни отчетов.
Обновлено 18.09.2024:
После выхода публикации на Хабре, вышеупомянутая площадка Bugbounty.ru (кстати, напрямую аффилированная с самим ЮМани, как выяснили хабровчане) молча удалили мою учётную запись c отчётом об уязвимости, будто их никогда не существовало. Сохраненные в Password Manager'е пароль и email при попытке входа теперь возвращают ошибку, а попытка восстановить пароль говорит, что такого пользователя больше не существует. Очень ответственный, профессиональный подход ?(нет)
ultpit
Да. Сберу ВСЕГДА плевать на безопасность пользователей. Пример. В веб версии нет вирт.карт. И нельзя отключить рекуррентные платежи. Т.е. ты оплачиваешь покупку на 10р. При этом подключаются рек.платежи. И могут затем списывать большие суммы по 1000-5000р(псевдоподписки итд). И ты не знаешь об этом(пока деньги не уйдут). нельзя просмотреть рекуррентные платежи в вебверсии. И отключить эти платежи тоже нельзя. Впрочем тех поддержка сбера очень грамотная. Предложила сразу два способа отключить рек.платежи. В мобильном приложении.И второй вариант для web версии - заблочить карту. Нет карты нет списаний. И это не сарказм. Именно это мне и предложили 4 года назад. Сейчас узнавал всё также. Это лишь один из примеров. Кстати пользуюсь также Ю-мани. Раньше было очень удобно и круто. Сейчас просто ужасно.
Didimus
Тащить всех в приложение выглядит очень тупо на фоне отсутствия приложения в сторах
MountainGoat
Корпорация. Отдел тащения в приложение и отдел размещения в сторах - в разных ветках находятся.
habrolog
"Вот где вам приложение в сторе обещали, туда и идите!"
dartraiden
Harwest
А покласть на постановления: смартфон 2018 года выпуска живёт уже вторую жизнь и асем устраивает. Никаких русторе и предустановленного гогна на нем нет и не будет )
Didimus
Можно сколько угодно обязывать установить рустор, но самая желанная аудитория банков продолжает использовать айфон, и кто побогаче и поумнее, обходят стороной всякие левые методы установки приложений. Так что сбер в пролете со своей упертой тупостью
rombell
Поделитесь статистикой? Среди моих знакомых прогеров и учёных владельцев айфонов от силы 10%
Sap_ru
Платёжеспособность.
djiggalag
Наличие айфона ни тогда, ни сейчас не говорит о какой либо платёжеспособности. А вот об отсутствие серого вещества очень даже, достаточно вспомнить на что готовы пойти некоторые индивиды для того чтобы получить заветный айфон))
ExTalosDx
Использование такого уровня софистики на ресурсе, который позиционирует себя, как для "прошаренных"/учёных/инженеров это всё равно, что сказать перед диалоговом:
"сейчас я солгу" и потом начать заливать про заговоры рептилоидов.
djiggalag
Ресурс может позиционировать себя как хочет, он уже давно отошёл от вышеописанных критериев когда решил обьеденить гик и хабр в одно место.
djiggalag
Наличие айфона ни тогда, ни сейчас не говорит о какой либо платёжеспособности. А вот об отсутствие серого вещества очень даже, достаточно вспомнить на что готовы пойти некоторые индивиды для того чтобы получить заветный айфон))
Skyl1ne32
adb uninstall - k --user 0 com.rustore.app или как там у них пакет этого калищного стопа называется
Fenex
К сожалению уже устоявшаяся классическая дискриминация по признаку наличия\отсутствия смартфона. Типа, если нету у тебя смартфона, то ты и не человек вовсе.
Didimus
Раньше ещё было подобное с вуцаппом. Все низкоинтеллектуальные личности пользовались только им. Строители, которые делают ремонт, продажники «пришлю цену в вуцаппе», мамкины группы в дет.садах. Создавало определённые неудобства тем, кто не принял его ублюдочные условия и отказался в пользу телеграма.
Ga1ena
Это вы ещё в забуграх не пожили, тут все в вацапе-вайбере сидят.
Didimus
Дикари.
Akorabelnikov
Дикие люди. Но Вацап установить пришлось
vikarti
Как вариант - Matrix с клиентом(да хоть Beeper) + whatsapp bridge(не помню уж - умеет этот бридж автономно работать совсем - если нет - на телефон какой старый). И на проблемы когда что-то где то не отправляется - "это глюки ватсаппа используйте X"
vm03
Работает автономно (эмулирует web-версию), но раз в две недели нужна активность в родном приложении.
SkywardFire
Просто замечу, что сейчас курс взят на то, чтобы функционал был максимально одинаков в вебе и в приложении. Возможно, не всё допилили пока еще.
Billander
Мне иногда кажется что баг трекер обязан быть открытым для всех на сайте площадки, со всеми описаниями и комментами, дабы действительно серьезные уязвимости быстро закрывались и мотивировали компании заботиться о тех данных без которых они не могут жить, такие как номера телефонов ФИО и прочее.