Ещё одна тема, на которой паразитируют техно-гики в России — это государственный удостоверяющий центр (SSL/TLS сертификат). К сожалению, тема крайне сложна и особенности этой технологии знают и понимают буквально единицы специалистов, остальные просто беспредметно истерят. Проблема с текущей моделью в TLS кроется совершенно в другой области и прилагать усилия по исправлению нужно именно там, но это крайне сложно, поскольку придётся бодаться с огромным межгосударственным болотом и корпоративными интересами.
Напомню историю вопроса. В 2022 году в госдуму был внесён законопроект № 244043-8, в котором предусматривается создание российского национального удостоверяющего центра (УЦ) для централизованного выпуска TLS-сертификатов для, например, сайтов. Обоснование было предельно рациональным: западные УЦ стали отказывать российским клиентам в обслуживании и перестали выдавать сертификаты для их сайтов, поэтому решили создать свой собственный УЦ, чтобы не зависеть от западных. Чтобы выданные этим новым удостоверяющим центром сертификаты корректно обслуживались на компьютерах пользователей, им нужно добавить корневой сертификат удостоверяющего центра в доверенные. И в этой статье я максимально подробно расскажу, что же это означает, какие от этого могут быть проблемы, как их можно решить и почему это никогда не будет решено.
Как работают сертификаты¶
Сначала нужно максимально подробно рассказать, как же вся устроена рассматриваемая предметная область. Без этого этого невозможно действительно понять, в чём кроются проблемы и как искать варианты их решения.
Обыватель сталкивается (часто даже не осознавая этого) с сертификатами практически только в веб-браузере, поэтому именно на этом всем понятном примере я и буду объяснять.
Сайт в браузере идентифицируется своим доменом. Вы заранее должны понимать, что cbr.ru — это сайт центробанка, а kommersant.ru — сайт газеты Коммерсантъ. Иными словами, вы сначала узнаёте настоящий адрес ресурса и только потом туда идёте. Не centrobank-rossii.ru, а именно cbr.ru. Если в офисе центробанка вам официально дали этот адрес, вы можете быть уверены, что он действительно представляет именно эту организацию. Допустим, вы пришли в банк Ваш Банк и подписали договор об обслуживании, в договоре указан сайт банка — ваш-банк.рф, на котором находится официальный персональный кабинет для дистанционного обслуживания. Вы приходите домой, открываете браузер и вбиваете адрес (без ошибок, ровно как указано в договоре), браузер загружает веб-сайт. Но как вы можете быть уверены, что это действительно сайт банка, а не подменный сайт злоумышленников?
До появления защищённых транспортных протоколов подменить сайт было достаточно легко, поскольку весь трафик от него никак не защищался, однако сейчас массово используется протокол TLS (Transport Layer Security, ранее назывался SSL — Secure Socket Layer, TLS более защищённый преемник SSL). TLS решает сразу две задачи: шифрование сетевого трафика и удостоверение принадлежности содержимого сайта владельцам этого домена, в нашем случае — ваш-банк.рф. Когда браузер устанавливает сетевое соединение в первый раз, он в рамках TLS получает от сервера банка его сертификат, в сертификате указан адрес сайта, срок действия сертификата и другие данные. Браузер проверяет соответствие сертификата домену и если проверка проходит успешно, начинает передачу данных. Для шифрования передаваемых данных также используется этот же сертификат.
Задача доверия сайту теперь сводится к технической задаче доверия сертификату. Но как браузер может быть уверен, что сертификат действительно принадлежит сайту? И здесь используется криптография, точнее, асимметричные криптосистемы.
Асимметричная криптосистема состоит из пары ключей: открытого и закрытого. Закрытый ключ является секретным и его знает только владелец, открытый ключ является публичным. Асимметричные криптосистемы в основном применяются именно для удостоверения данных: владелец закрытого ключа использует его для генерации электронной подписи некоего файла (электронная подпись представляет собой сравнительно небольшой блок данных), далее этот файл распространяется вместе с подписью и получатель может проверить подпись файла, зная только открытый ключ.
Основной сложностью при использовании асимметричных криптосистем как раз является надёжная доставка открытого ключа клиентам, чтобы этот ключ по пути не подменили злоумышленники на свой.
Сертификат сайта как раз содержит открытый ключ вместе с другими данным сайта, в частности, его доменный адрес. Поскольку сертификат у каждого сайта свой, клиент в идеальной ситуации обязан его проверять, сравнивая с эталонным, который он получил по надёжному каналу, например, в банке при заключении договора. Однако на практике такой сценарий невозможен, поскольку сертификатов очень много и получить эталонный для каждого сайта крайне сложно. По этой причине сертификат также содержит в себе ещё одну электронную подпись, удостоверяющую содержательную часть — домен, срок действия и другие параметры. Эта электронная подпись создана другим сертификатом, который называется удостоверяющим центром. Браузер проверяет достоверность сертификата сайта, используя сертификат удостоверяющего центра, их уже значительно меньше, но всё равно слишком много, чтобы хранить (и своевременно обновлять) базу сертификатов всех удостоверяющих центров на стороне клиента.
Эта проблема решается путём выстраивания цепочки доверия. Чтобы понять, как она работает, сначала нужно пояснить, какие именно данные хранятся в сертификате:
- содержательная часть сертификата:
- субъект (subject) — это имя сертификата, здесь может находиться название сайта, название организации, её адрес, email, телефон и так далее;
- эмитент (issuer) — имя сертификата, которым подписан данный сертификат;
- срок действия — диапазон дат, в котором сертификат считается достоверным;
- открытый ключ субъекта;
- признак удостоверяющего центра — параметр, определяющий, может ли этот сертификат использоваться для проверки других сертификатов;
- остальные информационные поля;
- созданная эмитентом электронная подпись содержательного блока.
Часто используется выражение данные подписаны сертификатом XXX, которое означает, что данные подписаны закрытым ключом, открытая часть которого находится внутри сертификата XXX. Аналогично используется выражение сертификат XXX выдан сертификатом YYY, что означает сразу две вещи: внутри сертификата XXX в поле эмитент стоит значение из поля субъект сертификата YYY и содержательная часть сертификата XXX подписана сертификатом YYY.
Благодаря такой структуре можно строить цепочки из сертификатов, используя значения из полей субъект и эмитент. Например, вот так выглядит цепочка из трёх сертификатов для домена этого блога:
субъект: CN = *.regolit.com
эмитент: C = US, O = Let's Encrypt, CN = E1
субъект: C = US, O = Let's Encrypt, CN = E1
эмитент: C = US, O = Internet Security Research Group, CN = ISRG Root X2
субъект: C = US, O = Internet Security Research Group, CN = ISRG Root X2
эмитент: C = US, O = Internet Security Research Group, CN = ISRG Root X2
Каждый сертификат в цепочке подписан нижеследующим сертификатом, за исключением последнего, который подписан сам собой, он называется самоподписанным.
Когда устанавливается TLS-соединение, сайт отправляет не только свой сертификат, но также и сертификаты, участвующие в цепочке подписывания. В моём случае сайт blog.regolit.com отправляет вместе с собственным сертификатом (CN = *.regolit.com
) ещё и промежуточный сертификат (C = US, O = Let's Encrypt, CN = E1
).
Если клиент считает какой-нибудь сертификат доверенным, то он также доверяет по умолчанию всем сертификатам, которые подписаны доверенным (за некоторым исключениями, которые далее указаны). На стороне клиента есть хранилище так называемых безусловно доверенных сертификатов удостоверяющих центров, все доверенные сертификаты должны состоять в цепочке, которая завершается сертификатом из хранилища. В нашем случае в хранилище находится только сертификат C = US, O = Internet Security Research Group, CN = ISRG Root X2
, а доверие ко всем остальным выстраивается иерархически и автоматически. Как правило в хранилище находятся самоподписанные сертификаты, они называются корневыми (root certificate).
Есть некоторые условия, при которых сертификат перестаёт считаться доверенным (и соответственно перестают быть доверенными все сертификаты, цепочки доверия которых завершаются проблемным):
- если сертификат находится в специальном обновляемом списке отозванных (revoked) сертификатов;
- если текущая дата находится вне границ срока действия, указанного в сертификате;
- если у сертификата из середины или конца цепочки (то есть не у первого) отсутствует признак удостоверяющего центра; иными словами, нельзя использовать для подписи сертификат, у которого нет признака удостоверяющего центра.
В итоге получается следующая схема цепочки доверия (trust chain):
- у клиента (в нашем случае браузера) есть статическое хранилище доверенных корневых сертификатов, то есть это список сертификатов, которые априори считаются принадлежащими указанным в них субъектам;
- если цепочка доверия (с учётом описанных выше условий) завершается сертификатом из статического хранилища, то такой сертификат считается доверенным.
Как работают удостоверяющие центры¶
Как правило удостоверяющие центры выписывают сертификаты за деньги, причём цены у них довольно высокие. Цель почти любого УЦ — попасть в список безусловно доверенных на стороне клиента. Списки формируют производители оборудования, операционных систем, программных библиотек или программного обеспечения. Например, в макоси есть системный список доверенных сертификатов, а браузера firefox свой собственный список, никак не связанный с системным. Также свои списки могут вести производители оборудования, например, межсетевых экранов.
Критерии попадания в этот список исключительно политические. Например, в устройствах apple есть УЦ Apple, а списке (точнее, в NSS) firefox их нет. Браузер яндекса использует все системные сертификаты УЦ плюс несколько скрытых дополнительных. В списке Firefox/NSS есть, например, сертификаты китайских или польских удостоверяющих центров, но нет российских (даже не пытались добавить) или казахстанских (не пустили).
Но стоит отметить, что далеко не всегда целью УЦ является добавление в общеиспользуемые списки. Например, корпоративные УЦ используются только внутри организации и его корневые сертификаты распространяются по клиентам корпоративными системными администраторами. Некоторые производители программного обеспечения в принципе не доверяют стандартным спискам и для доступа к собственным ресурсам используют свой собственный единственный сертификат, который включён в ПО и все соединения проверяются только им, такой подход может использоваться, например, в банковских приложениях на смартфоне.
Корневые удостоверяющие центры как правило не подписывают сертификаты самостоятельно, вместо этого создаются другие сертификаты с включённым признаком удостоверяющего центра, и уже ими подписываются оконечные сертификаты, например, сайтов.
Фактические проблемы схемы с удостоверяющими центрами¶
Теоретически модель доверия с удостоверяющими центрами хорошая, вот только практическая реализация подкачала. Как и всегда в безопасности, в полностью автоматическом режиме она работает удовлетворительно, а для надёжного использования у пользователей должно быть чёткое понимание теории и ключевых особенностей.
Основная проблема, которая полностью сейчас не решается ни одним пользовательским приложением (например, браузером) — это отслеживание изменения удостоверяющего центра с одного доверенного на другой. В случае компрометации УЦ (случайной или намеренной) клиент никак об этом сам не узнает, в том же браузере сертификат сайта по-прежнему будет считаться доверенным, хотя фактически это будет уже зловредный сайт с другим сертификатом.
Поскольку смена удостоверяющего центра происходит где-то в фоновом режиме, пользователь даже не подозревает, что сертификат его домена на самом деле уже существует в нескольких доверенных формах. Например, если домен обслуживается через Cloudflare, то для него прозрачно создаётся доверенный сертификат, закрытый ключ для которого находится, внезапно, у Cloudflare, а не у владельца домена. Например, для моего блога существует два доверенных сертификата, которым доверяет браузер, но которые я никак не контролирую: один у Cloudflare, а другой у Google Trust Services. Это совершенно легальная и официальная «фича» Cloudflare, анонсированная в 2022 году под невинным названием Backup Certificates. Является ли это безопасным? Безусловно, нет, но такова жизнь и с этим нужно либо мириться, либо не пользоваться сервисами типа Cloudflare.
Certificate transparency¶
Попытка решить эту проблему была предпринята примерно десять лет назад гуглом и вылилась в технологию Certificate Transparency (CT): все публичные удостоверяющие центры договорились вносить записи обо всех выписанных сертификатах в специальные реестры (CT Log). На данный момент полностью поддержка CT реализована в Chrome и Safari (и соответственно в порождённых от Chrome браузерах), но не реализована в Firefox. На практике это означает, что во всех выпущенных с 2018 сертификатах в содержательной части присутствует блок Embedded SCTs, в котором перечислены реестры, куда сертификат был добавлен удостоверяющим центром, а также подписанная держателем реестра дата добавления.
Chrome/Safari с 2018 года по умолчанию отказывается работать с TLS-сервером, если он не предоставляет информацию о записях в CT-реестры. В самом браузере регулярно скачиваются обновления CT-реестров и каждый сертификат в нём проверяется.
Здесь важно отметить, что политики Certificate transparency проверяются исключительно для публичных удостоверяющих центров, то есть для сертификатов, которые идут в базовой поставке клиента или операционной системы. Для вручную добавленных в доверенные сертификатов удостоверяющих центров (как, например, в корпоративных УЦ) Certificate transparency не применяется. А если по-простому: когда вы вручную добавляете сертификат в доверенные, то подписанные им сертификаты дополнительно проверяться не будут.
Также обратите внимание, что если для одного сайта было выпущено несколько сертификатов разными УЦ и все они присутствуют в CT-реестрах, пользователь никак про это не узнает.
Неплохая статья с объяснениями принципов работы CT есть на хабре. А если вам интересны технические детали реализации в Chrome, то это детально разъясняется на сайте https://googlechrome.github.io/CertificateTransparency/.
Записи о Signed Certificate Timestamp в сертификате выглядят так (на примере сертификата этого сайта):
% openssl x509 -in Downloads/regolit-com.pem -noout -text
...
CT Precertificate SCTs:
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : 7A:32:8C:54:D8:B7:2D:B6:20:EA:38:E0:52:1E:E9:84:
16:70:32:13:85:4D:3B:D2:2B:C1:3A:57:A3:52:EB:52
Timestamp : Apr 11 02:11:52.592 2023 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:45:02:21:00:D2:C1:64:A3:EA:A8:15:1B:2D:EE:FA:
9E:94:63:96:AB:18:90:9F:0E:47:6B:86:B7:55:AD:80:
2A:5D:F8:DE:D9:02:20:3C:B3:EE:8B:39:67:77:6E:2F:
C6:81:55:4F:74:CF:77:2E:0E:1A:71:79:9E:8B:BD:92:
01:84:B3:86:C7:33:F4
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : E8:3E:D0:DA:3E:F5:06:35:32:E7:57:28:BC:89:6B:C9:
03:D3:CB:D1:11:6B:EC:EB:69:E1:77:7D:6D:06:BD:6E
Timestamp : Apr 11 02:11:52.576 2023 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:46:02:21:00:A6:88:15:82:CB:B9:7A:A3:1B:49:54:
13:A6:05:CE:FB:F4:1B:4B:46:60:44:75:AF:6A:EF:1F:
FA:0A:DB:B4:4D:02:21:00:8A:6A:89:59:D6:8E:EF:5D:
64:A9:5F:62:FC:3A:58:45:E3:8E:9C:20:BF:71:E2:A9:
E1:53:DC:32:CD:CE:CC:5C
...
Здесь Log ID — это идентификатор CT-реестра, Timestamp — дата создания сертификата и Signature электронная подпись даты, созданная владельцем реестра. Лог с идентификатором 7A:32:8C:54:D8:B7...
— это Cloudflare Nimbus 2023, а с идентификатором E8:3E:D0:DA:3E:F5:06...
— Google Argon 2023.
❈ ❈ ❈
У CT-реестров есть один аспект, важность которого многие не осознают — эти реестры публичные. Если компания создаёт сертификаты через публичные удостоверяющие центры, участвующие в Certificate transparency, то все эти сертификаты вместе с доменными именами являются не просто публичными, а очень легко публично доступными благодаря сервисам мониторинга CT-реестров. Самое поразительное, что эти сервисы абсолютно легальны, никак не скрываются, но про них очень мало знают даже профильные технические специалисты. Так что если у вас есть непубличные домены с сертификатами от публичных удостоверяющих центров, то домены отныне публичные. Единственный способ скрыть их — это использовать wildcard-имена типа *.example.com
.
Поиск по crt.sh (одному из таких сервисов) может как минимум развлечь:
А как максимум послужить хорошим инструментом для исследования внутренней структуры организаций на основе доменных имён (всё так же на примере Positive Technologies):
X509v3 Subject Alternative Name:
DNS:admin.ptsecurity.com
DNS:dc1-sfb-fe-01.ptsecurity.ru
DNS:dc1-sfb-fe-02.ptsecurity.ru
DNS:dc1-sfb-fe-03.ptsecurity.ru
DNS:dialin.ptsecurity.com
DNS:lyncdiscover.ptsecurity.com
DNS:lyncdiscoverinternal.ptsecurity.com
DNS:meet.ptsecurity.com
DNS:sfb-fe-pool-01.ptsecurity.ru
DNS:sip.ptsecurity.com
DNS:skype.ptsecurity.com
Особенности работы российского национального удостоверяющего центра¶
В 2022 году был запущен российский национальный удостоверяющий центр Минцифры России. Главной целью его создания было заявлено: переход на российские TLS-сертификаты обеспечит независимость от зарубежных удостоверяющих центров и гарантирует пользователям безопасный доступ ко всем ресурсам. Скачать корневой сертификат можно с сайта Госуслуги, там же инструкции по установке для разных операционных систем и устройств.
Получить сертификат для своего домена можно (только для юрлица) бесплатно там же на госуслугах.
УЦ минцифры поддерживает Certificate transparency и соответствующие CT-реестры уже ведут Yandex, VK/Mail.ru и минцифры. В яндексе создали веб-сервис для поиска в этих реестрах: https://webmaster.yandex.ru/tools/ssl-check/. Однако эти реестры поддерживают только браузеры Yandex и Atom. При ручном добавлении сертификата в операционную систему или браузер CT-реестры игнорируются, что создаёт потенциальную угрозу безопасности. Так что если вам необходим условно-безопасный доступ к сайтам, сертификаты которого выпущены УЦ минцифры, рекомендую поставить браузер яндекса и открывать такие сайты в нём, но не импортировать сторонний сертификат в доверенные.
Безопасность сертификатов для гиков¶
И в заключение я расскажу, как можно улучшить работу с сертификатами на пользовательских устройствах на примере браузера. Под улучшением я понимаю более полный контроль над происходящим, обывателя предложенное решение будет только раздражать.
Самое главное, чего не хватает в браузерах — это гранулярного управления условиями автоматического доверия сертификатам. Сейчас максимум, что можно сделать, это заблокировать вручную какой-нибудь стандартный публичный сертификат в системном/браузерном списке доверенных УЦ. Однако хотелось бы, например, следующего:
- мониторинг изменения удостоверяющего центра сертификата (с возможностью выбора, что делать, если сертификат изменился);
- возможность назначить для сайта конкретный УЦ и запрещать установку соединения, если УЦ изменился;
- возможность добавлять (фиксировать) конкретный сертификат для конкретного сайта или сайтов в доверенные, именно оконечный сертификат, а не сертификат УЦ (в такой ситуации браузер откажется устанавливать соединение, даже если у сайта появится доверенный сертификат, отличающийся от зафиксированного);
- возможность отключать для конкретных сертификатов режимы верификации, например, по сроку действия;
- возможность добавлять свои сертификаты в доверенные с указанием конкретных CT-реестров, а также задавать приоритеты выбора сертификатов.
Все эти пожелания вряд ли будут когда-либо реализованы, поскольку создают слишком много проблем для обывателя, а интересы двинутого на безопасности гика для корпораций неприоритетны. Однако их появление вполне возможно в «гиковских» браузерах, на что я сильно надеюсь.