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 /groupsDat 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
systeminfosysteminfo 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 -VerbosePowerUp 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.exeals “probeer eerstC:\Program.exe, danC:\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 userinfoWinPEAS 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" /domainMaar 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 -DescendingDat 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,DescriptionDit 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,DescriptionHet 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:
- Service accounts met SPNs – Kerberoast-doelwitten (hoofdstuk 7)
- Accounts met wachtwoorden in de description – instant toegang
- Accounts die nooit verlopen – vaak vergeten service accounts
- Accounts met hoge logonCount – actieve admin accounts
- Accounts met lage logonCount – mogelijk honeypots of vergeten accounts
- 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 MemberNameLet 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 NameHet 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-AllowedToDelegateToEven 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,OperatingSystemIB 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
- Verouderde besturingssystemen: Server 2008, Server 2012, of god verhoede Windows 7. Die hebben vaak ongepatchte kwetsbaarheden.
- Naamconventies:
SQL01,DVLP-WEB03,FIN-DB– namen verraden functies. - Machines met delegatie: zoals hierboven besproken.
- Machines die niet pingen maar wel in AD staan: mogelijk uitgeschakeld maar niet opgeruimd.
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:
- SourceName / TargetName: welke domeinen betrokken zijn.
- TrustDirection: Bidirectional, Inbound, of Outbound.
- TrustType: External (buiten het forest) of ParentChild (binnen het forest).
# 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 targetcomputerTot 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 -VerboseDit 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,DistinguishedNameOUs 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 Groupsconfigureren: die vertellen je exact wie local admin is op welke machines.
GPO misconfiguraties
De meest voorkomende GPO-misconfiguraties die we in de praktijk tegenkomen:
- cPassword in SYSVOL: Oude GPP-wachtwoorden (MS14-025). Microsoft heeft de functionaliteit verwijderd, maar oude XML-bestanden staan er soms nog.
- Schrijfrechten op GPO-bestanden: Als je de bestanden van een GPO kunt wijzigen in SYSVOL, kun je de GPO aanpassen.
- 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-NetFileServerInvoke-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 AdministratorsIB Tip: De meest voorkomende vondsten op shares: - Excel-bestanden met wachtwoorden (altijd genaamd
wachtwoorden.xlsxofpasswords_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-PSRemotingLocalAdminAccessFind-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 -StealthDe -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,ObjectAceTypeDCSync-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,OwnerDie 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 lockoutThresholdDie 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 --groupsIB Tip: LDAP filter
1.2.840.113556.1.4.803is 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 ookldapsearch -LLLvoor 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\tasksDe --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\tasksDCOnly 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:00Dit 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 AllDe 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:
--ExcludeDomainControllersvoorkomt alerts op DC logons. De--Stealthoptie vermindert detectie door minder queries te versturen. In een omgeving met actieve monitoring, begin metDCOnly, 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:
- Selecteer een actieve sessie in de Screen Terminal
- Kies een command file uit de IB-bibliotheek (bijv.
enum_domain_users) - Pas het commando aan voor de specifieke omgeving
- Voer uit en analyseer de output
- 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:
- “Hij moest een printer installeren.” Een printer. We geven iemand godmode over het hele netwerk zodat hij een printer kan installeren.
- “Dat was de enige manier om het werkend te krijgen.” Vertaling: ik had geen zin om uit te zoeken welke specifieke rechten nodig waren, dus ik heb de nucleaire optie gekozen.
- “Ze is teamlead, dus ze heeft het nodig.” Nee. Nee, dat heeft ze niet. Teamlead zijn vereist nul technische privileges.
- “Het is tijdelijk.” Niets is zo permanent als een tijdelijke oplossing.
- “Iedereen in IT heeft het.” Oh, nou dan. Als iedereen van het dak springt, spring jij ook? Kennelijk wel, als het om netwerksecurity gaat.
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