Перехват TLS и защита канала
Разбираем, почему перехватить TLS «на лету» нельзя без доверенного сертификата, как устроена легальная инспекция в корпоративной сети — и как защитник усиливает канал через pinning и HSTS.
TLS-перехват (TLS MITM) — попытка встать между клиентом и сервером в зашифрованном соединении; он удаётся только если клиент доверяет сертификату, который предъявляет посредник, иначе соединение обрывается с ошибкой.
Урок концептуальный и оборонительный. Перехват чужого TLS-трафика без согласия — это статьи 272/274 УК РФ. Легальные сценарии инспекции (корпоративный прокси) работают с ведома владельца устройств и с явно установленным доверенным корневым сертификатом. Всё, что ниже, — на своём стенде и ради защиты канала.
Зачем это знать защитнику
TLS — основа доверия в вебе: он даёт шифрование, целостность и аутентификацию сервера. Если разработчик понимает, что именно проверяет TLS и где он может быть ослаблен (отключённая проверка сертификата, доверие к чужому корню), он не оставит в приложении дыру, через которую перехват станет возможен. Понимание pinning и HSTS позволяет сделать канал устойчивым даже к компрометации удостоверяющих центров.
Почему TLS нельзя перехватить «просто так»
При установлении соединения сервер предъявляет сертификат, подписанный доверенным удостоверяющим центром (CA). Клиент проверяет: подпись валидна, цепочка ведёт к корню из доверенного хранилища, имя в сертификате совпадает с доменом, срок не истёк. Дальше стороны согласуют ключи (современный TLS 1.3 — через эфемерный обмен), и канал шифруется. Чтобы посреднику читать трафик, ему нужно предъявить клиенту свой сертификат на тот же домен — но он не сможет его правильно подписать, не владея приватным ключом доверенного CA. Поэтому при попытке вклиниться клиент видит ошибку:
NET::ERR_CERT_AUTHORITY_INVALID # сертификат подписан недоверенным CA
SSL: certificate verify failed # цепочка/имя не прошли проверку
Из этого следует ключевой вывод: перехват TLS возможен только при наличии доверия — например, если в хранилище клиента заранее установлен корневой сертификат посредника (так работает корпоративная инспекция: ИТ-отдел разворачивает свой корень на управляемые ноутбуки легально и открыто). На стенде это и показывают: импортируют учебный корневой сертификат в свою же ВМ, и прокcи вроде mitmproxy начинает «видеть» трафик — но только потому, что вы сами выдали ему доверие на своей машине.
Проверить, чей сертификат реально отдаёт сервер, — обычная диагностика на своём хосте:
# Кто выдал сертификат и на какой домен (диагностика своего соединения)
openssl s_client -connect example.com:443 -servername example.com < /dev/null \
| openssl x509 -noout -issuer -subject -dates
Где разработчик случайно открывает дыру
Самая частая ошибка — отключить проверку сертификата в клиенте «чтобы заработало» (например, на этапе отладки) и забыть вернуть. Тогда приложение примет любой сертификат, и MITM становится тривиальным. Это анти-паттерн:
# ОПАСНО: клиент перестаёт проверять сертификат — TLS обесценен
http_client(verify=False) # псевдокод: проверка отключена
curl -k https://... # -k/--insecure тоже отключает проверку
Никогда не отключайте verify в продакшене. Если сертификат внутренний — добавьте корпоративный CA в доверенные правильным образом, а не выключайте проверку целиком.
Как это работает под капотом
Безопасность TLS держится на цепочке доверия: клиент верит ограниченному списку корневых CA, а те (через промежуточные) ручаются за сертификаты сайтов. Слабое место модели — она доверяет всем CA в хранилище одинаково: если хоть один CA скомпрометирован или вынужден выдать «левый» сертификат, он подпишет валидный с точки зрения клиента сертификат на чужой домен. Поэтому усиленные защиты не заменяют, а сужают доверие: certificate pinning говорит «для этого домена верь только вот этому ключу/сертификату, а не всему хранилищу CA».
Как защититься
1. Строгая проверка сертификата — база. Всегда проверяйте подпись, цепочку, срок и совпадение имени; никогда не оставляйте verify=False/-k вне отладки. Это минимум, без которого остальные меры бессмысленны.
2. Certificate pinning — для критичных клиентов (например, мобильных приложений). Приложение заранее «прибивает» ожидаемый сертификат или его публичный ключ и принимает соединение, только если сервер предъявил именно его. Даже валидный сертификат от другого (пусть и доверенного) CA будет отклонён — это ломает MITM через скомпрометированный/корпоративный корень. Концептуально:
# Идея pinning: принять соединение, только если хэш ключа сервера совпал с ожидаемым
expected_spki_sha256 = "base64-хэш-публичного-ключа-сервера"
if server_cert_spki_sha256 != expected_spki_sha256:
abort_connection() # даже валидный по CA сертификат отвергаем
Минус pinning — операционная хрупкость: при плановой смене ключа нужно заранее обновить пины (поэтому пинят набор с резервным ключом). Это осознанный компромисс ради защиты от подмены CA.
3. HSTS — защита от даунгрейда и подмены на старте. Заголовок HTTP Strict Transport Security заставляет браузер ходить на домен только по HTTPS и запрещает пользователю «проскочить» предупреждение о плохом сертификате. Это закрывает атаки, где посредник пытается удержать жертву на http или подсунуть невалидный сертификат:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Директива preload позволяет внести домен в встроенный в браузеры список HSTS — тогда первое же соединение идёт по HTTPS, без окна уязвимости при самом первом визите.
4. Мониторинг сертификатов и свежий стек. Следите за публичными логами Certificate Transparency на предмет «чужих» сертификатов, выпущенных на ваш домен (признак злоупотребления CA); держите TLS-библиотеки в актуальной версии и отключайте устаревшие протоколы (SSLv3, TLS 1.0/1.1). Проверка сертификата предотвращает MITM, pinning сужает доверие, HSTS убирает даунгрейд, CT-мониторинг ловит злоупотребления — слои в глубину.
Итоги
- TLS аутентифицирует сервер: перехват возможен только при доверии к сертификату посредника (заранее установленный корень) — иначе соединение рвётся с ошибкой.
- Главная самодельная дыра — отключённая проверка сертификата (
verify=False,curl -k); в продакшене это недопустимо. - Модель доверия CA — слабое звено: certificate pinning сужает доверие до конкретного ключа для домена.
- HSTS (и
preload) убирает даунгрейд на http и «проскок» предупреждений; CT-мониторинг ловит чужие сертификаты на ваш домен. - Перехват чужого TLS без согласия = ст. 272/274 УК РФ; легальная инспекция — только на своих устройствах с открыто установленным корнем.