Как работает HTTPS?

HTTPS — это дополнительная надстройка над старым-добрым HTTP, которая повзоляет нам относительно спокойно сидеть в интернете, не опасаясь, что кто-то читает запросы по пути с паролями и данными кредитных карт. Точнее запросы по-прежнему можно читать, но вот понять что там не выйдет. Ну, или почти не выйдет, ведь систем без уязвимостей нет, верно?

Что такое HTTPS? #

HTTP — правила, по которым могут общаться клиент и сервер. Здесь ничего не меняется. Появляется дополнительный слой шифрования: TLS/SSL или просто SSL. Прежде чем отправить запрос, он шифруется, а по прибытии — расшифровывается.

SSL выполняет две функции:

Как устанавливается соединение #

Всё начинается с «рукопожатия» (handshake). Его цели:

Дальше можно шифровать сообщения.

Что? Ключ на этапе хендшейка? Разве нельзя его подменить? Это самое интересное, про это дальше.

Хендшейк состоит из трёх этапов:

На этапе привествия сервер и клиент обмениваются информацией друг о друге. Клиент говорит, что «он умеет», сервер решает какой алгоритм шифрования и версию SSL использовать с учётом того, что клиент умеет.

Теперь, когда соединение установлено, сервер должен подтвердить, что он — это действительно он. Это делается с помощью сертификата.

Обмен ключами #

Само шифрование происходит симметричным образом, т.е. есть один ключ, о котором договорились на этапе хендшейка. Он используется и клиентом и сервером, чтобы шифровать и расшифровывать сообщения.

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

Т.е. перехватить первый запрос-хендшейк и взять ключ оттуда просто бесполезно, потому что это не сам ключ, а зашифрованное сообщение. И все последующие запросы не получится прочитать, потому что этот самый ключ не известен.

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

Сертификат #

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

Сертификат это просто текстовый файлик. Тогда кто угодно может составить любой сертификат. Как понять, что он подлинный?

Цифровые подписи — стандартный способ проверить, что контент не был подделан по пути. Аналогичный образом можно, например, подписывать вебхуки.

Есть много различных CA (Certificate Authority), которые имеют право выписывать сертификаты, а браузеры знают этот список и знают, где брать публичные ключи (или хранят их сразу в билдах, без походов по сети).

Хозяйке на заметку #

Публичные wi-fi #

Может ли злоумышленник читать https-трафик? Становится ясно, что пока у него не будет приватного ключа, который надёжно хранится на сервере, то он не сможет расшифровать симметричный ключ, которым зашифрован основной трафик.

Всё, что передаётся по http — легко прочитать. Никогда не отправляйте важные данные в формах по http!

Поэтому, кстати, браузер кидает предупреждения про mixed content. Представьте айфрейм, в котором форма грузится по http, внутри https-сайта. Пользователь смотрит на «замочек» и думает, что всё безопасно, а на самом деле сабмиты формы прослушиваются.

Может ли моя компания мониторить https-трафик? #

Если есть доступ к компьютеру, то да. Достаточно добавить свой корневой сертификат в браузер, перехватывать все запросы и представляться нужным веб-сайтом, по сути, всё шифруя и расшифровывая по пути (и даже подменяя содержимое запросов). Так как сертификат добавлен в браузер, то никаких проблем с «замочком» нет.

Любопытная история с Lavabit #

Когда в 2013 году ФБР охотились за Эдвардом Сноуденом, нужно было прочитать письма почтового сервиса Lavabit, трафик которого разумеется зашифрован.

Суд предписал выдать ключи шифрования. Основатель сервиса Levison распечатал 2560 символьный ключ на 11 листах и передал судебным приставам. После чего получил 5.000$ штрафа в день до тех пор, пока не передаст ключ в электронном виде 😂

Кстати, Lavabit после этой истории закрылся, а Levison начал делать DIME — сервис с end-to-end шифрованием, чтобы в следующий раз никаких ключей нельзя было получить.

