
Разбор обнаружения в Splunk для CVE-2026-54121 (CertiGhost): злоупотребление отслеживанием сертификатов AD CS, приводящее к полной компрометации домена. Проверенное в лабораторных условиях обнаружение, этапы триажа и расследование инцидента на реальном контроллере домена.
В этом документе описан механизм обнаружения для Splunk, созданный для CVE-2026-54121. Он следует стандартному формату сценария обнаружения, чтобы его можно было разместить в каталоге обнаружений так же, как это делала бы реальная команда инженеров по обнаружению.
Обзор
Построение обнаружения
Реагирование и проверка
План развития
Метаданные
Оповещение : Certighost ( CVE-2026-54121 )
Обнаруживает злоупотребление механизмом погони за целью (chase) при регистрации сертификатов в AD CS, описанным в CVE-2026-54121. Правило отмечает события жизненного цикла сертификатов на CA, когда указанная запрашивающей стороной цель погони (атрибут cdc) не разрешается в легитимный контроллер домена, — именно этот механизм Certighost использует, чтобы заставить CA выдать сертификат, содержащий данные идентичности контроллера домена, низкопривилегированному запрашивающему, что приводит к полной компрометации домена и его захвату.
Обнаружение привязано к цели погони cdc, а не к созданию учётной записи компьютера, поскольку рекомендации Microsoft по CVE-2026-54121 указывают в качестве предварительного условия для учётной записи либо значение по умолчанию ms-DS-MachineAccountQuota, либо учётную запись, уже контролируемую атакующим. Правило, основанное на создании учётной записи, полностью упустило бы второй путь, а также зависело бы от того, что создание учётной записи и эксплуатация произойдут в одном и том же временном окне. Проверка cdc охватывает оба пути и не имеет такой зависимости.
Это правило охватывает этап запроса и выдачи сертификата в цепочке атаки.
| Тактика | Техника (ID) | Доказательство |
|---|---|---|
| Повышение привилегий | Abuse Elevation Control Mechanism (T1548) | Пользователь домена с низкими привилегиями повышает права до привилегий контроллера домена через поддельный сертификат AD CS |
| Доступ к учётным данным | Steal or Forge Authentication Certificates (T1649) | Ядро Certighost — атрибуты cdc/rmd используются для получения сертификата с идентификационными данными DC |
| Доступ к учётным данным | OS Credential Dumping: DCSync (T1003.006) | TGT для учётной записи DC используется для выполнения репликации MS-DRSR — извлекаются krbtgt и хэши всех учётных записей |
| Доступ к учётным данным | Golden Ticket (T1558.001) | С хэшем krbtgt злоумышленник бессрочно подделывает Kerberos TGT, переживая сбросы паролей |
| Обход защиты | Use Alternate Authentication Material: Pass-the-Ticket (T1550.003) | TGT на основе сертификата используется для аутентификации как DC, затем с этим TGT выполняется DCSync |
| Закрепление | Create Account: Local Account (T1136.001) | Учётная запись компьютера создаётся через ms-DS-MachineAccountQuota для аутентификации на поддельной конечной точке LDAP |
| Боковое перемещение | Use Alternate Authentication Material (T1550) | Сертификат DC предоставляет полный сетевой доступ, эквивалентный учётной записи контроллера домена |
| Разведка | Domain Account (T1087.002) | Первоначальное перечисление LDAP обнаруживает CA, DC, SID домена, GUID и значение MAQ |
4886 (Получен запрос на сертификат)4887 (Сертификат выдан)4888 (Запрос на сертификат отклонён)![Источники логов подтверждены в Splunk, хост DC01, EventCodes 4886/4887 присутствуют, цель погони 172[.]66[.]66[.]33 извлечена для Request IDs 12, 13, 14](images/log-sources.png)
index=wineventlog-lab sourcetype=WinEventLog source="WinEventLog:Security"
(EventCode=4886 OR EventCode=4887 OR EventCode=4888) cdc
| fields _time EventCode Request_ID Requester Attributes Subject host Message
| rex field=Message "(?m)^cdc:(?<chase_cdc>\S+)"
| where isnotnull(chase_cdc) AND lower(chase_cdc)!="dc01.atlasvec.lab"
| stats min(_time) as _time
values(Requester) as requester
values(Attributes) as template
values(chase_cdc) as chase_target
values(Subject) as cert_subject
values(EventCode) as codes
values(host) as ca_host
by Request_ID
| eval status = case(mvfind(codes,"4887")>=0,"ISSUED",
mvfind(codes,"4888")>=0,"DENIED",
true(),"PENDING")
| eval severity = "critical"
| sort - _time
| rename ca_host as "CA Host", Request_ID as "Request ID",
requester as "User Requester", template as "Certificate Template",
chase_target as "Chase Target (cdc)", cert_subject as "Issued Subject",
status as "Outcome", severity as "Severity",
_time as "Timestamp"
| table "Timestamp" "CA Host" "Request ID" "User Requester" "Certificate Template" "Chase Target (cdc)" "Issued Subject" "Outcome" "Severity"

received, затем issued или denied) отображается в виде одной строки.