Windows en Domain Enumeratie

De stamboom van het netwerk

Er is iets merkwaardigs aan de manier waarop mensen omgaan met Active Directory. Stel je voor dat je een enorm landhuis binnenwandelt – een van die Engelse country estates met tweehonderd kamers, geheime doorgangen, en een butler die al sinds de Napoleontische oorlogen in dienst is. Je hebt een sleutel gekregen van de achterdeur (hoofdstuk 3 en 4, weet je nog?), maar je hebt werkelijk geen idee waar je bent. Je weet niet wie de eigenaar is. Je weet niet welke kamers er zijn, wie er toegang toe heeft, of waar de familiejuwelen liggen. Je weet eigenlijk helemaal niets.

Enumeratie is het systematisch bestuderen van die stamboom. Het is het openen van elke lade, het lezen van elk familieportret, het bestuderen van de hiërarchie van bedienden. Wie is de patriarch? Wie is de zwarte schaap? Wie heeft de sleutel van de kluis, en – cruciaal – wie heeft die sleutel afgegeven aan de tuinman omdat hij te lui was om zelf naar de kelder te lopen?

In Active Directory-termen: je wilt weten wie de Domain Admins zijn, welke machines er draaien, waar de vertrouwensrelaties lopen, en welke schaamteloze misconfiguraties er zijn gemaakt door iemand die op vrijdagmiddag om half vijf nog even snel iets “tijdelijk” wilde regelen. Spoiler: niets in IT is zo permanent als een tijdelijke oplossing.

Dit hoofdstuk is het langste van het boek, en met goede reden. Enumeratie is niet sexy. Het is niet het indrukwekkende moment waarop je een shell krijgt of een hash kraakt. Het is het equivalent van drie weken in een stoffig archief zitten met een vergrootglas en een notitieblok. Maar het is verreweg het belangrijkste wat je doet na initial access. Elke pentest die mislukt, mislukt omdat iemand deze stap heeft overgeslagen. Elke succesvolle pentest begint hier.

Laten we beginnen met de meest fundamentele vraag die je kunt stellen.


5.1 Lokale enumeratie: “Wie ben ik eigenlijk?”

De existentiële crisis van de aanvaller

Voordat je het domein gaat verkennen, moet je eerst begrijpen waar je staat. Dit is het digitale equivalent van wakker worden in een onbekend hotel en naar de badkamer strompelen om in de spiegel te kijken. Wie ben je? Wat kun je? En vooral: hoe diep zit je in de problemen?

De commando’s zijn zo simpel dat ze bijna beledigend aanvoelen:

whoami
whoami /priv
whoami /groups

Dat eerste commando vertelt je je gebruikersnaam. Het tweede laat je privileges zien – en dit is waar het interessant wordt. Als je SeImpersonatePrivilege ziet staan, mag je een klein vreugdedansje doen, want dat is je ticket naar SYSTEM via Potato- exploits. Als je SeDebugPrivilege hebt, kun je processen debuggen (lees: geheugen dumpen van alles wat beweegt). En het derde commando laat zien in welke groepen je zit.

net user %USERNAME%
net user %USERNAME% /domain
systeminfo

systeminfo is een goudmijn. Het vertelt je het besturingssysteem, de versie, de hotfixes die zijn geïnstalleerd (en dus impliciet welke er missen), het domein, de logon server, en meer. Het is alsof je de identiteitskaart, het medisch dossier, en het strafblad van je doelwit tegelijk leest.

systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"Hotfix(s)"

Maar laten we eerlijk zijn: handmatig zoeken naar privilege escalation vectoren is als het zoeken naar een naald in een hooiberg terwijl je niet eens weet hoe een naald eruitziet. Daarom bestaan er tools.

Geautomatiseerde lokale privesc enumeratie

Het IB command file enum_privesc_local bundelt de drie grote namen:

PowerUp – de klassieke PowerShell privilege escalation checker:

# Alle checks in één keer
powershell -c "Import-Module .\PowerUp.ps1; Invoke-AllChecks"

# Specifieke checks als je weet wat je zoekt:
Get-ServiceUnquoted -Verbose
Get-ModifiableServiceFile -Verbose
Get-ModifiableService -Verbose

PowerUp zoekt naar de usual suspects: unquoted service paths (services waarvan het pad spaties bevat maar niet tussen aanhalingstekens staat), schrijfbare service binaries, en services waarvan je de configuratie kunt aanpassen.

IB Tip: Unquoted service paths zijn het digitale equivalent van een zin zonder interpunctie. Windows interpreteert C:\Program Files\My App\service.exe als “probeer eerst C:\Program.exe, dan C:\Program Files\My.exe, en pas daarna het echte pad.” Als je ergens in dat pad kunt schrijven, win je.

WinPEAS – de Zwitserse zakmes van Windows enumeratie:

.\winPEASx64.exe

# Alleen specifieke categorieën:
.\winPEASx64.exe servicesinfo
.\winPEASx64.exe userinfo

WinPEAS is… grondig. Het produceert meer output dan een Russische roman en kleurt alles in rood, geel en groen alsof het een verkeersrapport is. Rood betekent “dit is bijna zeker exploiteerbaar,” geel is “dit is verdacht,” en groen is “dit is interessant maar waarschijnlijk niet direct bruikbaar.” In de praktijk scroll je door een zee van groen op zoek naar dat ene rode item dat je dag gaat maken.

PrivescCheck – het PowerShell alternatief:

powershell -c "Import-Module .\PrivescCheck.ps1; Invoke-PrivescCheck -Extended"

En dan de handmatige checks voor de puristen onder ons:

# AlwaysInstallElevated -- als beide registry keys op 1 staan,
# kun je elke MSI als SYSTEM installeren
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated

# Unquoted service paths via WMI
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "C:\Windows\\"

# Scheduled tasks -- wie draait wat, en als wie?
schtasks /query /fo LIST /v | findstr /i "task to run\|run as user"

IB Tip: Draai PowerUp EN WinPEAS voor maximale dekking. Ze vinden niet dezelfde dingen. PowerUp is gespecialiseerd in service-gerelateerde zwakheden, terwijl WinPEAS ook kijkt naar credentials in bestanden, register-entries, en allerlei andere hoeken waar je niet aan denkt.

