Про HTTPS, HSTS, MitM и certificate pinning

#censorship #https #russian

В истории с попыткой блокировать википедию появились какие–то слухи об успешности или не успешности атак MitM (человек посередине), проводимых некоторыми провайдерами.

При этом, на сайте ru.wikipedia.org используется механизм HSTS (HTTP Strict Transport Security). Это легко проверить, например, с помощью curl:

ivlad@ivlad-osx2 ~ 765% curl -I http://ru.wikipedia.org
HTTP/1.1 301 TLS Redirect
Server: Varnish
Location: https://ru.wikipedia.org/
Content-Length: 0
Accept-Ranges: bytes
Date: Wed, 26 Aug 2015 07:51:29 GMT
X-Varnish: 1524114755
Age: 0
Via: 1.1 varnish
Connection: close
X-Cache: cp3040 frontend miss (0)
Set-Cookie: GeoIP=:::::v6; Path=/; Domain=.wikipedia.org
Set-Cookie: WMF-Last-Access=26-Aug-2015;Path=/;HttpOnly;Expires=Sun, 27 Sep 2015 00:00:00 GMT

HTTP/1.1 301 Moved Permanently
Server: nginx/1.9.3
Date: Wed, 26 Aug 2015 07:51:29 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
X-Powered-By: HHVM/3.6.5
X-Content-Type-Options: nosniff
Cache-control: s-maxage=1200, must-revalidate, max-age=0
Vary: Accept-Encoding,X-Forwarded-Proto,Cookie
Location: https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0
Last-Modified: Wed, 26 Aug 2015 07:33:03 GMT
X-Varnish: 3400906055, 2212408807 2212407565, 3416102176 3414853561
Via: 1.1 varnish, 1.1 varnish, 1.1 varnish
Age: 1106
X-Cache: cp1055 miss (0), cp3030 hit (13), cp3014 frontend hit (471)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Analytics: https=1;WMF-Last-Access=26-Aug-2015

HTTP/1.1 200 OK
Server: nginx/1.9.3
Date: Wed, 26 Aug 2015 07:51:29 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Content-Type-Options: nosniff
X-Powered-By: HHVM/3.6.5
Content-language: ru
X-UA-Compatible: IE=Edge
Vary: Accept-Encoding,Cookie
Last-Modified: Wed, 26 Aug 2015 06:07:46 GMT
X-Varnish: 2411226180, 3554012048 3554011365, 3416102237 3409779660
Via: 1.1 varnish, 1.1 varnish, 1.1 varnish
Age: 6222
X-Cache: cp1068 miss (0), cp3009 hit (9), cp3014 frontend hit (3121)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Cache-Control: private, s-maxage=0, max-age=0, must-revalidate
X-Analytics: page_id=4401;ns=0;https=1;WMF-Last-Access=26-Aug-2015

Интересные заголовки в HTTP–ответах я выделил жирным. Тут видно, что при попытке подключиться к сайту ru.wikipedia.org по HTTP, первым ответом сервера мы получаем постоянный редирект (код HTTP 301) на HTTPS. В HTTPS–версии сайта сервер возвращает дополнительный заголовок Strict-Transport-Security, который и обеспечивает работу механизма HSTS.

После получения этого заголовка, браузер запоминает, что на этот сайт нужно ходить только по HTTPS, даже если ссылка на него или пользователь в адресной строке ввел адрес с HTTP. Срок жизни этой настройки — 31536000 секунд, что составляет один год.

Например, в Google Chrome можно открыть специальный адрес chrome://net-internals/#hsts, а в Яндекс.Браузере — browser://net-internals/#hsts и посмотреть, как работает HSTS.

Вот что мы видим до посещения Википедии:

А вот — что происходит после посещения:

Видно, что браузер запомнил, что ходить на сайт википедии можно только по HTTPS (dynamic_upgrade_mode: STRICT), это же распространяется на все поддомены (dynamic_sts_include_subdomains: true). Таким образом, с этого момента пользователь защищен от прослушивания трафика с Википедией.

Важно, что для Википедии эта настройка срабатывает только после первого посещения сайта, заранее браузер не знает, что необходимо пользоваться исключительно HTTPS. Здесь возникает первая проблема: если провайдер подменит страничку Википедии до того, как пользователь первый раз её посетил, защита HSTS не будет работать и провайдер во–первых сможет видеть всё содержимое запросов и ответов, а во–вторых, сможет показать прекрасно оформленную страничку о блокировке ресурса, такую, например:

Если пользователь все–таки уже посетил HTTPS–версию сайта и HSTS для него оказался включен, провайдер все еще может попытаться провести атаку MitM, создав собственный HTTPS сервис со страничкой блокировки, и пытаясь перенаправлять людей туда. Как правило, для этого провайдеры создают так называемые «самоподписанные сертификаты», и используют их на страницах блокировки. Это не будет работать потому, что когда браузер запомнил флаг HSTS для конкретного сайта, он не дает возможности пользователю обойти ошибку сертификатов, кнопка «Продолжить» просто исчезает из интерфейса:

И на этом процесс останавливается. В идеологии включения HSTS считается, что безопасность важнее нужды пользователя посмотреть сайт «прямо сейчас, потому, что срочно надо», и простого способа обойти это ограничение нет (есть относительно сложный — удалить настройку HSTS через net-internals, но обычному пользователю это недоступно).

Провайдер мог бы провести атаку успешно, если бы у него был валидный сертификат для ru.wikipedia.org. Получить такой сертификат теоретически можно было бы тремя способами:

Я полагаю, все эти три способа недостижимы для любого российского провайдера: первых два — все-таки нарушения, провайдер этим заниматься не будет (это привелегия взломщиков и, возможно, спецслужб), и использование такого сертификата сразу будет заметно. А третий способ невозможен потому, что в России нет ни одной компании, владеющей так называемыми «корневыми сертификатами», а есть только компании, перепродающие услуги таковых. И если такие перепродавцы будут пойманы на подделке сертификатов, владельцы корневых сертификатов моментально перестанут с ними работать, а это никому не надо.

Тем не менее, от этой атаки тоже можно защититься. Для этого может использоваться механизм public key pinning. В Википедии он не используется и я не видел новостей от Фонда Викимедиа, что они собираются это включить. Однако, сделать это несложно, и, на мой взгляд, полезно.

Впрочем, у провайдера есть еще одна возможность: он может предложить пользователю установить собственный корневой сертификат и, таким образом, для этого пользователя станет компанией, выдающей сертификаты. От этого механизм public key pinning не защищает (потому, что так работают антивирусы и системы контентной фильтрации в крупных компаниях), так что я думаю, что крупные провайдеры могли бы пойти по этому пути — настраивая компьютер клиента, предложить ему установить сертификат «для правильной работы», а после этого — успешно делать MitM, блокируя нужным образом в том числе и любые HTTPS–сайты.

Дно еще не достигнуто.