
Writeup de detecção no Splunk para CVE-2026-54121 (CertiGhost): abuso de certificate chase no AD CS levando ao comprometimento total do domínio. Detecção validada em laboratório, etapas de triagem e investigação de incidentes contra um DC ativo.
Este documento descreve a detecção Splunk criada para CVE-2026-54121. Ele segue o formato padrão de caso de uso de detecção para que possa integrar um catálogo de detecções da mesma forma que uma equipe real de engenharia de detecção o manteria.
Visão Geral
Construção da Detecção
Resposta e Validação
Roteiro
Metadados
Alerta : Certighost ( CVE-2026-54121 )
Detecta o abuso do mecanismo de perseguição de inscrição de certificados do AD CS descrito em CVE-2026-54121. A regra sinaliza eventos do ciclo de vida de certificados na CA em que o alvo de perseguição fornecido pelo solicitante (o atributo cdc) não resolve para o Controlador de Domínio legítimo, que é exatamente o mecanismo que o Certighost utiliza para fazer a CA emitir um certificado contendo dados de identidade do Controlador de Domínio para um solicitante de baixo privilégio, resultando em comprometimento total do domínio e tomada de controle.
A detecção é ancorada no alvo de perseguição cdc em vez da criação de conta de máquina porque o aviso da Microsoft para CVE-2026-54121 lista a pré-condição de conta como sendo um valor padrão de ms-DS-MachineAccountQuota ou uma conta que o atacante já controla. Uma regra baseada na criação de conta perderia completamente o segundo caminho e também dependeria de a criação da conta e a exploração ocorrerem dentro da mesma janela de tempo. A verificação do cdc cobre ambos os caminhos e não possui tal dependência.
Esta regra cobre o estágio de solicitação e emissão de certificados da cadeia de ataque.
| Tática | Técnica (ID) | Evidência |
|---|---|---|
| Escalonamento de Privilégios | Abuse Elevation Control Mechanism (T1548) | Usuário de domínio com baixos privilégios escala para privilégios de Controlador de Domínio via certificado AD CS forjado |
| Acesso a Credenciais | Steal or Forge Authentication Certificates (T1649) | Núcleo do Certighost - atributos cdc/rmd usados para obter certificado com material de identidade do DC |
| Acesso a Credenciais | OS Credential Dumping: DCSync (T1003.006) | TGT para conta do DC usado para realizar replicação MS-DRSR - extrai krbtgt e todos os hashes de contas |
| Acesso a Credenciais | Golden Ticket (T1558.001) | Com o hash krbtgt, o atacante forja TGTs Kerberos indefinidamente, sobrevivendo a redefinições de senha |
| Evasão de Defesa | Use Alternate Authentication Material: Pass-the-Ticket (T1550.003) | TGT baseado em certificado usado para autenticar como DC, em seguida DCSync realizado com esse TGT |
| Persistência | Create Account: Local Account (T1136.001) | Conta de máquina criada via ms-DS-MachineAccountQuota para autenticar endpoint LDAP malicioso |
| Movimento Lateral | Use Alternate Authentication Material (T1550) | Certificado do DC concede acesso total à rede equivalente à conta do Controlador de Domínio |
| Descoberta | Domain Account (T1087.002) | Enumeração LDAP inicial descobre CA, DC, SID do domínio, GUID e valor MAQ |
4886 (Solicitação de certificado recebida)4887 (Certificado emitido)4888 (Solicitação de certificado negada)![Fontes de log confirmadas ao vivo no Splunk, host DC01, EventCodes 4886/4887 presentes, alvo de perseguição 172[.]66[.]66[.]33 extraído para 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, depois issued ou denied) apareça como uma única linha.