Компрометация промежуточного CA: рвётся цепочка доверия
Инцидент с промежуточным CA eMudhra показывает, как слабые ключи подрывают доверие Web PKI. Разбираем риски и как проверить и обновить клиенты.

Вот мысль, которая звучит наоборот: самые страшные инциденты с центрами сертификации — это не те, где злоумышленник взламывает систему. Недавняя компрометация промежуточного CA eMudhra тому подтверждение: восемь ключей промежуточных CA можно было восстановить прямо из самих сертификатов, без всякого вторжения, потому что церемония генерации ключей самого CA выдала приватные ключи настолько слабыми, что один из них буквально равнялся числу 4. Никто эти ключи не крал. Они родились скомпрометированными. И это более пугающий сценарий, чем любой взлом, ведь его не исправить ротацией учётных данных и латанием дыры. Доверие было изначально дефектным.
Если вы запускаете что-либо, что устанавливает TLS-соединения вне браузера — а вы запускаете — эта история стоит вашего внимания. Браузеры защитили в течение нескольких дней. Остальная экосистема — curl в ваших cron-задачах, Python-сервисы с закреплённым certifi, Go-бинарники с вшитыми корневыми хранилищами — всё ещё догоняет. Давайте разберём, что именно произошло, почему компрометация промежуточного CA принципиально хуже компрометации конечного сертификата и что неравномерное исправление говорит о состоянии отзыва сертификатов в современном интернете.
Что на самом деле пошло не так у eMudhra
Согласно предварительной оценке самого CA в трекере инцидентов Mozilla, история почти до боли обыденная. Скрипт церемонии генерации ключей — контролируемый, аудируемый процесс, в ходе которого CA создаёт свои самые чувствительные ключи — был изменён с одобренным отклонением, чтобы протестировать процедуру wrap/unwrap ключа для экспорта. Ошибка в этом изменённом коде привела к тому, что на HSM сгенерировался второй набор ECC-ключей, и эти ключи были слабыми. Не «слабыми с пониженной энтропией». Слабыми настолько, что их можно восстановить прямо из публичного сертификата.
Подумайте, что это значит. Приватный ключ ECC должен быть случайным 256-битным числом. Безопасность всей схемы опирается на задачу дискретного логарифмирования: зная публичный ключ, найти приватный скаляр должно быть вычислительно невозможно. Но если ваш «случайный» скаляр — это один байт, публичный ключ — это просто точка-генератор, умноженная на этот байт, и любой может перебрать все 256 вариантов за микросекунды на ноутбуке. Один из восьми ключей, по сообщениям, был целым числом 4. Это не компрометация в традиционном смысле; это сертификат, который никогда не был по-настоящему защищённым, выпущенный под корнем, которому доверяют Mozilla, Microsoft, Apple и Chrome.
Исследователь, который сообщил о проблеме, по имени Wayne, доказал владение, подписав сообщение каждым из восьми приватных ключей и отправив подписи в программы корневых сертификатов. Любой мог проверить доказательство парой команд OpenSSL: извлечь публичный ключ из каждого промежуточного сертификата и проверить, что подпись на сообщении верифицируется с ним. В этом и есть элегантная и пугающая сторона криптографического доказательства владения ключом: никакой двусмысленности, никакого «мы серьёзно относимся к безопасности» в PR-тумане. Математика либо сходится, либо нет. Здесь сошлась.
Почему компрометация промежуточного CA хуже компрометации конечного сертификата
Когда приватный ключ конечного сертификата утекает — скажем, ключ для api.example.com оказывается в публичном репозитории GitHub, — радиус поражения ограничен одним именем хоста, максимум несколькими, если это wildcard. Вы отзываете сертификат, выпускаете новый и двигаетесь дальше. Неприятно, но не экзистенциально.
Ключ промежуточного CA — совсем другой зверь. Web PKI работает как цепочка подписей: корневой CA (хранится офлайн и охраняется как ядерный материал) подписывает промежуточные, а промежуточные подписывают конечные сертификаты, которые серверы реально предъявляют. Тот, кто владеет приватным ключом промежуточного CA, и есть этот CA во всех криптографических смыслах. Он может выпустить валидный сертификат для google.com, для вашего банка, для вашего внутреннего домена SSO — и каждый клиент, доверяющий цепочке, примет его без жалоб. Нет ни лимитов, ни центрального органа, которому можно позвонить, ни способа отличить мошенническую, но валидную подпись от легитимной.
Инцидент с eMudhra умножил это на восемь промежуточных CA, часть из которых была кросс-подписана корнями Sectigo и попадала в хранилища доверия, установленные на миллиардах устройств. Примерно полтора года — от момента создания проблемных сертификатов до раскрытия — любой клиент, доверявший этим промежуточным CA и не проверявший Certificate Transparency, мог стать объектом подмены для любого, кто сумел восстановить ключи. Вот это окно. Мы просто не знаем, использовал ли его кто-то, и без удачной находки в журнале CT или наблюдаемой атаки, возможно, так и не узнаем.
Именно поэтому программы корневых сертификатов относятся к инцидентам с промежуточными CA с такой серьёзностью, которой никогда не удостаиваются инциденты с конечными сертификатами. Недоверие к промежуточному CA означает, что все выпущенные им сертификаты становятся недействительными — тысячи сайтов ломаются одновременно. История с недоверием к Symantec, растянувшаяся на годы, — канонический пример того, насколько болезненным становится полное исправление, когда операции CA признаны недостойными доверия. Система работает, но работает как ампутация, а не как хирургия.
Certificate Transparency — случайный герой
Самая важная часть этой истории заслуживает большего внимания: Chrome, Safari, Firefox и Edge были, пожалуй, защищены до того, как кто-либо узнал о проблеме. Не благодаря отзыву, а благодаря Certificate Transparency.
Браузеры, проверяющие CT, требуют, чтобы каждый публично доверенный сертификат, который они принимают, был записан в публичные журналы CT, доступные только для добавления. У скомпрометированных промежуточных CA eMudhra нет записей в журналах CT за интересующий период, а значит, любой конечный сертификат, выпущенный злоумышленником с этими ключами, всё равно был бы отвергнут клиентами, проверяющими CT: он пришёл бы без валидных подписанных временных меток сертификата (SCT). Чтобы поддельному сертификату поверили, его пришлось бы опубликовать, а публикация мгновенно выдала бы его.
CT задумывался, чтобы выявлять неправильную выдачу задним числом, делая поддельные сертификаты обнаруживаемыми. В этом инциденте он сработал как превентивный механизм: он сделал скомпрометированные ключи почти бесполезными против браузерной аудитории, которая является главной целью массового перехвата трафика. Это по-настоящему хорошая новость для инфраструктуры, о которой большинство инженеров никогда не думает.
Но — и здесь я признаю пределы своего оптимизма — проверка CT по сути является роскошью браузеров. Большинство TLS-клиентов в интернете SCT не проверяют. Ваш вызов curl не проверяет. Ваш вызов requests в Python не проверяет. Парк IoT-устройств, которые звонят домой в облако вендора, не проверяет. Для всех них единственной защитой были данные об отзыве, вовремя попавшие в хранилище доверия, и вот тут история становится неприглядной.
Разрыв в отзыве сертификатов: браузеры против всего остального
Вендоры браузеров справились хорошо, и они заслуживают признания за инфраструктуру, построенную десятилетие назад. Mozilla уже больше десяти лет поставляет OneCRL — механизм push-доставки для недоверия к промежуточным и корневым сертификатам, — и это исправило инцидент для пользователей Firefox в течение нескольких часов, без обновления браузера. CRLSets Chrome и аналогичные механизмы Apple сделали то же самое на их платформах за несколько дней. CA отозвал промежуточные сертификаты. С точки зрения пользователя браузера этот инцидент закончился почти раньше, чем начался.
Теперь посмотрите на мир за пределами браузеров. Список исправлений выглядит как инвентаризация цепочки поставок ПО: обновлённые пакеты ca-certificates для Ubuntu, Debian, Fedora, Alpine, Arch, Gentoo; новый релиз NSS; новый бандл CA для curl; certifi для Python; rustls-webpki и webpki-roots для Rust; патч-релизы Go; патч-версии Electron на трёх линейках релизов; ca-bundle для Composer; castore для Elixir. Каждый из них — отдельный артефакт со своим графиком выпусков и своим механизмом обновления. Некоторые всё ещё висели в ожидании через несколько дней после раскрытия.
А ещё есть категория, которая не даёт мне спать по ночам: софт, который вшивает собственное хранилище CA прямо в бинарник. Статически слинкованный Go-сервис, собранный в прошлом году, несёт свои корни в скомпилированном артефакте. Единственное исправление — пересборка и переразвёртывание, системного пакета для патча нет. Умножьте это на каждый образ контейнера в вашем реестре с вшитым слоем /etc/ssl/certs, на каждое Electron-приложение на каждом десктопе, на каждый образ прошивки подключённого устройства — и вы увидите масштаб проблемы. Системное хранилище доверия — самая лёгкая часть. Ранее мы писали о том, как встроенные и OT-устройства превращают инциденты безопасности в многолетние эпопеи; компрометация CA — ровно то событие, после которого эти устройства просто никогда не получают исправления.

