Приключилась со мной история, которая отражает лояльность компании Яндекс.
Небольшой спойлер — история на миллионы.
Яндекс проводит конкурс «Охота за ошибками», в рамках которого, участник нашедший уязвимость, удовлетворяющую условиям конкурса, может рассчитывать на денежное вознаграждение (более подробно с условиями и самим конкурсом можно ознакомиться здесь yandex.ru/bugbounty).
Решил я один из вечером посвятить анализу сервисов Яндекса на наличие уязвимостей. Претендентом на анализ стал eda.yandex.ru.
Буквально через пол часа анализа кода сервиса, наткнулся на интересный момент.
На сервисе в исходном коде сразу же красуется такой код:
«preconnect» href=«enterprise.geocode-maps.yandex.ru»
link rel=«preconnect» href=«enterprise.api-maps.yandex.ru»
Проще говоря, данный код заранее устанавливает соединение с указанным сайтом, а это значит, что скорее всего эти сервисы используются далее на сайте, так оно и есть. Продолжив анализ кода, я нашел где задавался API ключ для вышеуказанного сервиса, а именно js объект в котором задавался ключ объекта geocodeKey и его значение «c0d403ab-e5be-4049-908c-8122a58acf23», именно он и станет виновником данного «торжества».
Раз «пациент» подключается к geocode-maps.yandex.ru, можно предположить, что тут происходит геокодирование. Если углубиться, то можно узнать, что у Яндекса есть два вида версии API (бесплатная и платная). Платная подключается с префиксом «enterprise» в адресе, как в нашем случае enterprise.geocode-maps.yandex.ru.
Уже становится интересно, так как на сайте подключена платная версия API.
Здесь можно ознакомиться с расценками на API ключ yandex.ru/dev/maps/commercial/doc/concepts/jsapi-geocoder-docpage
Небольшой спойлер, цены за год пользования API ключом доходят до 1.5 млн рублей.
Провожу прямое геокодирование и ожидаю ошибку 403 (это ошибка, когда на API ключ наложено ограничение, например по IP или домену, откуда идет запрос), но на моё удивление, я получаю успешный результат геокодирования и всё бы ничего, если бы это был бесплатный запрос, но геокодирование один из пунктов платных запросов на API ключе Яндекса.
Пример прямого геокодирования с ключом Яндекса:
geocode-maps.yandex.ru/1.x/?apikey=c0d403ab-e5be-4049-908c-8122a58acf23&geocode=%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F,+%D0%91%D0%B5%D0%BB%D0%B3%D0%BE%D1%80%D0%BE%D0%B4%D1%81%D0%BA%D0%B0%D1%8F+%D0%BE%D0%B1%D0%BB%D0%B0%D1%81%D1%82%D1%8C
А здесь мы видим yandex.ru/dev/maps/commercial/doc/concepts/jsapi-geocoder-docpage
что прямое геокодирование или обращение к HTTP API Геокодера является тарифицируемым запросом, т.е. платным, но ведь мы сделали запрос, получили успешный результат и ничего не заплатили!
Далее проведя еще несколько тестов, я окончательно убедился, что Яндекс не защитил свой корпоративный API ключ от стороннего использования и тут же создал обращение, через программу «Охота за ошибками» от Яндекса.
Ниже представлена переписка с сотрудником Яндекса.
Яндекс:
Проблема использования чужих geocodeKey в JS API нам была уже известна. В связи с этим, к сожалению, мы не можем присудить за нее вознаграждение.
Я:
А при чем здесь использование чужих geocodeKey в JS API, я говорю про конкретный случай в вашем сервисе, про ваш geocodeKey, который вы же и не защитили, что позволяет его использовать всем желающим.
Яндекс:
Так geocodeKey используется в JS API на стороне браузера, защитить его от попадания в браузер технически невозможно. Проблема использования этого geocodeKey сторонним сервисами нам уже была известна. В связи с этим, к сожалению, мы не можем присудить за нее вознаграждение.
Я:
А для чего тогда вот это?
Это как раз и защищает ключ от стороннего использования его в платных функциях, например геокодирование.
Как я ранее приводил пример, если у ключа нет ограничений, его может применять кто угодно, но если поставить ограничение в функционале (см скриншот выше), тогда на запрос
geocode-maps.yandex.ru/1.x/?apikey=c0d403ab-e5be-4049-908c-8122a58acf23&geocode=Россия, Белгородская область
будет отдаваться не результат геокодирования, а
403
Forbidden
Invalid key
Яндекс:
Действительно ключ не защищен стороннего использования. К сожалению эта проблема не входит в рамки программы «Охота за ошибками». В связи с этим мы можем добавить вас в Зал Славы Охоты за Ошибками (https://ift.tt/333nDiV) без назначения денежного вознаграждения.
Я:
Почему данная проблема не входит в рамки программы «Охота за ошибками»?
Здесь сказано
yandex.ru/bugbounty
1. «Где искать
Веб-сервисы: на доменах yandex.ru, yandex.com, yandex.com.tr, yandex.kz, yandex.ua, yandex.by, yandex.net (кроме people.yandex.net), yandex.st, eda.yandex, ya.ru.»
eda.yandex — входит в данный перечень
2. «A01. Инъекции», согласно классификации «OWASP Top-10 версии 2010 года».
Это недостаток внедрения. Злоумышленник может воспользоваться вашим же ключом в своих корыстных целях путем подстановки его в get запросы, своего рода проведя инъекцию на выполнение платных запросов для получения данных (бесплатно) без надлежащей авторизации.
Яндекс:
Описанная вами проблема с нашей точки зрения не относится к классу «A01. Инъекции», а относится к классу отсутствия лимитов на использование API. К сожалению, правилами нашей программы пока не предусмотрены выплаты за такой тип уязвимостей, если они не затрагивают безопасность данных наших пользователей.
Я:
Уточните, пожалуйста, согласно какой классификации вы отнесли данный баг к классу «отсутствия лимитов на использование API»?
Даже если не расценивать данный баг как инъекцию, то он подпадает, как минимум, под один из классов классификации «OWASP Top-10 версии 2010 года»:
2. Broken Authentication.
5. Broken Access Control.
6. Security Misconfiguration.
Яндекс:
Согласно классификации OWASP API Security Top 10 2019 (https://ift.tt/2V0yFSm). С нашей точки зрения описанная вами проблема не может отнесена к категориям «Broken Authentication», «Broken Access Control», «Security Misconfiguration».
Итоги:
1. Пришлось потратить не мало времени, чтобы доказывать и «разжевывать» Яндексу, что найденный баг является багом, а также немного научить пользоваться их же функционалом (я про выставление ограничений на ключ).
2. В их же условиях указано, что «В качестве классификации уязвимостей для веб-сервисов используется OWASP Top-10 версии 2010 года, для мобильных приложений — OWASP Mobile Top-10.», но в диалоге их сотрудник уточнил, что мою уязвимость они классифицировали по «OWASP API Security Top 10 2019».
3. Найденный баг был передан Яндексу 9 июня 2020 года, прошло более 3 месяцев, но Яндекс так и не исправил баг и любой желающий может совершенно бесплатно воспользоваться их корпоративным API ключом «c0d403ab-e5be-4049-908c-8122a58acf23», стоимость которого достигает до 1.5 млн рублей в год и более. В зал славы меня добавили yandex.ru/bugbounty/hall-of-fame/2020/6, а вот в денежном вознаграждении отказали («Конкурсы занятные и призы интересные»).
P.S. я лишь донес историю, случившуюся со мной и то как повел себя Яндекс в такой ситуации. Участвовать в данном конкурсе или нет, решать только вам!
Комментариев нет:
Отправить комментарий