En nu – even een cynisch intermezzo – laten we het hebben over het feit dat AlwaysInstallElevated uberhaupt bestaat als instelling. Microsoft heeft letterlijk een registry key gemaakt die zegt: “Ja, laat iedereen software installeren met de hoogste rechten. Wat kan er misgaan?” Het is alsof je een knop op je voordeur monteert met het label “Druk hier om het alarm uit te schakelen.” En er zijn systeembeheerders die deze instelling aanzetten. Met opzet. Omdat een gebruiker klaagde dat hij zijn favoriete screensaver niet kon installeren.


5.2 Domain gebruikers: het telefoonboek van de organisatie

Van lokaal naar domein

Nu je weet wie je lokaal bent, is het tijd om het domein in te stappen. En het eerste wat je doet is het telefoonboek opslaan – elke gebruiker in het domein, met zoveel mogelijk details.

De primitieve manier:

net user /domain
net group "Domain Admins" /domain

Maar net user /domain geeft je alleen een kale lijst met namen. Geen beschrijvingen, geen groepslidmaatschappen, geen interessante attributen. Het is alsof je het telefoonboek hebt, maar alleen de namen – geen adressen, geen telefoonnummers.

PowerView: het echte werk

# Alle users met nuttige velden
Get-DomainUser | select samaccountname,description,memberof

# Users gesorteerd op login count (wie is actief?)
Get-DomainUser -Properties samaccountname,logonCount | sort logonCount -Descending

Dat eerste commando is goud. samaccountname is de gebruikersnaam. description is – en ik verzin dit niet – het veld waar systeembeheerders regelmatig wachtwoorden in opslaan. Ja, echt. In plaintext. In een veld dat standaard leesbaar is voor elke geauthenticeerde gebruiker in het domein.

# Zoek naar wachtwoorden in description velden
Get-DomainUser -LDAPFilter "Description=*pass*" | select name,Description

Dit commando zoekt naar het woord “pass” in description velden. Je zou verbaasd zijn hoe vaak dit resultaten oplevert. “Temp password: Winter2024!” of “Service account - pwd: P@ssw0rd123” of mijn persoonlijke favoriet: “DO NOT CHANGE PASSWORD: Admin123”.

IB Tip: Het description-veld in AD is standaard leesbaar voor alle domain users. Dit is geen bug, het is by design. Microsoft vond dat beschrijvingen van accounts nuttige informatie is die iedereen zou moeten kunnen zien. En systeembeheerders dachten: “Handig! Dan zet ik het wachtwoord erbij, zodat ik het niet vergeet.” Het is alsof je je pincode op je bankpas schrijft en dan zegt: “Maar ik heb hem in mijn portemonnee, dus niemand kan erbij.”

Met de AD Module (het officiële PowerShell-module van Microsoft):

Get-ADUser -Filter * -Properties * | select name,logoncount,Description

Het verschil tussen PowerView en de AD Module is subtiel maar belangrijk. De AD Module is door Microsoft gemaakt en staat standaard op Domain Controllers. PowerView is door de offensieve security community gemaakt en moet je zelf uploaden. De AD Module is “legitiem” verkeer dat minder snel alarmbellen doet rinkelen bij een SOC. PowerView is krachtiger en flexibeler, maar het gebruik ervan is een rode vlag als je wordt gemonitored.

Wat je zoekt in gebruikersdata

Laat me het uitspellen, want dit is waar junior pentesters constant overheen kijken:

  1. Service accounts met SPNs – Kerberoast-doelwitten (hoofdstuk 7)
  2. Accounts met wachtwoorden in de description – instant toegang
  3. Accounts die nooit verlopen – vaak vergeten service accounts
  4. Accounts met hoge logonCount – actieve admin accounts
  5. Accounts met lage logonCount – mogelijk honeypots of vergeten accounts
  6. Disabled accounts – soms nog steeds bruikbaar via Kerberos

5.3 Domain groepen: de organisatiestructuur

Wie heeft de macht?

Active Directory-groepen zijn als de adellijke titels in een monarchie. Er is een hiërarchie, er zijn privileges, en er zijn altijd meer mensen met toegang dan er zouden moeten zijn. De koning mag dan zeggen dat alleen de innerlijke kring toegang heeft tot de schatkamer, maar in de praktijk heeft de helft van het hof een sleutel omdat iemand ooit zei: “Voeg Jan even toe, hij moet er bij kunnen voor dat ene project.”

# PowerView: alle groepen
Get-DomainGroup | select Name

# Zoek specifiek naar admin-groepen
Get-DomainGroup *admin* | select Name

# De heilige graal: wie zit er in Domain Admins?
Get-DomainGroupMember -Identity "Domain Admins" -Recurse | select MemberName

Let op die -Recurse flag. Dat is cruciaal. Active Directory ondersteunt geneste groepen. Groep A kan lid zijn van Groep B, die lid is van Domain Admins. Zonder -Recurse zie je alleen de directe leden, en mis je de impliciete Domain Admins die via nesting hun privileges hebben gekregen.

# AD Module equivalenten:
Get-ADGroup -Filter 'Name -like "*admin*"' | select Name
Get-ADGroupMember -Identity "Domain Admins" -Recursive | select Name

# Van welke groepen is een specifieke user lid?
Get-DomainGroup -UserName "targetuser"

IB Tip: Zoek niet alleen naar “Domain Admins”. Zoek ook naar “Enterprise Admins”, “Schema Admins”, “Account Operators”, “Backup Operators”, en “Server Operators”. Backup Operators kunnen bijvoorbeeld elk bestand op het systeem lezen, inclusief de SAM-database en NTDS.dit. Server Operators kunnen services aanmaken en starten. Dit zijn geen admin-accounts, maar ze zijn net zo gevaarlijk.

Hier is het moment voor een cynisch intermezzo. Weet je wat het mooiste is van groepslidmaatschappen in de meeste organisaties? Niemand ruimt ze op. Ooit. Een medewerker begint als stagiair, wordt analist, wordt teamleider, wordt manager, en aan het eind van zijn carrière zit hij in 47 groepen – waarvan 43 niets te maken hebben met zijn huidige functie. Het is digitale hoarding. Mensen die hun inbox op nul houden maar hun groepslidmaatschappen er uitzien alsof een peuter met de “Toevoegen”-knop heeft gespeeld.