GoDaddy, который выписал сертификат, отозовал его, как только узнал о передаче ключей. Это значит, что сертификат попадает в специальный список (CRL), и браузеры постепенно перестают ему доверять, начиная показывать синий экран смерти предупреждения. Про это дальше.

Итак, вроде всё круто, трафик можно прочитать, но нельзя понять. Наши пароли и кредитные карты в безопасности…

Уязвимости #

Приватный ключ больше не приватный #

Приватный ключ — просто файлик, который хранится у вас на сервере. Каждое TLS-соединение устанавливается с помощью этого файлика, т.е. используется он постоянно. Нельзя использовать его один раз и потом убрать подальше — он должен оставаться на сервере постоянно. А значит, если получить доступ к серверу, то можно и файлик себе стянуть. Всё.

Каким образом защититься от этого?

В принципе, никак, но можно ограничить количество серверов, которые имеют доступ к серверу с приватным ключом.

Я моделировал аналогичную историю с панелью администратора, которая живёт за VPN.

Вообще, хорошо и правильно настраивать уровни доступа внутри своей корпоративной сети.

Таким образом, если хакер получит доступ к нашей сети, есть вероятность, что на сервер с приватным ключом он добраться не сможет.

Как я уже сказал выше, полностью защититься от кражи ключа невозможно. Что делать, если ключ всё-таки оказался скомпрометирован?

Не существует какого-то единого места, которое можно было бы уведомить, что сертификат невалидный, и все браузеры мгновенно перестали бы ему доверять.

Первая попытка решить эту задачу — т.н. CRL, «список отозванных сертификатов». Браузер скачивает список, проверяет нет ли там сертификата, который он собирается использовать. Это работало, но в какой-то момент эти списки стали настолько огромными, и скачивать их каждый раз стало слишком сложно.

На смену приходит специальный протокол OCSP.

Суть в том, что вместо того, чтобы перекладывать эту ответственность на клиента, она перекладывается на CA — организацию выписавшую сертификат. Там находится база данных отозванных сертификатов.

Как выглядит теперь попытка соединения между A (Алиса) и Б (Боб):

Можно ли обмануть браузер, что сертификат не отозван, хотя на самом деле отозван? Для этого теперь нужно украсть приватный ключ у CA, которым подписывается ответ.

Есть ещё одна проблема — что если сервер CA не отвечает? Такое, конечно, может быть. Ничего лучше ретраев пока не придумали 😃.

Шуточный девиз команды инфраструктуры в Яндексе, в которой я работал, был «полинги и ретраи 💪».

Какие ещё могут быть уязвимости? Можно отозвать сертификат, только если ты знаешь, что он был скомпрометирован. Однако, вряд ли хакер, который украл приватный ключ, уведомит вас по почте.

Частая смена сертификатов #

У сертификата есть «срок годности»: это может быть один месяц, а может быть 5 лет.

Желательно не лениться и заказывать сертификат на поменьше, соответственно менять почаще.

Цепочки сертификатов #

В браузерах предустановлено около 60 корневых сертификатов, которым браузеры «доверяют по умолчанию». Если приватный ключ утечёт для корневого сертификата — беда, пока не выйдет новая версия браузера с патчем.

Существует цепочка сертификатов, когда один CA доверяет другому, тот третьему, и так дело доходит до корневого сертификата. Чтобы провалидировать сертификат для домена, нужно проверить всю цепочку.

GlobalSign — корневой CA для доменов Гугла.

Так вот, имеет смысл выпускать промежуточные сертификаты, которые в случае утечки приватных ключей проще отозвать. А ключ от корневого сертификата хранить за семью печатями.

Оригинальное изображение из статьи Роберта.

Приватный ключ от корневого сертификата хранится на HSM — реальном физическом устройстве, предназначенном для хранения ключей. Это не просто софт. Даже получив доступ к физическому устройству, получить доступ к данным на нём весьма проблематично.

Если промежуточные сертификаты будут скомпрометированы, то можно их отозвать и выпустить новые, подписав корневым сертификатом, таким образом заново встроив в цепочку.

