Государственная атака MitM

Предпоследний абзац моего предыдущего поста оказался в каком–то смысле пророческим: на этой неделе появились новости про Национальный сертификат безопасности в Казахстане.

30 ноября на сайте Казахтелекома появилась новость следующего содержания:

Согласно Закону операторы связи обязаны осуществлять пропуск трафика с использованием протоколов, поддерживающих шифрование, с применением сертификата безопасности, за исключением трафика, шифрованного средствами криптографической защиты информации на территории Республики Казахстан.
Национальный сертификат безопасности обеспечит защиту казахстанских пользователей при использовании протоколов шифрованного доступа к зарубежным ресурсам сети Интернет.

Сейчас новость удалили, но archive.org ее запомнил (правда, в России archive.org забанен, так что прочитать архив можно только через Tor или VPN). В общем–то эти два абзаца довольно мутные, понять, что они означают, можно не сразу, но зато дальше всё встаёт на свои места:

По словам Управляющего директора по инновациям АО «Казахтелеком» Нурлана Мейрманова, пользователям сети Интернет необходимо установить национальный сертификат безопасности, который будет доступен через Интернет-ресурсы АО «Казахтелеком». «Пользователю необходимо зайти на сайт www.telecom.kz и установить на своих устройствах выхода в сеть Интернет данный сертификат, следуя пошаговой инструкции по установке» — подчеркнул Н. Мейрманов.
АО «Казахтелеком» обращает особое внимание пользователей на то, что установка сертификата безопасности должна быть выполнена с каждого устройства абонента, с которого будет осуществляться выход в сеть Интернет (мобильные телефоны и планшеты на базе iOS/Android, персональные компьютеры и ноутбуки на базе Windows/MacOS).

Выделение жирным мое.

Каждый пользователь устанавливает корневой сертификат Казахтелекома (или, если угодно, Комитета Национальной Безопасности Казахстана) на свой компьютер, после чего на этом сертификате (или любом другом, сходящемся к этому корню) можно будет выпускать сертификаты для любых сайтов, и они будут валидны с точки зрения браузера пользователя. Судя по второму абзацу первой цитаты, казахские чекисты предполагают делать это для всех зарубежных сайтов.

В прошлый раз я упомянул HTTP public key pinning (HPKP), механизм, защищающий от подмены сертификатов сайтов. Вкратце, суть его в том, что сайт сообщает браузеру, какие сертификаты обязательно должны присутствовать в цепочке доверия этого сайта. Делается это почти тем же способом, что и в HSTS — через HTTP заголовки.