En dan worden ze ontslagen of gaan ze met pensioen, en raad eens? Het account wordt “disabled” maar niet verwijderd, de groepslidmaatschappen blijven staan, en drie jaar later weet niemand meer waarom j.vanderberg_oud lid is van “Financieel Systeem Beheerders” en “VPN Full Access”. Maar niemand durft het te verwijderen, want “stel dat het ergens voor nodig is.”


5.4 Domain computers: de inventaris

Elke machine in kaart brengen

# PowerView: alle computers met OS info
Get-DomainComputer | select Name,OperatingSystem,DNSHostName

# Filter op specifiek OS
Get-DomainComputer -OperatingSystem "*Server 2022*" | select Name

# Alleen machines die online zijn (ICMP ping)
Get-DomainComputer -Ping | select Name

Het IB command file enum_domain_computers bevat ook twee bijzonder interessante queries:

# Unconstrained delegation -- machines die tickets mogen doorsturen
Get-DomainComputer -UnConstrained | select Name

# Constrained delegation -- machines met beperkte delegatie
Get-DomainComputer -TrustedToAuth | select Name,msDS-AllowedToDelegateTo

Even een historische noot, met de warmte die het onderwerp verdient. Kerberos-delegatie werd in 2000 geïntroduceerd met Windows 2000 Server. Het idee was elegant: als een webserver namens een gebruiker toegang moest hebben tot een database, kon de server het Kerberos-ticket van de gebruiker doorsturen. Unconstrained delegation betekende: “Deze machine mag het ticket doorsturen naar elke service.” Het was het equivalent van een volmacht zonder beperkingen.

Twintig jaar later realiseerde iedereen zich dat dit een verschrikkelijk idee was. Een machine met unconstrained delegation slaat de TGTs van elke gebruiker die erop inlogt op in het geheugen. Als je die machine compromitteert, heb je de tickets van iedereen die er recent is geweest – inclusief, als je geluk hebt, een Domain Admin.

# AD Module:
Get-ADComputer -Filter * -Properties OperatingSystem | select Name,OperatingSystem

IB Tip: Machines met unconstrained delegation zijn high-value targets. In een standaard AD-omgeving heeft elke Domain Controller unconstrained delegation (dat is by design), maar als je andere machines vindt met deze instelling, zijn dat potentiële springplanken naar Domain Admin.

Waar je op let


5.5 Domain trusts: de diplomatieke betrekkingen

Het web van vertrouwen

Domain trusts zijn de diplomatieke verdragen van Active Directory. Ze definiëren welke domeinen elkaar vertrouwen, in welke richting dat vertrouwen loopt, en welk type vertrouwen het is. En net als echte diplomatieke verdragen zijn ze vaak ouder dan de mensen die ze beheren, en begrijpt niemand meer precies waarom ze bestaan.

# PowerView:
Get-DomainTrust

# AD Module:
Get-ADTrust -Filter *

De output vertelt je:

# Forest informatie:
Get-Forest
Get-ForestDomain
Get-ForestGlobalCatalog
Get-ForestTrust

# AD Module varianten:
Get-ADForest | select Domains,GlobalCatalogs
(Get-ADForest).Domains
Get-ADTrust -Filter 'msDS-TrustForestTrustInfo -ne "$null"'

Laat me uitleggen waarom dit belangrijk is met een analogie die het verdient om verteld te worden.

Stel je voor dat je in een groot kasteel woont (het forest). Binnen dat kasteel zijn er meerdere vleugels (domeinen). De eigenaar van de noordvleugel vertrouwt de eigenaar van de zuidvleugel, en vice versa – dat is een bidirectionele trust binnen hetzelfde forest. Maar de eigenaar van het kasteel heeft ook een overeenkomst met de eigenaar van het kasteel verderop – dat is een forest trust.

Het cruciale punt is dit: een parent-child trust binnen een forest is altijd bidirectioneel en transitief. Als je domein kind.parent.local compromitteert, kun je via de trust relatie escaleren naar parent.local. En van daaruit naar andere child-domeinen. Het is als domino’s – duw er eentje om en de rest volgt.

IB Tip: Forest trusts zijn de echte grens in Active Directory, niet domeinen. Binnen een forest deelt elk domein hetzelfde Schema en dezelfde Enterprise Admins groep. Een domain compromise binnen een forest is in principe een forest compromise. Externe en forest trusts zijn lastiger maar niet onmogelijk te misbruiken – zie SID History attacks en trust ticket forging in hoofdstuk 8.


5.6 GPO enumeratie: de wet van het land

Group Policy Objects

Als Active Directory het koninkrijk is, dan zijn Group Policy Objects de wetten. Ze dicteren wat gebruikers en computers mogen en moeten doen: welke software wordt geïnstalleerd, welke instellingen worden afgedwongen, welke scripts worden uitgevoerd bij het inloggen. En net als echte wetten zijn ze vaak tegenstrijdig, verouderd, en geschreven door iemand die de gevolgen niet helemaal had doordacht.

# PowerView: alle GPOs
Get-DomainGPO | select DisplayName,Name

# GPOs die van toepassing zijn op een specifieke computer
Get-DomainGPO -ComputerIdentity targetcomputer

Tot zover niets schokkends. Maar het wordt interessant bij deze commando’s:

# Restricted Groups -- welke groepen worden via GPO toegevoegd aan lokale groepen?
Get-DomainGPOLocalGroup

# Wie wordt via GPO local admin op een specifieke machine?
Get-DomainGPOComputerLocalGroupMapping -ComputerIdentity targetcomputer

# Op welke machines is een specifieke user local admin via GPO?
Get-DomainGPOUserLocalGroupMapping -Identity targetuser -Verbose

Dit is enorm waardevol. GPOs worden gebruikt om lokale beheerdersgroepen te configureren. Als je weet dat GPO_ITBeheer de groep IT-Beheerders toevoegt aan de lokale Administrators-groep op alle servers, en jij kunt lid worden van IT-Beheerders (of al lid bent), dan ben je lokale admin op elke server waar die GPO wordt toegepast.

# Organizational Units -- de structuur waarop GPOs worden toegepast
Get-DomainOU | select Name,DistinguishedName

OUs zijn de mappen in Active Directory. GPOs worden gekoppeld aan OUs, en alle objecten in die OU (en sub-OUs) krijgen die GPO. Als je weet welke OU een target computer in zit, weet je welke GPOs erop worden toegepast. En als je weet welke GPOs er zijn met interessante instellingen, weet je welke OUs je moet targeten.

