5772

Яндекс Баунти или ключ за миллион бесплатно

Приключилась со мной история, которая отражает лояльность компании Яндекс.

Небольшой спойлер - история на миллионы.


Яндекс проводит конкурс "Охота за ошибками", в рамках которого, участник нашедший уязвимость, удовлетворяющую условиям конкурса, может рассчитывать на денежное вознаграждение (более подробно с условиями и самим конкурсом можно ознакомиться здесь https://yandex.ru/bugbounty/).


Решил я один из вечером посвятить анализу сервисов Яндекса на наличие уязвимостей. Претендентом на анализ стал https://eda.yandex.ru/.

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

На сервисе в исходном коде сразу же красуется такой код:


<link rel="preconnect" href="https://enterprise.geocode-maps.yandex.ru" />
<link rel="preconnect" href="https://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 ключ https://yandex.ru/dev/maps/commercial/doc/concepts/jsapi-geocoder-docpage/
Небольшой спойлер, цены за год пользования API ключом доходят до 1.5 млн рублей.

Провожу прямое геокодирование и ожидаю ошибку 403 (это ошибка, когда на API ключ наложено ограничение, например по IP или домену, откуда идет запрос), но на моё удивление, я получаю успешный результат геокодирования и всё бы ничего, если бы это был бесплатный запрос, но геокодирование один из пунктов платных запросов на API ключе Яндекса.
Пример прямого геокодирования с ключом Яндекса:

https://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

А здесь мы видим https://yandex.ru/dev/maps/commercial/doc/concepts/jsapi-geocoder-docpage/

что прямое геокодирование или обращение к HTTP API Геокодера является тарифицируемым запросом, т.е. платным, но ведь мы сделали запрос, получили успешный результат и ничего не заплатили!


Далее проведя еще несколько тестов, я окончательно убедился, что Яндекс не защитил свой корпоративный API ключ от стороннего использования и тут же создал обращение, через программу "Охота за ошибками" от Яндекса.

Ниже представлена переписка с сотрудником Яндекса.


Яндекс:

Проблема использования чужих geocodeKey в JS API нам была уже известна. В связи с этим, к сожалению, мы не можем присудить за нее вознаграждение.


Я:

А при чем здесь использование чужих geocodeKey в JS API, я говорю про конкретный случай в вашем сервисе, про ваш geocodeKey, который вы же и не защитили, что позволяет его использовать всем желающим.

Яндекс:

Так geocodeKey используется в JS API на стороне браузера, защитить его от попадания в браузер технически невозможно. Проблема использования этого geocodeKey сторонним сервисами нам уже была известна. В связи с этим, к сожалению, мы не можем присудить за нее вознаграждение.

Я:

А для чего тогда вот это?
Это как раз и защищает ключ от стороннего использования его в платных функциях, например геокодирование.
Как я ранее приводил пример, если у ключа нет ограничений, его может применять кто угодно, но если поставить ограничение в функционале (см скриншот выше), тогда на запрос
https://geocode-maps.yandex.ru/1.x/?apikey=c0d403ab-e5be-4049-908c-8122a58acf23&geocode=Россия, Белгородская область
будет отдаваться не результат геокодирования, а
<error>
<statusCode>403</statusCode>
<error>Forbidden</error>
<message>Invalid key</message>
</error>

Яндекс:

Действительно ключ не защищен стороннего использования. К сожалению эта проблема не входит в рамки программы "Охота за ошибками". В связи с этим мы можем добавить вас в Зал Славы Охоты за Ошибками (https://yandex.ru/bugbounty/hall-of-fame/) без назначения денежного вознаграждения.

Я:

Почему данная проблема не входит в рамки программы "Охота за ошибками"?
Здесь сказано
https://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://owasp.org/www-project-api-security/). С нашей точки зрения описанная вами проблема не может отнесена к категориям "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 млн рублей в год и более. В зал славы меня добавили https://yandex.ru/bugbounty/hall-of-fame/2020/6/ , а вот в денежном вознаграждении отказали ("Конкурсы занятные и призы интересные").


P.S. я лишь донес историю, случившуюся со мной и то как повел себя Яндекс в такой ситуации. Участвовать в данном конкурсе или нет, решать только вам!

UPD: К посту есть вопросы #comment_180781762