If Active Directory Certificate Services (ADCS) is a familiar topic, you most likely have heard of the research published in 2021 by Will Schroeder (@harmj0y) and Lee Christensen (@tifkin_) [1]. To summarize in one sentence, ADCS certificate templates can be misconfigured, so that in the worst case, they allow any authenticated domain user to directly request a certificate in the name of any other domain user, including domain administrators. With the relevant flags configured in the template, the certificate can then be used to authenticate to the domain controller. This is also known as the ESC1 attack.
Default MDI Detection
Microsoft’s Defender for Identity (MDI) alerts by default when the authentication with such ESC1 certificates is done for example using Certipy tool’s (https://github.com/ly4k/Certipy) auth command:
certipy auth -pfx victimuser.pfx -dc-ip 10.0.0.1
The following image shows the relevant MDI alert:
As can be seen in the alert name, this method uses PKINIT Kerberos authentication. In Red Teaming engagements we often use Schannel based authentication to bypass those MDI detections.
The following example shows a successful Schannel based authentication attempt with the certificate, by opening an LDAP shell on the domain controller:
As the following KQL query shows, no MDI alert was generated:
This LDAP shell, which is from the impacket project, can be used by an attacker to for example create new users, add them to various groups or to read LAPS passwords of domain computers.
Since we wanted to be able to give Blue Teams some recommendations for improving detection, we conducted further research and got the relevant hint finally over at the SpecterOps BloodHound Slack channel (bloodhoundhq.slack.com), that the key for getting events logged would be to configure the Schannel provider.
Configuring Schannel Event Logging
Note: The following steps describe how you can enable the successful authentication events, which will cause a huge increase in logged events in the relevant CAPI2 log. Tests revealed that on a domain controller in a lab environment with only a few machines and users, the CAPI2 log configured with a maximum size of 100MB retained data for just two days. This is primarily due to the installed MDI sensor, which relies on certificate-based authentication and generated in our case most of the logged events. It is therefore recommended to verify what size is required for your environment and more importantly to ensure that only the events you need for monitoring are forwarded to a SIEM.
Schannel is a Security Support Provider (SSP) which implements various authentication protocols on Windows which use the client/server model and are based on public key cryptography (e.g. SSL, TLS, DTLS). By default, only discarded or rejected authentication events are logged on the server [2].
To log also successful authentication events, the following registry key must be set to the value of 3:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL]
"EventLogging"=dword:00000003
Additionally, the CAPI2 log in Windows (Microsoft-Windows-CAPI2/Operational) must be enabled, since this is the log where the relevant events will be stored. To do this:
- Open Event Viewer (press Win + R, type eventvwr, and press Enter)
- Navigate to Applications and Services Logs -> Microsoft -> Windows -> CAPI2 -> Operational.
- Right-click on the log and select “enable” to enable the log.
Consuming the Logs
Successful authentication using ADCS certificates will now be logged on the domain controller and the following screenshot shows an example of the user jdoe2 logging in using a certificate with the SubjectAltName of another user:
The following PowerShell script provides an example of how these events could be queried:
Get-WinEvent -LogName 'Microsoft-Windows-CAPI2/Operational' -FilterXPath '*[System[EventID=90]]' -max 10 | % { $xmlevent = ([xml]$_.toXml()).Event $certs = $xmlevent.UserData.x509Objects.certificate $systemdata = $xmlevent.system if($certs -notlike $null){ foreach($cert in $certs){ $data = [PSCustomObject]@{ Computer = $($systemdata.Computer) TimeCreated = $(Get-date $systemdata.TimeCreated.SystemTime -Format 'yyyy-MM-dd HH:mm') Issuer = $($cert.Issuer.CN) SubjectCN = $($cert.Subject.CN) SubjectAltName = $($cert.Extensions.SubjectAltName.UPN) } $data } } }
This will list the last 10 Schannel based logins, whereas the ones with a different user in SubjectCN and SubjectAltName will be of interest if monitoring for ADCS abuse (e.g. ESC1 attack):
Computer : dc01.testlab.local TimeCreated : 2025-02-24 07:08 Issuer : CA SubjectCN : Jdoe2 SubjectAltName : rplant@testlab.local
Note: More guidance for security monitoring of ADCS related events can be found in the chapter “Detective Guidance” of the whitepaper created by SpecterOps [1].
References:
- [1] SpecterOps’ research “Certified Pre-Owned”: https://posts.specterops.io/certified-pre-owned-d95910965cd2
- [2] How to enable Schannel event logging: https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/dn786445(v=ws.11)#how-to-enable-schannel-event-logging