Предисловие

Как известно, в России почти каждая первая финансовая организация позиционирует себя как софтверную IT-компанию, а не просто как "банк" или "платежная система". Сегодня речь пойдет о ЮМани — подразделении Сбера, IT-гиганта всея руси.

До того, как ЮМани стал тем, чем он сейчас является, сервис долгое время существовал как продукт Яндекса под названием Яндекс.Деньги — в те времена у меня был очень приятный опыт взаимодействия с техническим руководством компании, я неоднократно (будучи security researcher'ом) сообщал им об уязвимостях, а они, в свою очередь, оперативно это исправляли, давали обратную связь и вознаграждали за такую работу, аналогично тому, как это делали и зарубежные крупные IT-компании в рамках взаимодействия с white-hat хакерами. Такая вот IT-компания здорового человека. Но с тем, как Сбербанк поглотил Яндекс.Деньги и провёл ребрендинг, проект стал превращаться, скорее, в IT-компанию курильщика: взаимодействовать с представителями проекта в соц. сетях стало практически невозможно, какие-либо данные на страницах о Bug Bounty программах были удалены и даже ни одного email-адреса не оставили в качестве средства связи для сообщения об уязвимостях.

Пару месяцев назад я обнаружил уязвимость в сервисе ЮМани (о ней чуть позже) и сразу же решил сообщить о ней. Однако никаких релевантных этому форм связи, email-адресов и т.д. я не обнаружил — способов безопасно сообщить о такой уязвимости элементарно не было на официальном сайте сервиса. Я попытался связаться с людьми, работающими в ЮМани, однако, опять же, я не получил никакой обратной связи. На этом моменте я, что называется, "забил", в надежде, что ошибку исправят и без меня, ведь не может же такая дырень оставаться незамеченной долго, правда? Спойлер: может.

В один из прекрасных летних вечеров я воспользовался этой платежной системой в очередной раз, ну и, в рамках праздного интереса, решил проверить, "а не исправили ли". Как выяснилось, нет. Не исправили. И вот получается, что уже на протяжении очень продолжительного периода времени (около 2 месяцев) мне известно о критической уязвимости в сервисе, которую исправить можно было бы за 1-2 минуты (буквально). И тут я решаю связаться хоть каким-то способом с кем-то из этой организации. Кое-как откопал контакты HR-менеджера, с которой состоялся диалог:

HR-менеджер поделилась ссылкой на программу для баг-хантеров
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 при попытке входа теперь возвращают ошибку, а попытка восстановить пароль говорит, что такого пользователя больше не существует. Очень ответственный, профессиональный подход ?(нет)

А нет больше такой учётной записи
А нет больше такой учётной записи

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


  1. ultpit
    18.09.2024 07:11
    +49

    Да. Сберу ВСЕГДА плевать на безопасность пользователей. Пример. В веб версии нет вирт.карт. И нельзя отключить рекуррентные платежи. Т.е. ты оплачиваешь покупку на 10р. При этом подключаются рек.платежи. И могут затем списывать большие суммы по 1000-5000р(псевдоподписки итд). И ты не знаешь об этом(пока деньги не уйдут). нельзя просмотреть рекуррентные платежи в вебверсии. И отключить эти платежи тоже нельзя. Впрочем тех поддержка сбера очень грамотная. Предложила сразу два способа отключить рек.платежи. В мобильном приложении.И второй вариант для web версии - заблочить карту. Нет карты нет списаний. И это не сарказм. Именно это мне и предложили 4 года назад. Сейчас узнавал всё также. Это лишь один из примеров. Кстати пользуюсь также Ю-мани. Раньше было очень удобно и круто. Сейчас просто ужасно.


    1. Didimus
      18.09.2024 07:11
      +7

      Тащить всех в приложение выглядит очень тупо на фоне отсутствия приложения в сторах


      1. MountainGoat
        18.09.2024 07:11
        +5

        Корпорация. Отдел тащения в приложение и отдел размещения в сторах - в разных ветках находятся.


        1. habrolog
          18.09.2024 07:11
          +1

          "Вот где вам приложение в сторе обещали, туда и идите!"


      1. dartraiden
        18.09.2024 07:11

        отсутствия приложения в сторах

        На всех устройствах, которые будут продаваться в России, в обязательном порядке должен быть предустановлен магазин приложений RuStore вне зависимости от решения правообладателя операционной системы. Такое постановление подписало правительство


        1. Harwest
          18.09.2024 07:11
          +2

          А покласть на постановления: смартфон 2018 года выпуска живёт уже вторую жизнь и асем устраивает. Никаких русторе и предустановленного гогна на нем нет и не будет )


        1. Didimus
          18.09.2024 07:11
          +4

          Можно сколько угодно обязывать установить рустор, но самая желанная аудитория банков продолжает использовать айфон, и кто побогаче и поумнее, обходят стороной всякие левые методы установки приложений. Так что сбер в пролете со своей упертой тупостью


          1. rombell
            18.09.2024 07:11

            Поделитесь статистикой? Среди моих знакомых прогеров и учёных владельцев айфонов от силы 10%


            1. Sap_ru
              18.09.2024 07:11
              +3

              Платёжеспособность.


              1. djiggalag
                18.09.2024 07:11
                +5

                Наличие айфона ни тогда, ни сейчас не говорит о какой либо платёжеспособности. А вот об отсутствие серого вещества очень даже, достаточно вспомнить на что готовы пойти некоторые индивиды для того чтобы получить заветный айфон))


                1. ExTalosDx
                  18.09.2024 07:11
                  +3

                  Использование такого уровня софистики на ресурсе, который позиционирует себя, как для "прошаренных"/учёных/инженеров это всё равно, что сказать перед диалоговом:

                  "сейчас я солгу" и потом начать заливать про заговоры рептилоидов.


                  1. djiggalag
                    18.09.2024 07:11

                    Ресурс может позиционировать себя как хочет, он уже давно отошёл от вышеописанных критериев когда решил обьеденить гик и хабр в одно место.


              1. djiggalag
                18.09.2024 07:11

                Наличие айфона ни тогда, ни сейчас не говорит о какой либо платёжеспособности. А вот об отсутствие серого вещества очень даже, достаточно вспомнить на что готовы пойти некоторые индивиды для того чтобы получить заветный айфон))


        1. Skyl1ne32
          18.09.2024 07:11
          +1

          adb uninstall - k --user 0 com.rustore.app или как там у них пакет этого калищного стопа называется


      1. Fenex
        18.09.2024 07:11
        +10

        К сожалению уже устоявшаяся классическая дискриминация по признаку наличия\отсутствия смартфона. Типа, если нету у тебя смартфона, то ты и не человек вовсе.


        1. Didimus
          18.09.2024 07:11

          Раньше ещё было подобное с вуцаппом. Все низкоинтеллектуальные личности пользовались только им. Строители, которые делают ремонт, продажники «пришлю цену в вуцаппе», мамкины группы в дет.садах. Создавало определённые неудобства тем, кто не принял его ублюдочные условия и отказался в пользу телеграма.


          1. Ga1ena
            18.09.2024 07:11

            Это вы ещё в забуграх не пожили, тут все в вацапе-вайбере сидят.


            1. Didimus
              18.09.2024 07:11

              Дикари.


              1. Akorabelnikov
                18.09.2024 07:11
                +1

                Дикие люди. Но Вацап установить пришлось


                1. vikarti
                  18.09.2024 07:11

                  Как вариант - Matrix с клиентом(да хоть Beeper) + whatsapp bridge(не помню уж - умеет этот бридж автономно работать совсем - если нет - на телефон какой старый). И на проблемы когда что-то где то не отправляется - "это глюки ватсаппа используйте X"


                  1. vm03
                    18.09.2024 07:11

                    Работает автономно (эмулирует web-версию), но раз в две недели нужна активность в родном приложении.


      1. SkywardFire
        18.09.2024 07:11

        Просто замечу, что сейчас курс взят на то, чтобы функционал был максимально одинаков в вебе и в приложении. Возможно, не всё допилили пока еще.


    1. Billander
      18.09.2024 07:11
      +1

      Мне иногда кажется что баг трекер обязан быть открытым для всех на сайте площадки, со всеми описаниями и комментами, дабы действительно серьезные уязвимости быстро закрывались и мотивировали компании заботиться о тех данных без которых они не могут жить, такие как номера телефонов ФИО и прочее.