Посмотрим на работу HPKP на примере сайта tollmanz.com. Если перед посещением сайта открыть net-internals (Google Chrome адрес chrome://net-internals/#hsts, а в Яндекс.Браузере — browser://net-internals/#hsts), и сделать запрос относительно этого сайта, увидим вот что:

HSTS и HPKP до посещения сайта www.tollmanz.com

Теперь, если открыть инструкцию по включению HPKP на этом сайте, а потом вернуться в net-internals, увидим вот это:

HSTS и HPKP до посещения сайта www.tollmanz.com

Как видно, для сайта включился HSTS (про это я уже говорил в прошлый раз), а еще заполнены поля PKP — это как раз public key pinning. Браузер запомнил 5 SHA256 хешей, они видны в поле dynamic_spki_hashes в base64. Теперь, обращаясь к сайту www.tollmanz.com, браузер будет проверять, что в цепочке доверия сертификата этого сайта есть хотя бы один сертификат с хешом публичного ключа, равным одному из этих пяти хешей. За подробностями я отправляю вас в RFC7469 или в вышеупомянутую инструкцию. Тут мы обсудим, почему эта конструкция бесполезна.

Само возникновение механизма связано с инцидентом DigiNotar. В один прекрасный августовский день обнаружилось, что пользователи в Иране видят другой сертификат на сайте gmail.com, вовсе не тот, который видят пользователи по всему миру. Оказалось, что этот CA взломали с целью получения валидных сертификатов как раз для целей MitM. Волнующие подробности можно прочитать в отчете компании Fox–IT об этом инциденте. В общем–то давно было понятно, что из–за отсутствия дополнительных ограничений на корневые CA они становятся весьма привлекательными целями для взлома и потому весьма опасными для всех, кто полагается на X.509 PKI. Для того, чтобы какой попало CA не мог выписать валидный сертификат, Google придумал механизм, который можно было реализовать на стороне браузера, без участия CA (они, к слову, не сильно рады этой перспективе). Как было сказано, суть работы механизма в том, чтобы сообщить браузеру, какой CA нужно считать валидным для этого сайта. Побочным эффектом стала возможность запинить и оконечный сертификат сайта.

Работает это через HTTP заголовки, аналогично HSTS. Вот пример для сайта www.tollmanz.com:

curl -vLo /dev/null https://www.tollmanz.com/
[...]
< HTTP/1.1 200 OK
< Date: Thu, 03 Dec 2015 19:13:02 GMT
< Content-Type: text/html; charset=UTF-8
< Content-Length: 10965
< Last-Modified: Wed, 12 Aug 2015 01:42:49 GMT
< Etag: “55caa499–2ad5”
< Expires: Thu, 03 Dec 2015 19:23:02 GMT
< Cache-Control: max-age=600
< Link: </css/main.css>; rel=preload; as=stylesheet
< Cache-Control: public
< X-Frame-Options: deny
< X-Xss-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< Strict-Transport-Security: max-age=15552000; includeSubDomains; preload
< X-Frame-Options: SAMEORIGIN
< Content-Security-Policy: default-src ‘self’ https:; font-src ‘self’ https:; img-src ‘self’ https:; style-src ‘self’ https: https://fonts.googleapis.com; script-src ‘self’ https: ‘unsafe-inline’ https://ssl.google-analytics.com
< Public-Key-Pins: pin-sha256=”lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=”; pin-sha256=”h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=”; pin-sha256=”6X0iNAQtPIjXKEVcqZBwyMcRwq1yW60549axatu3oDE=”; pin-sha256=”58qRu/uxh4gFezqAcERupSkRYBlBAvfcw7mEjGPLnNU=”; pin-sha256=”grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=”; max-age=2592000; includeSubDomains
< Accept-Ranges: bytes
< Server: nghttpx nghttp2/1.0.6-DEV

Выделение жирным мое.

Видно, что в заголовке перечислены SHA256 хеши, те самые, которые запомнил браузер, а также указано, на какое время их запоминать. Если проверить все хеши публичных ключей сертификатов в цепочке доверия этого сайта, там обязательно найдется один из этих пяти.

Теперь, когда браузер запомнил эти отпечатки, он не примет цепочку, не содержащую сертификат хотя бы с одним из них. Казалось бы, проблема решена: нельзя подменить сертификат сервера. Но на деле проверка производится только для заранее встроенных в браузер или операционную систему сертификатов. Вот что про это пишут в FAQ по Chromium:

To enable certificate chain validation, Chrome has access to two stores of trust anchors: certificates that are empowered as issuers. One trust anchor store is the system or public trust anchor store, and the other other is the local or private trust anchor store. The public store is provided as part of the operating system, and intended to authenticate public internet servers. The private store contains certificates installed by the user or the administrator of the client machine. Private intranet servers should authenticate themselves with certificates issued by a private trust anchor.
[…]
Chrome does not perform pin validation when the certificate chain chains up to a private trust anchor. A key result of this policy is that private trust anchors can be used to proxy (or MITM) connections, even to pinned sites. “Data loss prevention” appliances, firewalls, content filters, and malware can use this feature to defeat the protections of key pinning.

Итак, причина понятна: считается, что существуют легитимные ситуации, где MitM оправдан. Это контроль трафика на уровне сети в компаниях и организациях. Эта легитимная причина перевешивает возможные проблемы, поскольку требует от пользователя явной установки специального корневого сертификата. В крупных компаниях такой сертификат распространяется на все компьютеры сотрудников, например, через политики домена Active Directory.

Теперь остается представить, что Казахстан — это просто гигантский интранет, только без Active Directory, а с ручной установкой сертификата, и всё станет на свои места. Пиннинг работать не будет.

Что можно сделать обычному пользователю?

Нужно понимать, что DPI, штука туповатая, ищет TLS handshake совершенно определенным образом, практически сигнатурно. Если установка зашифрованного соединения не будет похожа на TLS handshake, вероятнее всего, это соединение будет работать. Также, вероятнее всего, будет работать SSH и еще многие протоколы. Думаю, будет работать и Tor, хотя сам сайт https://www.torproject.org в Казахстане зафильтрован. Кстати, если вы не можете скачать браузер с официального сайта потому, что он у вас заблокирован, отправьте письмо на gettor@torproject.org и вам пришлют ссылку на скачивание браузера из другого, еще не заблокированного места.

Однако, обнаружение зашифрованных, высокоэнтропийных соединений — не больно–то сложная задача. Например, с ней справляется net-entropy (конечно, нужно уметь этим пользоваться, да и на масштабах государства это являет собой определенную инженерную задачу). Это означает, что в принципе возможна ситуация, когда все шифрованные соединения будут запрещены, а гражданам и организациям будет рекомендовано пользоваться государственными системами шифрования (см., например, историю про чип Clipper).

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