IB Tip: Zoek naar GPOs met namen als “Wachtwoordbeleid”, “Software Installatie”, of “Logon Scripts”. Logon scripts zijn bijzonder interessant – als je een logon script kunt wijzigen dat via GPO wordt uitgerold, heb je code execution op elke machine waar dat script draait. Zoek ook naar GPOs die Restricted Groups configureren: die vertellen je exact wie local admin is op welke machines.

GPO misconfiguraties

De meest voorkomende GPO-misconfiguraties die we in de praktijk tegenkomen:

  1. cPassword in SYSVOL: Oude GPP-wachtwoorden (MS14-025). Microsoft heeft de functionaliteit verwijderd, maar oude XML-bestanden staan er soms nog.
  2. Schrijfrechten op GPO-bestanden: Als je de bestanden van een GPO kunt wijzigen in SYSVOL, kun je de GPO aanpassen.
  3. Overmatig brede GPO-koppelingen: Een GPO die Domain Admins local admin maakt op werkstations, maar per ongeluk is gekoppeld aan de hele domain root.

5.7 Share en bestandsenumeratie: de archiefkamer

SMB shares: het open buffet

Als er een plek is waar organisaties hun vuile was buiten hangen, dan is het op SMB-shares. Het is werkelijk verbijsterend wat mensen op gedeelde netwerkschijven zetten in de veronderstelling dat “alleen collega’s erbij kunnen.” Spoiler: elke geauthenticeerde domeingebruiker kan standaard de meeste shares zien.

# Alle shares in het domein vinden
Invoke-ShareFinder -Verbose

# Gevoelige bestanden zoeken op die shares
Invoke-FileFinder -Verbose

# File servers identificeren
Get-NetFileServer

Invoke-ShareFinder scant elke computer in het domein op open SMB-shares. Invoke-FileFinder gaat een stap verder en zoekt naar bestanden met interessante namen: *password*, *credential*, *config*, *.kdbx (KeePass databases), *.vmdk (virtuele disks), enzovoort.

# Lokale groepen op een remote machine bekijken
Get-NetLocalGroup -ComputerName target
Get-NetLocalGroupMember -ComputerName target -GroupName Administrators

IB Tip: De meest voorkomende vondsten op shares: - Excel-bestanden met wachtwoorden (altijd genaamd wachtwoorden.xlsx of passwords_DO_NOT_DELETE.xlsx) - Configuratiebestanden met database connection strings - PowerShell-scripts met hardcoded credentials - Backup-bestanden van databases - KeePass-databases (en soms de master key ernaast) - SSH private keys - VPN-configuratiebestanden met ingebedde certificaten

Ik wil hier even stilstaan bij de absurditeit van wat we in de praktijk tegenkomen. Er bestaan organisaties – grote, serieuze organisaties met compliance-afdelingen en een CISO met een kantoor op de directie-etage – waar een share genaamd \\fileserver\IT leesbaar is voor Domain Users en een bestand bevat genaamd admin_passwords.txt. In plaintext. Onversleuteld. Al vier jaar niet gewijzigd.

En als je het rapporteert, krijg je te horen: “Ja maar dat is alleen intern toegankelijk.” Alsof het interne netwerk een onneembare vesting is. Alsof we niet net drie hoofdstukken hebben besteed aan hoe je op dat interne netwerk komt.


5.8 User hunting: de jacht

Waar zijn de kroonjuwelen?

User hunting is precies wat het klinkt: het opsporen van specifieke gebruikers op het netwerk. Meestal zoek je Domain Admins, want als je een machine vindt waar een Domain Admin is ingelogd en je hebt daar lokale beheerdersrechten, kun je hun credentials stelen en het spel is voorbij.

Het IB command file enum_user_hunting is een van de meest bruikbare in de hele collectie:

# Stap 1: Vind machines waar je local admin bent
Find-LocalAdminAccess -Verbose

# Alternatief als SMB/RPC geblokkeerd is:
Find-WMILocalAdminAccess
Find-PSRemotingLocalAdminAccess

Find-LocalAdminAccess probeert een SMB-verbinding te maken naar elke computer in het domein en checkt of je lokale beheerdersrechten hebt. Het is luidruchtig – het genereert veel verkeer en veel logs – maar het is effectief.

# Stap 2: Vind waar Domain Admin sessies draaien
Find-DomainUserLocation -Verbose

# Zoek naar andere groepen:
Find-DomainUserLocation -UserGroupIdentity "RDPUsers"

# Combineer: vind DA sessie EN check of je daar admin bent
Find-DomainUserLocation -CheckAccess

# Stealth modus: scan alleen file servers en DFS servers
Find-DomainUserLocation -Stealth

De -CheckAccess flag is briljant. Het combineert twee stappen in een: “Waar is een Domain Admin ingelogd?” en “Heb ik daar admin-rechten?” Als beide waar zijn, heb je je attack path gevonden.

De -Stealth optie is voor als je probeert niet gedetecteerd te worden. In plaats van elke machine in het domein te scannen, kijkt het alleen naar file servers, distributed file system servers, en domain controllers – machines waar Domain Admins waarschijnlijk sessies hebben, maar met veel minder netwerk-ruis.

IB Tip: De volgorde is altijd: (1) vind waar je local admin bent, (2) vind waar DAs zijn ingelogd, (3) vind het overlap. Als er geen overlap is, moet je eerst lateraal bewegen naar machines waar je wel admin bent, en hopen dat je van daaruit dichter bij een DA-sessie komt. Dit is het “derivative local admin” pad dat BloodHound zo goed kan visualiseren – daarover later meer.


5.9 ACL enumeratie: de kleine lettertjes

De onzichtbare rechtenstructuur

Active Directory Access Control Lists zijn de meest onderschatte aanvalsvector in de hele Windows-wereld. De meeste systeembeheerders weten dat ACLs bestaan. Veel minder begrijpen hoe ze werken. En bijna niemand controleert ze regelmatig.

Een ACL op een AD-object (een gebruiker, groep, computer, OU, of GPO) definieert wie wat mag doen met dat object. De rechten die je zoekt als aanvaller:

