
CVE-2026-54121 (Certighost) AD CS DC-impersonation PoC. Patched SAN handling + MAQ-safe account reuse.
A working fork of the proof-of-concept tool for CVE-2026-54121, also known as Certighost. Original research and PoC by @H0j3n and @aniqfakhrul detailed analysis at:
This fork fixes the SAN handling that prevented PKINIT from succeeding on CAs that honor the requested SAN, hardens the --target-san parsing, and reworks the computer-account handling so it no longer exhausts the ms-DS-MachineAccountQuota.
Execute as root because the rogue LDAP and SMB services require the privileged ports 389 and 445.
sudo python3 certighost.py -d playground.local -u lowpriv -p 'Password1234' --dc-ip 192.168.1.10
Upon successful completion, the target certificate (.pfx) and Kerberos cache (.ccache) are written to the current working directory.
CERTIGHOST$, created on first run) or use one specified via --computer-name.cdc attribute pointing to a controlled IP (via --listener; optional, auto-detected if omitted) plus an rmd attribute carrying the target DC's DNS name..ccache and NT hash.The original built the certificate SAN both the CSR subjectAltName extension and the SAN:dns= request attribute from the rogue computer's hostname instead of the target DC's FQDN. On a CA that honors the requested SAN, the issued certificate therefore carried the rogue account's dNSHostName, so PKINIT mapped it to the wrong principal and failed with:
KDC_ERR_CLIENT_NAME_MISMATCH(Reserved for PKINIT)
The SAN now uses the target DC's dNSHostName (rmd_value / target_dns), which is what PKINIT maps a machine account on. The issued certificate now presents DNS:<dc>.<domain> and the AS-REQ closes as the DC.
--target-san--target-san now accepts any of MEEREEN, MEEREEN$, or the FQDN meereen.essos.local (matched by sAMAccountName or dNSHostName), instead of only the short NAME form.
The original created a fresh random GHOST********$ account on every run. Because computer accounts created via the ms-DS-MachineAccountQuota are owned by Domain Admins (not the creator), a low-privileged user cannot delete them, so repeated runs quickly exhausted the quota (default 10) with orphaned accounts.
This fork reuses a single stable account (CERTIGHOST$, created only if it does not already exist), so the quota never grows and there is nothing to clean up between runs.
When the account is created for the first time, the script prints a warning noting it is left in AD:
[!] WARNING: computer account CERTIGHOST$ was created and is left in AD.
The account remains for reuse on subsequent runs. To remove it entirely, delete it with a Domain Admin (the object owner):
Get-ADComputer CERTIGHOST | Remove-ADComputer -Confirm:$false
impacketcryptography, pyasn1, asn1crypto, pycryptodomexFor authorized security testing and educational purposes only. Use it only against systems you have explicit permission to test.