Классический страх: вы в кафе, Wi-Fi открытый, кто-то за соседним столиком «перехватывает трафик». Или провайдер всё видит. Атака «человек посередине» (man in the middle) — это когда кто-то встаёт между вами и сайтом и пропускает разговор через себя. Разберём, что у него получится с HTTPS, а что нет, — и в каких случаях посередине всё-таки читают всё, причём вполне законно.
Это девятая часть цикла «Что происходит, когда открываешь сайт».
Почему подслушать не получится
Вспомним рукопожатие из седьмой части. Клиент и сервер обменялись половинами ключа — открытыми частями, которые видит любой на пути. Из двух открытых частей общий секрет вычисляют только стороны, у которых есть соответствующие закрытые части. Они рождаются на одно соединение и после него выбрасываются. Посредник видит обе открытые половины и всё равно не может вычислить ключ — это математическое свойство обмена ключами, а не секретность алгоритма.
Бонус: раз ключи одноразовые, даже если когда-нибудь украдут ключ сертификата сервера, записанный сегодня трафик расшифровать не выйдет. Это называют прямой секретностью, и в TLS 1.3 она обязательна.
Почему подменить тоже не получится
Хорошо, подслушать нельзя. А если посредник не подслушивает, а сам притворяется сайтом: устанавливает с вами своё TLS-соединение, а с настоящим сайтом — другое, и пересылает между ними?
Тут вступает сертификат. Чтобы браузер принял соединение, посредник должен предъявить сертификат на имя этого сайта, подписанный доверенным центром, и подписать рукопожатие его закрытым ключом. Вариантов у него три, и все плохие:
- показать настоящий сертификат сайта — он публичный, скопировать можно. Но подпись
CertificateVerifyбез закрытого ключа сайта не сойдётся, и браузер оборвёт соединение; - выпустить свой сертификат на это имя — ни один доверенный центр не выдаст его без подтверждения владения доменом. А если выдаст по ошибке, это всплывёт в публичных журналах сертификатов;
- показать самоподписанный — браузер покажет на всю страницу «Подключение не защищено».
Поэтому предупреждение о сертификате нельзя пролистывать, особенно в публичной сети. Кнопка «Всё равно перейти» — это ровно согласие пустить посредника.
Слабое место — первый запрос без S
Если вы набрали адрес без https://, браузер исторически шёл сначала по HTTP, а сайт перенаправлял на HTTPS. Этот первый открытый запрос посредник может перехватить и не пустить вас на защищённую версию — отдать свою копию по HTTP. Против этого есть заголовок HSTS:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Увидев его один раз, браузер на год запоминает: к этому сайту — только HTTPS, даже если пользователь набрал без буквы S, и никаких «всё равно перейти» при ошибке сертификата. Современные браузеры к тому же сами пробуют HTTPS первым. Проверьте, отдаёт ли ваш сайт этот заголовок: curl -sI https://example.ru/ | grep -i strict.
Осторожнее с includeSubDomains: если у вас есть поддомен, который работает только по HTTP, после этого заголовка он перестанет открываться у всех, кто побывал на основном сайте. И отменить быстро не получится — браузеры помнят срок.
Что посредник видит всё равно
Шифрование прячет содержимое, но не сам факт разговора. Как в шестой части: адрес сервера, имя сайта в SNI, объём и время. Провайдер знает, что вы были на таком-то сайте, — но не знает, какие страницы открыли и что ввели в формы. Расширение ECH (Encrypted Client Hello) шифрует и имя сайта, но работает только когда его поддерживают браузер, DNS поверх HTTPS и сервер.
Когда посередине читают всё — законно
Есть ситуация, где весь HTTPS прозрачно расшифровывается: корпоративные сети. Компания ставит на рабочие компьютеры свой корневой сертификат, и её шлюз выпускает на лету сертификаты для любого сайта, подписанные этим корнем. Браузер им доверяет — корень же в хранилище. Так работают системы защиты от утечек и фильтры корпоративного трафика.
Узнать легко: откройте сведения о сертификате любого сайта. Если в цепочке не Let’s Encrypt, DigiCert или другой публичный центр, а что-то вроде «Corporate Root CA», ваш трафик читает шлюз.
# кто на самом деле подписал сертификат, который видит ваш компьютер
echo | openssl s_client -connect example.ru:443 -servername example.ru 2>/dev/null | grep -E '^ *[0-9] s:|i:'
То же самое умеют отладочные прокси вроде mitmproxy и Charles: вы сами ставите их корень на свой компьютер, чтобы посмотреть, что отправляет приложение. Механизм тот же — разница только в том, кто поставил корень и знаете ли вы об этом.
Итог
- подслушать HTTPS со стороны нельзя — ключи вычисляют только участники;
- подменить сайт нельзя без закрытого ключа сайта или доверенного корня на вашем устройстве;
- опасны предупреждение о сертификате, которое вы пролистали, и первый запрос по HTTP — от второго защищает HSTS;
- имя сайта, адрес и объём видны всем на пути;
- чужой корень в хранилище — и посредник читает всё.
Нужно проверить, правильно ли настроен HTTPS на сайте?
Пришлите адрес — проверю переадресацию, HSTS, цепочку и шифры и скажу, что поправить.
// загружаю комментарии…