Recht Betekenis Aanvalspotentieel
GenericAll Volledige controle Wachtwoord resetten, groepsleden wijzigen, alles
GenericWrite Schrijfrechten op attributen SPN toevoegen (Targeted Kerberoast), logon script wijzigen
WriteDacl ACL aanpassen Jezelf GenericAll geven
WriteOwner Eigenaar wijzigen Eigenaar worden, dan WriteDacl, dan GenericAll
ForceChangePassword Wachtwoord resetten zonder oud wachtwoord Account overnemen
WriteProperty Specifiek attribuut schrijven Afhankelijk van welk attribuut

Het IB command file ad_enum_acl pakt dit systematisch aan:

# Stap 1: Alle interessante ACLs voor je huidige user of groep
powershell -c "Import-Module .\PowerView.ps1; Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match 'currentuser|currentgroup'} | Select-Object ObjectDN,ActiveDirectoryRights,IdentityReferenceName | Format-Table -AutoSize"

Vervang currentuser en currentgroup met je eigen gebruikersnaam en groepen. Dit commando zoekt naar alle objecten in het domein waar jij (of je groepen) interessante rechten op hebt.

# Stap 2: ACLs op een specifiek object bekijken
Get-DomainObjectAcl -Identity 'Domain Admins' -ResolveGUIDs | ?{$_.ActiveDirectoryRights -match 'GenericAll|WriteDacl|WriteOwner|GenericWrite|ForceChangePassword|WriteProperty'}

Dit vertelt je wie er speciale rechten heeft op de Domain Admins groep. Als jouw account (direct of via nesting) WriteDacl heeft op Domain Admins, kun je jezelf toevoegen. Game over.

# Stap 3: Wie heeft DCSync rechten?
Get-DomainObjectAcl -SearchBase 'DC=domain,DC=local' -ResolveGUIDs | ?{$_.ObjectAceType -match 'Replicating'} | Select-Object IdentityReferenceName,ObjectAceType

DCSync-rechten (de replicatie-rechten op het domeinobject) zijn het equivalent van de sleutel tot de kluis. Met DCSync kun je elke hash uit Active Directory halen zonder ooit een Domain Controller aan te raken. Het is het verschil tussen een bank beroven en de bank vragen om je al het geld toe te sturen. Standaard hebben alleen Domain Controllers en Domain Admins deze rechten, maar misconfiguraties zijn verrassend vaak.

# Stap 4: Accounts met GenericWrite (Kerberoast target)
Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.ActiveDirectoryRights -match 'GenericWrite'} | Select-Object ObjectDN,IdentityReferenceName

# Stap 5: Owner van een object checken
Get-DomainObjectAcl -Identity targetuser -ResolveGUIDs | Select-Object SecurityIdentifier,Owner

Die laatste is subtiel maar belangrijk. De eigenaar van een AD-object kan altijd de ACL van dat object aanpassen (WriteDacl). Dus als je eigenaar bent van een account, kun je jezelf GenericAll geven op dat account, en dan het wachtwoord resetten.

IB Tip: Gebruik BloodHound voor visuele ACL attack paths. Handmatig door ACL-output scrollen is als het lezen van een juridisch contract – technisch mogelijk, maar je mist gegarandeerd iets. BloodHound visualiseert de ketens: User A heeft WriteDacl op Groep B, die GenericAll heeft op User C, die lid is van Domain Admins. Dat is drie stappen, en je ziet het in een oogopslag.


5.10 LDAP raw queries: zonder PowerView

Wanneer je geen tools hebt

Er zijn situaties waarin je PowerView niet kunt of wilt laden. Misschien is er een EDR die PowerShell-modules monitort. Misschien heb je geen schrijfrechten op disk. Misschien wil je gewoon zo min mogelijk voetafdrukken achterlaten. In die gevallen val je terug op wat er al op het systeem staat.

Het IB command file ad_enum_ldap_raw is een meesterwerk van minimalisme. Het gebruikt drie methoden: de .NET [adsisearcher] class (die op elk domein-joined Windows-systeem werkt zonder extra tools), de DirectoryEntry en DirectoryServices classes, en voor Linux: ldapsearch.

PowerShell [adsisearcher]: altijd beschikbaar

# Alle gebruikers
([adsisearcher]'(objectCategory=user)').FindAll() | % { $_.Properties.samaccountname }

# Alle computers
([adsisearcher]'(objectCategory=computer)').FindAll() | % { $_.Properties.cn }

# Alle groepen
([adsisearcher]'(objectCategory=group)').FindAll() | % { $_.Properties.cn }

# Domain Admins leden
([adsisearcher]'(&(objectCategory=user)(memberOf=CN=Domain Admins,CN=Users,DC=domain,DC=local))').FindAll() | % { $_.Properties.samaccountname }

De schoonheid van [adsisearcher] is dat het puur LDAP is. Er worden geen extra modules geladen, er wordt niets naar disk geschreven, en het verkeer is identiek aan wat elke Windows-machine doet als onderdeel van normaal domeinverkeer. Het is onzichtbaar. Nou ja, bijna onzichtbaar – als iemand LDAP-queries monitort op de Domain Controller, kun je worden opgemerkt, maar dat doet bijna niemand.

De echt interessante queries:

# Gebruikers met een SPN (Kerberoastable)
([adsisearcher]'(&(objectCategory=user)(servicePrincipalName=*))').FindAll() | % { $_.Properties.samaccountname; $_.Properties.serviceprincipalname }

# Gebruikers met DONT_REQ_PREAUTH (AS-REP Roastable)
([adsisearcher]'(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))').FindAll() | % { $_.Properties.samaccountname }

# Uitgeschakelde accounts
([adsisearcher]'(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=2))').FindAll() | % { $_.Properties.samaccountname }

# Wachtwoord verloopt nooit
([adsisearcher]'(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))').FindAll() | % { $_.Properties.samaccountname }

Die 1.2.840.113556.1.4.803 ziet er intimiderend uit, maar het is simpelweg de LDAP OID voor een bitwise AND-operatie. userAccountControl is een bitfield – elke bit vertegenwoordigt een instelling. Bit 2 (waarde 2) is “account is disabled.” Bit 22 (waarde 4194304) is “do not require Kerberos pre-authentication.” De OID zegt: “geef me alle accounts waar deze specifieke bit aan staat.”