Длинный хвост хранилищ доверия, которыми никто не владеет
В этом инциденте есть особый случай, который заслуживает отдельного абзаца, потому что он идеально иллюстрирует проблему: macOS. Платформа Apple оперативно заблокировала скомпрометированные промежуточные CA на уровне ОС. Но встроенный /usr/bin/curl проверяет по /etc/ssl/cert.pem — файлу, который не обновили, — и отзыв не проверяет. Так что может быть полностью пропатченный Mac, где Safari отвергает подделку, а curl на той же машине спокойно её принимает. Два решения о доверии, одна машина, противоположные ответы.
Эта фрагментация и есть главный урок. Мы часто говорим о «Web PKI», как будто это одна система. На деле это десятки систем с очень разными свойствами:
- Браузеры: отзыв через push (OneCRL, CRLSets), проверка CT, автообновления. Исправление занимает от часов до дней.
- Хранилища доверия ОС: обновления через менеджер пакетов (ca-certificates, ca_root_nss). Исправление зависит от графика выпусков дистрибутива и от того, получает ли машина вообще патчи.
- Экосистемы языков: certifi, webpki-roots, встроенные корни Go, встроенное хранилище Mozilla в Node. Исправление означает выпуск релиза и ожидание обновления зависимостей в тысячах проектов.
- Скомпилированные артефакты и образы: бинарники, контейнеры, прошивки. Исправление означает пересборку и переразвёртывание, а на практике — длинный уязвимый хвост, растянувшийся на годы.
- IoT и встраиваемые системы: часто вообще нет пути обновления. Фактически постоянная уязвимость.
Браузеры десятилетие вкладывались именно в такой сценарий. Почти никто другой — нет. Один комментарий вышестоящей стороны от Mozilla сформулировал прямо: за пределами экосистемы браузеров в отзыв сертификатов почти не инвестировали, и для таких клиентов подобный класс инцидентов — огромная проблема. Это совпадает со всем, что я видел, управляя инфраструктурой. Если вы сталкивались с слепыми зонами в логировании событий облачной аутентификации, вы узнаете этот паттерн: критический путь хорошо инструментирован, а длинный хвост — тёмная комната.
Как проверить, уязвимы ли ваши клиенты
Теория теорией, но проверить парк нужно на самом деле, и хорошо то, что TLS можно протестировать эмпирически. Участники сообщества подняли хосты, отдающие сертификаты, подписанные скомпрометированными промежуточными CA; если ваш клиент подключается без ошибки сертификата, он всё ещё им доверяет. Общий паттерн проверки curl или любого другого инструмента командной строки выглядит так:
# A certificate error here means you're protected.
# A successful response means this client still trusts a compromised intermediate.
curl -v https://dv-g3b-emudhra.we-have-a-problem.com/
# You can also test whether a client will accept a forged cert for an
# arbitrary hostname by pointing it at a test server:
curl -v https://example.org --connect-to example.org::2.29.126.86:
Запустите это из каждого контекста, который важен: ваши ноутбуки разработчиков, ваши CI-раннеры, базовые образы контейнеров, ваши серверные парки. Ответ будет отличаться в разных местах, и именно эти различия и важны. Для быстрой инвентаризации того, что нужно обновить:
- Сервисы на Go: пересоберите с Go 1.27.3 или 1.26.10 или новее — корни вшиты в бинарник.
- Python: certifi 2026.10.19 или новее (проверьте также версии
pipиuv, они тоже бандлят собственные хранилища). - Rust: rustls-webpki 0.103.16 и webpki-roots / webpki-root-certs 1.0.10.
- Node.js и Electron: ожидающие или патч-релизы для каждой линейки; проверьте каждый поставляемый артефакт.
- Системные хранилища: обновлённые пакеты ca-certificates уже вышли для Ubuntu, Debian, Fedora, Alpine, Arch, Gentoo; ca_root_nss во FreeBSD на момент написания ещё ожидал обновления.
Если ждать пакета нельзя, большинство Linux-дистрибутивов позволяют вручную отозвать доверие к затронутым корням. В Debian/Ubuntu достаточно пометить сертификаты префиксом ! в /etc/ca-certificates.conf и выполнить update-ca-certificates; в семействе Fedora/RHEL корни извлекаются в /etc/pki/ca-trust/source/blocklist/, после чего запускается update-ca-trust. В NixOS есть аккуратная декларативная опция:
security.pki.caCertificateBlacklist = [
"Comodo AAA Services root"
"emSign ECC Root CA - G3"
];
Обратите внимание, что именно вы отзываете в этих обходных путях: корни, к которым привязаны эти промежуточные сертификаты. Это грубая реальность исправления PKI. В большинстве инструментов хранилищ доверия нет примитива «не доверять только этому промежуточному CA», поэтому вы вносите в чёрный список корень и принимаете побочный ущерб для не связанных с проблемой сертификатов. В экстренной ситуации это правильный выбор, но это всё же компромисс.
Где моя контринтуитивная мысль ломается
Я начал с утверждения, что самостоятельные сбои генерации ключей хуже взломов. Давайте честно: здесь это утверждение ломается. Традиционный взлом — вспомним DigiNotar — хотя бы подразумевает, что CA работал компетентно, пока атакующий не переиграл его, а на компетентных CA держится вся система. Церемония, которая выдаёт приватный ключ «4», говорит о том, что ни аудируемые контроли, ни процедуры HSM, ни галочки соответствия не поймали катастрофический дефект в самой чувствительной операции CA. Это не проблема противника; это проблема гарантий, а гарантии — и есть весь продукт, который продаёт CA.
Где утверждение действительно не работает: взломы труднее предотвратить и они могут оставаться незамеченными дольше. Злоумышленник, который аккуратно украл промежуточный ключ, может использовать его скупо, для точечного перехвата, и ни разу не столкнуться с клиентом, проверяющим CT. Слабые ключи, напротив, может найти любой, кто сканирует публичные сертификаты — именно так эта проблема и всплыла. Есть аргумент, что катастрофично-но-очевидное лучше тонкого-но-целевого. Я не до конца с ним согласен, но и отмахнуться не могу. По сути, оба режима отказа приводят в одно место: к промежуточному CA, которому нужно перестать доверять, и к длинному хвосту клиентов, которые получат это сообщение через месяцы.
Что вам действительно стоит сделать
Web PKI вы не почините. Но можно уменьшить свою уязвимость к следующему сбою:
- Проверяйте, а не предполагайте. Прощупайте свои клиенты на хостах, отдающих скомпрометированные цепочки. Это займёт полдня и наверняка удивит.
- Пересобирайте скомпилированные артефакты. Бинарники Go и образы контейнеров несут хранилища доверия с собой. «Мы пропатчили базовый образ» ничего не значит, пока вы не переразвернули сервисы.
- Инвентаризируйте хранилища доверия. Нельзя исправить то, что вы не перечислили. Считайте копии certifi, вендорные бандлы и приложения Electron так, будто это важно, — потому что так и есть.
- По возможности используйте системные хранилища доверия. Каждый вендорный бандл — это патч, который вы забудете доставить. Централизация на системном хранилище не решает проблему полностью, но даёт одну точку, за которую можно ухватиться.
- Следите за экосистемой CT и отзыва. Проекты, которые стремятся принести отзыв уровня браузеров в не-браузерные клиенты, существуют и заслуживают поддержки; этот инцидент — лучший аргумент в пользу их финансирования, который они когда-либо получат.
- Относитесь к инцидентам CA как к инцидентам безопасности. Они должны будить дежурного, запускать инвентаризацию и порождать письменную запись — так же, как утёкший учётные данные. Потому что это именно они и есть.
Неприятный итог: аварийный тормоз Web PKI отлично работает именно в тех клиентах, которым он нужен меньше всего, потому что CT их уже прикрывает. Клиенты, которым тормоз действительно нужен — headless, встроенные, вендорные, забытые, — в основном его не имеют. Следующая компрометация промежуточного CA — вопрос «когда», а не «если». Единственная переменная под вашим контролем — заметит ли ваш собственный парк.


