Почему Яндекс.Метрика стала https-only

#security #russian

На ЛОРе жалуются, как тяжело жить с https–only Яндекс.Метрикой, тут я объясню, почему она такая.

С полгода назад в новостях мелькала история об «импортозамещении» Яндекс.Браузером других браузеров. Вкратце, суть истории такова: при попадании на какой-нибудь сайт пользователь видел развёрнутое во весь экран настойчивое предложение заменить его браузер на другой, якобы Яндекса. При переходе по ссылке пользователю устанавливался UC Browser китайской компании UC Web.

Если честно, в тот момент детективная и пиарная части истории в тот момент меня не интересовали, интересовала техническая: как получилось, что на сотнях сайтов пользователям на разных платформах показывают одно сообщение. В кросс-платформенную малварь я не верил, так что объяснение Ильи Чекальского, что баннер появляется на сайтах, где установлена Яндекс.Метрика, выглядело правильным. Однако, я знал, что Яндекс не показывает рекламу с хоста счётчика Метрики (mc.yandex.ru), тем более, у меня была эталонная копия скриптов Метрики и никакого кода показа баннеров там не было (ещё я был уверен, что Яндекс не займётся такой желтизной, но это не технический, а гуманитарный аргумент).

Long story short, после теорий о подмене трафика на DPI Ростелекома или сговоре iMarker с UC Web выяснилось, что способ подмены mc.yandex.ru очень простой: на wifi-маршрутизаторе пользователя изменяются настройки DNS серверов. На домашних wifi-маршрутизаторах (а их часто используют и в интернет-кафе, на заправках и прочих местах) работает простой кеширующий DNS-сервер с пересылкой запросов (а не полностью рекурсивный). Когда пользователь подключается к wifi, маршрутизатор (через DHCP или RA) предлагает ему свой адрес в качестве адреса DNS сервера, впоследствии, получая DNS запросы, маршрутизатор перенаправляет их настоящему DNS серверу.

В этой истории атакующий завёл свой DNS сервер и прописал на нём свои адреса для mc.yandex.ru, www.google-analytics.com и тому подобного. Дальше, получив доступ к маршрутизаторам пользователей, он прописал свой DNS сервер в настройках. Теперь, браузеры пользователей, пытаясь загрузить счетчик Метрики или Google Analytics, обращались на подконтрольный злоумышленнику адрес и получали оттуда скрипт, который и показывал пугающий баннер.

Для того, чтобы эта история не повторялась (и для того, чтобы избежать тривиальной подмены контента при обращении к mc.yandex.ru), Яндекс решил увести mc.yandex.ru за https.

Внедрение происходило в несколько этапов. Сначала на mc.yandex.ru появился заголовок HSTS (что это, я раньше писал), с коротким TTL. Сейчас его тоже можно увидеть:

curl -Lvo /dev/null https://mc.yandex.ru/metrika/watch.js
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 — : — : — — : — : — — : — : — 0
* Trying 87.250.250.119…
* Connected to mc.yandex.ru (87.250.250.119) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
* Server certificate: bs.yandex.ru
* Server certificate: GlobalSign Organization Validation CA — G2
* Server certificate: GlobalSign Root CA

> GET /metrika/watch.js HTTP/1.1
> Host: mc.yandex.ru
> User-Agent: curl/7.43.0
> Accept: */*
>

< HTTP/1.1 200 OK
< Server: nginx/1.8.0
< Date: Wed, 16 Dec 2015 07:31:57 GMT
< Content-Type: application/x-javascript
< Content-Length: 65960
< Connection: keep-alive
< P3P: CP=”NOI DEVa TAIa OUR BUS UNI STA”
< Last-Modified: Tue, 08 Dec 2015 16:44:57 GMT
< Expires: Wed, 16 Dec 2015 08:31:57 GMT
< Strict-Transport-Security: max-age=31536000
<

{ [16048 bytes data]
100 65960 100 65960 0 0 98k 0 — : — : — — : — : — — : — : — 98k
* Connection #0 to host mc.yandex.ru left intact

При запуске, max-age был равен 15 минутам, чтобы можно было быстро вернуться назад. Подключение счетчика Метрики в то время было реализовано через вот такой URL без указания протокола: “//mc.yandex.ru/metrika/watch.js”. Такое подключение (так называемый protocol related URL) работает, используя протокол основной страницы для подключения кода счётчика. Иначе говоря, если страница со счетчиком загружена по http, счётчик подключается по http, если основная страница загружена по https — то и счётчик загружается по https. У Яндекса было несколько своих https–only ресурсов (Например, Почта или интерфейс Директа) и, таким образом, пользователи Почты получали mc по https с HSTS заголовком. Это позволило дать некоторой доле пользователей https–only Метрику на 15 минут, а админам — наблюдать за изменениями в трафике, количеству потерянных хитов и ждать жалоб пользователей.

Дальше в несколько этапов время жизни HSTS увеличивался, изменялись ciphersuites (про выбор ciphersuites я писал в блог Яндекса на Хабре), аналитики посмотрели на пользовательские характеристики, penalty по скорости загрузки и т.п. В конце концов, состояние https на mc.yandex.ru было признано удовлетворительным, а масштаб потерь пользовательского трафика — приемлемым (действительно, есть небольшое количество пользователей со сломанным https, но по измерениям Яндекса их исчезающе мало).

Наконец, было принято решение, что можно переезжать на https–only. Тогда HSTS TTL увеличили до 1 года, а на http–версии сделали редирект на https. Теперь оно так и живет.

Есть мнение, что от такого изменения пользы никакой нет, ведь если сайт загружен по http, атакующий по пути может изменить в нем ссылку на Метрику или вставить свой js код. Я с этим не согласен. Переход на https–only в Метрике защищает Метрику, но не сторонние пользовательские сайты. Кроме того, есть атаки разной степени сложности, подменить DNS легко, а inline смена контента — более сложная задача. Поэтому польза есть, и по моему мнению, она больше, чем потенциальные потери от неработающего у части пользователей https. Нужно понимать, что достижение дна обеспечивается не только государственными организациями, но и каждым мошенником, который научился подбирать пароли по умолчанию к роутерам или слушать WiFi трафик в открытых сетях.