IB Tip: [adsisearcher] werkt op elk domein-joined Windows zonder extra tools. Het is je fallback als alles faalt. Onthoud deze syntax – het kan het verschil maken tussen succes en falen als je in een beperkte omgeving zit.

.NET DirectoryServices: meer detail

# Domain informatie
$d = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$d.Name
$d.DomainControllers

# Forest informatie
[System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() | % { $_.Domains; $_.GlobalCatalogs }

# Trust relaties
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()

Linux: ldapsearch

Als je vanuit een Linux-machine werkt (bijvoorbeeld je aanvalsmachine), kun je ldapsearch gebruiken om LDAP-queries te doen:

# Anonieme LDAP bind (werkt zelden, maar probeer het altijd)
ldapsearch -x -H ldap://DC_IP -b "DC=domain,DC=local" "(objectClass=*)"

# Geauthenticeerde LDAP query
ldapsearch -x -H ldap://DC_IP -D "user@domain.local" -w 'PASSWORD' \
  -b "DC=domain,DC=local" "(objectCategory=user)" sAMAccountName

# Domain Admins opvragen
ldapsearch -x -H ldap://DC_IP -D "user@domain.local" -w 'PASSWORD' \
  -b "DC=domain,DC=local" \
  "(&(objectCategory=user)(memberOf=CN=Domain Admins,CN=Users,DC=domain,DC=local))" \
  sAMAccountName

# Wachtwoordbeleid opvragen
ldapsearch -x -H ldap://DC_IP -D "user@domain.local" -w 'PASSWORD' \
  -b "DC=domain,DC=local" "(objectClass=domainDNS)" \
  ms-DS-MachineAccountQuota minPwdLength lockoutThreshold

Die laatste query is bijzonder nuttig. ms-DS-MachineAccountQuota vertelt je hoeveel computer-accounts een gewone domeingebruiker mag aanmaken (standaard: 10). minPwdLength is de minimale wachtwoordlengte. lockoutThreshold is het aantal mislukte pogingen voordat een account wordt vergrendeld – cruciaal om te weten voordat je gaat sprayen (hoofdstuk 6).

windapsearch: de Python wrapper

# Domain Admins
windapsearch -d domain.local --dc-ip DC_IP -u user@domain.local -p PASSWORD --da

# Alle computers
windapsearch -d domain.local --dc-ip DC_IP -u user@domain.local -p PASSWORD --computers

# Alle groepen
windapsearch -d domain.local --dc-ip DC_IP -u user@domain.local -p PASSWORD --groups

IB Tip: LDAP filter 1.2.840.113556.1.4.803 is de bitwise AND operator. Als je het vergeet, zoek dan naar “LDAP matching rule OID” – het is een van die dingen die je elke keer opnieuw moet opzoeken, en dat is prima. Gebruik ook ldapsearch -LLL voor schonere output zonder commentaarregels en versie-informatie.


5.11 BloodHound: het vogelperspectief

De kaart van het koninkrijk

Als alle voorgaande secties het handmatig verkennen van individuele kamers waren, dan is BloodHound de drone die over het hele landgoed vliegt en een gedetailleerde luchtfoto maakt. Het is een tool die alle relaties in Active Directory verzamelt – groepslidmaatschappen, lokale admin-rechten, sessies, ACLs, trusts – en ze visualiseert als een graaf. Knooppunten zijn gebruikers, groepen, en computers. Verbindingen zijn relaties: “is lid van”, “heeft admin-rechten op”, “heeft een sessie op”, “kan het wachtwoord resetten van.”

En dan vraag je BloodHound: “Wat is het kortste pad van mijn huidige gebruiker naar Domain Admin?” En het antwoord is vaak korter dan je zou denken.

Data verzamelen met SharpHound

BloodHound heeft data nodig, en die data wordt verzameld door SharpHound (of de Python-versie bloodhound-python voor Linux).

# Methode 1: Alles verzamelen (meest complete, maar ook meest luidruchtige)
.\SharpHound.exe --CollectionMethods All --Domain domain.local --ExcludeDomainControllers --OutputDirectory C:\Windows\tasks

De --CollectionMethods All flag verzamelt alles: groepslidmaatschappen, lokale groepen op elke machine, actieve sessies, ACLs, trusts, SPNs, en meer. De --ExcludeDomainControllers flag is een stealth-maatregel: het voorkomt dat SharpHound inlogt op Domain Controllers, wat vaak wordt gemonitord.

De output gaat naar C:\Windows\tasks – een map die op elke Windows-machine bestaat en waar schrijven meestal is toegestaan, zelfs als je geen admin bent.

# Methode 2: Alleen DC-data (minder ruis, nog steeds nuttig)
.\SharpHound.exe --CollectionMethods DCOnly --Domain domain.local --OutputDirectory C:\Windows\tasks

DCOnly haalt alleen data op van de Domain Controller via LDAP. Het mist lokale admin-rechten en sessie-informatie, maar het is veel stiller en geeft je alsnog groepslidmaatschappen, ACLs, en trusts.

# Methode 3: Sessie-verzameling met looping
.\SharpHound.exe --CollectionMethods Session --Loop --Loopduration 02:00:00

Dit is slim. Sessies zijn vluchtig – een Domain Admin logt in, doet zijn werk, en logt weer uit. Als je op het verkeerde moment scant, mis je hem. Met --Loop draait SharpHound de sessie-collectie herhaaldelijk gedurende twee uur, waardoor je een veel completer beeld krijgt van wie waar inlogt.

# Methode 4: PowerShell-versie (als .exe geblokkeerd wordt)
powershell -c "Import-Module .\SharpHound.ps1; Invoke-BloodHound -CollectionMethod All -Domain domain.local -OutputDirectory C:\Windows\tasks"

En voor de Linux-aanvallers:

# Python-versie (vanuit je aanvalsmachine, geen tools op target nodig)
bloodhound-python -u user -p 'Password123!' -d domain.local -ns DC_IP -c All

De Python-versie is elegant: je hoeft niets te uploaden naar het doelnetwerk. Het draait op je eigen machine en doet alles via LDAP en RPC. Minder compleet dan SharpHound op een domein-joined machine, maar nul voetafdruk op het target.

BloodHound GUI: de grafieken interpreteren

Na het verzamelen upload je het .zip-bestand naar de BloodHound GUI (de Neo4j- gebaseerde interface). En dan begint het echte werk.

De voorgebouwde queries die je als eerste draait:

Query Wat het zoekt
Find Shortest Paths to Domain Admins Het kortste pad van elke gebruiker naar DA
Find All Kerberoastable Users Accounts met SPNs die je offline kunt kraken
Find AS-REP Roastable Users Accounts zonder pre-auth die je kunt aanvallen
Find Principals with DCSync Rights Wie kan alle hashes uit AD halen?
Shortest Path from Owned Principals Paden vanaf accounts die je al hebt gecompromitteerd

Die laatste query is je brood en boter. Elke keer dat je een account compromitteert, markeer je het als “owned” in BloodHound en draai je deze query opnieuw. Het is een iteratief proces: compromitteer, markeer, herbereken, kies het volgende doelwit.

IB Tip: --ExcludeDomainControllers voorkomt alerts op DC logons. De --Stealth optie vermindert detectie door minder queries te versturen. In een omgeving met actieve monitoring, begin met DCOnly, analyseer de resultaten, en doe pas een volledige scan als je weet dat het veilig is.

De realiteit van BloodHound-output

En hier een moment van eerlijkheid. In mijn ervaring – en de ervaring van elke pentester die ik ken – vindt BloodHound in 80% van de domeinen een pad naar Domain Admin binnen drie stappen. Drie. Stappen. Van een willekeurige domeingebruiker naar volledige controle over het hele netwerk.

Dat is niet omdat de tool zo goed is (hoewel hij dat is). Het is omdat de configuratie van de meeste Active Directory-omgevingen zo slecht is. Geneste groepen die niemand begrijpt. Lokale admin-rechten die ooit tijdelijk werden gegeven. ACLs die verkeerd staan omdat iemand “Grant Everyone Full Control” had aangevinkt om een probleem op te lossen. Het is een kaartenhuis.


5.12 IB Screen Terminal: interactieve enumeratie

Enumeratie via het dashboard

Het Incompetent Bastard dashboard biedt een Screen Terminal die je kunt gebruiken voor interactieve sessies op gecompromitteerde machines. Dit is bijzonder nuttig voor enumeratie, omdat veel van de commando’s in dit hoofdstuk iteratief zijn – je draait een commando, analyseert de output, en beslist op basis daarvan welk commando je daarna draait.

De Screen Terminal in IB geeft je een webgebaseerde interface naar je reverse shells en remote sessies. In combinatie met de command files die we in dit hoofdstuk hebben besproken, kun je enumeratie-commando’s direct vanuit het dashboard uitvoeren en de output real-time bekijken.

Het typische werkproces:

  1. Selecteer een actieve sessie in de Screen Terminal
  2. Kies een command file uit de IB-bibliotheek (bijv. enum_domain_users)
  3. Pas het commando aan voor de specifieke omgeving
  4. Voer uit en analyseer de output
  5. Gebruik de output om het volgende commando te kiezen

Dit is waar het dashboard zijn waarde bewijst ten opzichte van losse tools. Alles staat op een plek: je sessies, je command files, je output. Geen geswitsch tussen terminals, geen verloren output, geen “wacht, in welk venster had ik die query gedraaid?”

IB Tip: Gebruik de Output-pagina van IB om enumeratie-resultaten op te slaan. Grote outputs (zoals volledige user- of computerlijsten) kun je later doorzoeken zonder het commando opnieuw te hoeven draaien. Dit bespaart tijd en vermindert je voetafdruk op het doelnetwerk.


5.13 De ongemakkelijke waarheid: over Domain Admins en verantwoordelijkheid

Laten we het even hebben over de olifant in de kamer. Of beter gezegd: de twintig olifanten in de kamer, want dat is ongeveer het aantal Domain Admin-accounts in een gemiddeld middelgroot bedrijf.

Twintig Domain Admins. In een organisatie van driehonderd man. Dat is bijna zeven procent van de werknemers met de sleutels van het koninkrijk. Stel je voor dat zeven procent van de medewerkers van een bank de code van de kluis had. Stel je voor dat zeven procent van de medewerkers van een kerncentrale de lanceercode kende. Maar in IT is het normaal.

En het mooiste is: als je vraagt waarom iemand Domain Admin is, krijg je antwoorden als:

Het principe van least privilege – geef mensen alleen de rechten die ze nodig hebben voor hun werk – is niet nieuw. Het is niet controversieel. Het staat in elke security standaard, elk framework, elk handboek. Het wordt onderwezen in elke security-cursus. En het wordt genegeerd in elke organisatie.

Waarom? Omdat het makkelijker is om iemand Domain Admin te maken dan om uit te zoeken welke specifieke rechten hij nodig heeft. Omdat het makkelijker is om “ja” te zeggen tegen een collega die klaagt dat iets niet werkt dan om het juiste rechtenmodel te configureren. Omdat gemak altijd wint van security, tenzij er actief wordt gehandhaafd.

En zo eindig je met een netwerk waar de helft van de IT-afdeling Domain Admin is, waar service accounts met wachtwoorden die nooit verlopen in de Domain Admins-groep zitten, en waar de description van die accounts letterlijk het wachtwoord bevat. En dan huurt men een pentester in en zegt: “Test ons netwerk maar, we zijn benieuwd hoe veilig we zijn.”

Ik zal je vertellen hoe veilig jullie zijn. Ik had Domain Admin binnen vier uur, en twee daarvan heb ik besteed aan koffie drinken en mijn rapport alvast opmaken.


5.14 Referentietabel: alle enumeratie-commando’s

Lokale enumeratie

Doel Commando Tool
Huidige user whoami Ingebouwd
Privileges whoami /priv Ingebouwd
Groepen whoami /groups Ingebouwd
User details net user %USERNAME% Ingebouwd
Systeem info systeminfo Ingebouwd
Alle privesc checks Invoke-AllChecks PowerUp
Unquoted paths Get-ServiceUnquoted PowerUp
Schrijfbare binaries Get-ModifiableServiceFile PowerUp
Wijzigbare services Get-ModifiableService PowerUp
Volledige scan .\winPEASx64.exe WinPEAS
Privesc check Invoke-PrivescCheck -Extended PrivescCheck
AlwaysInstallElevated reg query HKLM\...\Installer /v AlwaysInstallElevated Ingebouwd

Domain gebruikers

Doel Commando Tool
Alle users Get-DomainUser \| select samaccountname,description,memberof PowerView
Actieve users Get-DomainUser -Properties samaccountname,logonCount \| sort logonCount -Descending PowerView
Wachtwoorden in description Get-DomainUser -LDAPFilter "Description=*pass*" PowerView
Alle users (AD Module) Get-ADUser -Filter * -Properties * AD Module
Alle users (LDAP raw) ([adsisearcher]'(objectCategory=user)').FindAll() .NET

Domain groepen

Doel Commando Tool
Alle groepen Get-DomainGroup \| select Name PowerView
Admin groepen Get-DomainGroup *admin* PowerView
DA leden (recursief) Get-DomainGroupMember -Identity "Domain Admins" -Recurse PowerView
DA leden (AD Module) Get-ADGroupMember -Identity "Domain Admins" -Recursive AD Module
User groepen Get-DomainGroup -UserName "targetuser" PowerView

Domain computers

Doel Commando Tool
Alle computers Get-DomainComputer \| select Name,OperatingSystem,DNSHostName PowerView
Specifiek OS Get-DomainComputer -OperatingSystem "*Server 2022*" PowerView
Online machines Get-DomainComputer -Ping PowerView
Unconstrained delegation Get-DomainComputer -UnConstrained PowerView
Constrained delegation Get-DomainComputer -TrustedToAuth PowerView

Domain trusts

Doel Commando Tool
Alle trusts Get-DomainTrust PowerView
Alle trusts (AD Module) Get-ADTrust -Filter * AD Module
Forest info Get-Forest PowerView
Forest domeinen Get-ForestDomain PowerView
Forest trusts Get-ForestTrust PowerView
Forest (AD Module) Get-ADForest \| select Domains,GlobalCatalogs AD Module

GPO enumeratie

Doel Commando Tool
Alle GPOs Get-DomainGPO \| select DisplayName,Name PowerView
GPOs op computer Get-DomainGPO -ComputerIdentity target PowerView
Restricted groups Get-DomainGPOLocalGroup PowerView
Local admin via GPO Get-DomainGPOComputerLocalGroupMapping -ComputerIdentity target PowerView
User admin locaties Get-DomainGPOUserLocalGroupMapping -Identity user PowerView
OUs Get-DomainOU \| select Name,DistinguishedName PowerView

Share enumeratie

Doel Commando Tool
Alle shares Invoke-ShareFinder -Verbose PowerView
Gevoelige bestanden Invoke-FileFinder -Verbose PowerView
File servers Get-NetFileServer PowerView
Lokale groepen Get-NetLocalGroup -ComputerName target PowerView
Lokale admins Get-NetLocalGroupMember -ComputerName target -GroupName Administrators PowerView

User hunting

Doel Commando Tool
Waar ben ik admin? Find-LocalAdminAccess -Verbose PowerView
Via WMI Find-WMILocalAdminAccess PowerView
Via PSRemoting Find-PSRemotingLocalAdminAccess PowerView
DA sessies Find-DomainUserLocation -Verbose PowerView
DA + admin check Find-DomainUserLocation -CheckAccess PowerView
Stealth Find-DomainUserLocation -Stealth PowerView

ACL enumeratie

Doel Commando Tool
Interessante ACLs Find-InterestingDomainAcl -ResolveGUIDs PowerView
ACLs op object Get-DomainObjectAcl -Identity 'Domain Admins' -ResolveGUIDs PowerView
DCSync rechten Get-DomainObjectAcl -SearchBase 'DC=domain,DC=local' -ResolveGUIDs \| ?{$_.ObjectAceType -match 'Replicating'} PowerView
GenericWrite targets Find-InterestingDomainAcl -ResolveGUIDs \| ?{$_.ActiveDirectoryRights -match 'GenericWrite'} PowerView
Object owner Get-DomainObjectAcl -Identity targetuser \| Select Owner PowerView

LDAP raw queries

Doel Commando Tool
Alle users ([adsisearcher]'(objectCategory=user)').FindAll() .NET
Kerberoastable ([adsisearcher]'(&(objectCategory=user)(servicePrincipalName=*))').FindAll() .NET
AS-REP Roastable ([adsisearcher]'...userAccountControl:1.2.840.113556.1.4.803:=4194304...') .NET
Disabled accounts ([adsisearcher]'...userAccountControl:1.2.840.113556.1.4.803:=2...') .NET
Password never expires ([adsisearcher]'...userAccountControl:1.2.840.113556.1.4.803:=65536...') .NET
Linux: alle users ldapsearch -x -H ldap://DC -D user -w pass -b "DC=d,DC=l" "(objectCategory=user)" ldapsearch
Python: DA windapsearch -d domain.local --dc-ip DC -u user -p pass --da windapsearch

BloodHound

Doel Commando Tool
Volledige collectie .\SharpHound.exe --CollectionMethods All --Domain domain.local --ExcludeDomainControllers SharpHound
DC only .\SharpHound.exe --CollectionMethods DCOnly SharpHound
Sessie loop .\SharpHound.exe --CollectionMethods Session --Loop --Loopduration 02:00:00 SharpHound
PowerShell versie Invoke-BloodHound -CollectionMethod All SharpHound.ps1
Python versie bloodhound-python -u user -p pass -d domain.local -ns DC_IP -c All bloodhound-python

5.15 Samenvatting: de enumeratie-checklist

Voordat je naar het volgende hoofdstuk gaat, controleer of je het volgende hebt:

Als je dit allemaal hebt, heb je een vollediger beeld van het netwerk dan de meeste systeembeheerders die er dagelijks in werken. En dat is niet als compliment bedoeld naar jou – het is een aanklacht tegen de staat van IT-beheer in de meeste organisaties.

In het volgende hoofdstuk gaan we deze informatie gebruiken. We gaan wachtwoorden kraken, sprayen, en roasten. We gaan die misconfiguraties die we zojuist hebben gevonden exploiteren. We gaan van “ik weet wie de Domain Admins zijn” naar “ik ben een Domain Admin.”

Maar dat is voor later. Nu eerst: sla je enumeratie-data op, drink een kop koffie, en bestudeer je BloodHound-grafieken. Het antwoord zit erin. Het zit er altijd in.


“Reconnaissance is the most important phase of any engagement. Unfortunately, it’s also the most boring, which is why most people skip it and then wonder why they failed.”

— Een pentester die het weet