Про CA и корневые сертификаты #

CA, имеющие корневые сертификаты в браузерах, серьёзно обеспокоены своей репутацией. Например, в 2017 году Chrome выкатили дорожную карту по постепенному отказу от корневого сертификата Symantec начиная с 66 версии, по причине «утраты доверия», будто бы у Symantec были неоднократные проблемы с безопасностью. За Chrome подтянулись Mozilla и Apple, и Symantec была вынуждена продать всю часть компании про SSL, растеряв всех клиентов.

CA не выдают сертификат, не убедившись, что человек действительно владелец домена. Например, Let’s Encrypt просит либо добавить специальную DNS-запись, либо положить файлик на сервер публично доступный по выданному адресу (например, mysite.com/aDg73fN).

CTL (Certificate Transparency Logs) #

И всё-таки, а как понять, что никто не выписал сертификат для твоего домена? Рано или поздно мошенничество станет очевидно, но может быть поздно.

Гугл популяризировали идею публично доступных списков сертифатов. Владельцы доменов могут легко посмотреть какие сертификаты были выписаны для определённых доменов, и, если там есть что-то подозрительное, то писать CA с просьбой отозвать левые сертификаты, разобраться.

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

Когда CA выпускает новый сертификат, он должен отправить запись об этом как минимум в два CTL. Те в ответ отправляют подписанные сообщения вида «Я, такой-то CTL, подтверждаю у себя регистрацию сертификата», и подписи добавляются в сам сертификат.

Теперь можно мониторить сертификаты, выпущенные для своего домена. Например, вот лог для домена vitkarpov.me.

Есть и обратная сторона медали наличия таких списков: злоумышленники могут прочёсывать списки всех доменов. Скажем, посмотреть какие сертификаты выписаны для Фейсбука.

Вероятно, какой-нибудь dewey-lfs.vip.facebook.com может быть менее надёжно защищен, чем facebook.com, и без этих списков не привлёк бы внимания.

Зачем вообще CA отправлять сертификаты в CTL? Ведь это дополнительный шаг, который самим CA как таковым не нужен. Дело в том, что браузеры вынуждают их это делать. Без двух подписей от двух различных CTL браузеры отказывают доверять сертификату.

Любопытно посмотреть, каким образом CTL хранит списки сертификатов. Это не просто текстовый файлик, который можно переписать, проведя изменения задним числом. CTL обязаны хранить списки в виде деревьев Меркла. Так же работает блокчейн: каждая следующая нода в дереве подписывается хешом от контента её детей, таким образом нельзя просто так взять и поменять что-то в прошлом — получается append only лог.

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

Certificate Authority Authorization (CAA) #

Владелец домена может помочь CA сделать процесс безопаснее, ведь и владельцы доменов, и выписывающие сертификаты организации заинтересованы в этом в равной степени.

CAA — специальная DNS-запись, которую может создать владелец домена. Запись содержит список CA, которые имеют право выписывать сертификаты для домена. Соответственно, CA должен проверить этот список и найти там себя. Конечно, CA могут и не следовать этому правилу — не проверишь. Но в их же интересах снижать вероятность появления новых векторов атак.

По отчётам Qualys на январь 2020 года только 6.8% из 150 тысяч наиболее популярных https-сайтов пользуются CAA.

Так что это уже совсем свежая история. Одним словом, PKI не думает останавливаться в развитии.

В заключение #

PKI (Public Key Infrastructure) — сложная и интересная система, со всеми этими организациями проверяющими друг друга.

Разработчики Хрома могут легко убить большой бизнес CA при желании, исключив его из корневых сертификатов.

А чего стоит один Hardware Security Module? Когда весь бизнес зависит от безопасности приватного ключа — лучше быть параноиком.

Мир информационной безопасности сложен, но интересен и поэтому прекрасен.

Материалы #

PS. Обсудить можно в телеграм-чате любознательных программистов. Welcome! 🤗

Подписывайтесь на мой твитер или канал в телеграме, чтобы узнавать о новых разборах задач.