AD Offensive Testing
Notes below taken and edited from https://casvancooten.com/posts/2020/11/windows-active-directory-exploitation-cheat-sheet-and-command-reference/
General
‘Plain’ AMSI bypass example:
PowerShell
Obfuscation example for copy-paste purposes:
Another bypass, which is not detected by PowerShell autologging:
More bypasses here. For obfuscation, check Invoke-Obfuscation, or get a custom-generated obfuscated version at amsi.fail.
PowerShell one-liners - Load PowerShell script reflectively
Proxy-aware:
Non-proxy aware:
Load C# assembly reflectively
Ensure that the referenced class and main methods are public
before running this. Note that a process-wide AMSI bypass may be required for this to work if the content is detected, refer here for details.
PowerShell - Download file
Encoded commands
Base64-encode a PowerShell command in the right format:
Bash
Encode existing script, copy to clipboard:
PowerShell
Run it, bypassing execution policy.
PowerShell
If you have Nishang handy, you can use Invoke-Encode.ps1.
Enumeration
AD Enumeration With PowerView
PowerView is available here.
AppLocker
Identify the local AppLocker policy. Look for exempted binaries or paths to bypass.
PowerShell
Get a remote AppLocker policy, based on the Distinguished Name of the respective Group Policy (you could identify this e.g. in BloodHound).
Some high-level bypass techniques:
Use LOLBAS if only (Microsoft-)signed binaries are allowed.
If binaries from
C:\Windows
are allowed (default behavior), try dropping your binaries toC:\Windows\Temp
orC:\Windows\Tasks
. If there are no writable subdirectories but writable files exist in this directory tree, write your file to an alternate data stream (e.g. a JScript script) and execute it from there.Wrap your binaries in a DLL file and execute them with
rundll32
to bypass executable rules if DLL execution is not enforced (default behavior).If binaries like Python are allowed, use those. If that doesn’t work, try other techniques such as wrapping JScript in a HTA file or running XSL files with
wmic
.Otherwise elevate your privileges. AppLocker rules are most often not enforced for (local) administrative users.
PowerShell Constrained Language Mode
You can identify you’re in constrained language mode by polling the following variable to get the current language mode. It will say FullLanguage
for an unrestricted session, and ConstrainedLanguage
for CLM.
The constraints posed by CLM will block many of your exploitations attempts as key functionality in PowerShell is blocked. Bypassing CLM is largely the same as bypassing AppLocker as discussed above.
Another quick and dirty bypass is to use in-line functions, which sometimes works. If e.g. whoami
is blocked, try the following:
LAPS
The permission ReadLAPSPassword
grants users or groups the ability to read the ms-Mcs-AdmPwd
property and as such get the local admin password. We can also use PowerView to read the password, if we know that we have the right ReadLAPSPassword
privilege to a machine.
We can also use LAPSToolkit.ps1 to identify which machines in the domain use LAPS, and which principals are allowed to read LAPS passwords. If we are in this group, we can get the current LAPS passwords using this tool as well.
Lateral Movement
Lateral Movement Enumeration With PowerView
BloodHound
Use Invoke-BloodHound
from SharpHound.ps1
, or use SharpHound.exe
. Both can be run reflectively, get them here. Examples below use the PowerShell variant but arguments are identical.
For real engagements definitely look into the various arguments that BloodHound provides for more stealthy collection and exfiltration of data.
Kerberoasting
Automatic
With PowerView:
Crack the hash with Hashcat:
Bash
Manual
Targeted kerberoasting by setting SPN
We need have ACL write permissions to set UserAccountControl flags for the target user, see above for identification of interesting ACLs. Using PowerView:
AS-REP roasting
Get the hash for a roastable user (see above for hunting). Using ASREPRoast.ps1
:
Crack the hash with Hashcat:
Targeted AS-REP roasting by disabling Kerberos pre-authentication
Again, we need ACL write permissions to set UserAccountControl flags for the target user. Using PowerView:
Token Manipulation
Tokens can be impersonated from other users with a session/running processes on the machine. Most C2 frameworks have functionality for this built-in (such as the ‘Steal Token’ functionality in Cobalt Strike).
Incognito
If you’re using Meterpreter, you can use the built-in Incognito module with use incognito
, the same commands are available.
Invoke-TokenManipulation
Lateral Movement with Rubeus
We can use Rubeus to execute a technique called “Overpass-the-Hash”. In this technique, instead of passing the hash directly (another technique known as Pass-the-Hash), we use the NTLM hash of an account to request a valid Kerberost ticket (TGT). We can then use this ticket to authenticate towards the domain as the target user.
Once we have a TGT as the target user, we can use services as this user in a domain context, allowing us to move laterally.
Lateral Movement with Mimikatz
Note that Mimikatz is incredibly versatile and is discussed in multiple sections throughout this blog. Because of this, however, the binary is also very well-detected. If you need to run Mimikatz on your target (not recommended), executing a custom version reflectively is your best bet. There are also options such as Invoke-MimiKatz or Safetykatz. Note that the latter is more stealthy but does not include all functionality.
Plaintext
A nice overview of the SPNs relevant for offensive purposes is provided here (scroll down) and here.
Command execution with scheduled tasks
Requires ‘Host’ SPN
To create a task:
PowerShell
To trigger the task:
PowerShell
Command execution with WMI
Requires ‘Host’ and ‘RPCSS’ SPNs
From Windows
PowerShell
From Linux
Bash
Command execution with PowerShell Remoting
Requires ‘CIFS’ and ‘HTTP’ SPNs. May also need the ‘WSMAN’ or ‘RPCSS’ SPNs (depending on OS version)
PowerShell
Unconstrained delegation
Unconstrained Delegation can be set on a frontend service (e.g., an IIS web server) to allow it to delegate on behalf of a user to any service in the domain (towards a backend service, such as an MSSQL database).
DACL UAC property: TrustedForDelegation
.
Exploitation
With administrative privileges on a server with Unconstrained Delegation set, we can dump the TGTs for other users that have a connection. If we do this successfully, we can impersonate the victim user towards any service in the domain.
With Mimikatz:
Plaintext
Or with Rubeus:
PowerShell
We can also gain the hash for a domain controller machine account, if that DC is vulnerable to the printer bug. If we do this successfully, we can DCSync the domain controller (see below) to completely compromise the current domain.
On the server with Unconstrained Delegation, monitor for new tickets with Rubeus.
PowerShell
From attacking machine, entice the Domain Controller to connect using the printer bug. Binary from here.
PowerShell
The TGT for the machine account of the DC should come in in the first session. We can pass this ticket into our current session to gain DCSync privileges (see below).
PowerShell
Constrained delegation
Constrained delegation can be set on the frontend server (e.g. IIS) to allow it to delegate to only selected backend services (e.g. MSSQL) on behalf of the user.
DACL UAC property: TrustedToAuthForDelegation
. This allows s4u2self
, i.e. requesting a TGS on behalf of anyone to oneself, using just the NTLM password hash. This effectively allows the service to impersonate other users in the domain with just their hash, and is useful in situations where Kerberos isn’t used between the user and frontend.
DACL Property: msDS-AllowedToDelegateTo
. This property contains the SPNs it is allowed to use s4u2proxy
on, i.e. requesting a forwardable TGS for that server based on an existing TGS (often the one gained from using s4u2self
). This effectively defines the backend services that constrained delegation is allowed for.
NOTE: These properties do NOT have to exist together! If s4u2proxy
is allowed without s4u2self
, user interaction is required to get a valid TGS to the frontend service from a user, similar to unconstrained delegation.
Exploitation
In this case, we use Rubeus to automatically request a TGT and then a TGS with the ldap
SPN to allow us to DCSync using a machine account.
PowerShell
Resource-based constrained delegation
Resource-Based Constrained Delegation (RBCD) configures the backend server (e.g. MSSQL) to allow only selected frontend services (e.g. IIS) to delegate on behalf of the user. This makes it easier for specific server administrators to configure delegation, without requiring domain admin privileges.
DACL Property: msDS-AllowedToActOnBehalfOfOtherIdentity
.
In this scenario, s4u2self
and s4u2proxy
are used as above to request a forwardable ticket on behalf of the user. However, with RBCD, the KDC checks if the SPN for the requesting service (i.e., the frontend service) is present in the msDS-AllowedToActOnBehalfOfOtherIdentity
property of the backend service. This means that the frontend service needs to have an SPN set. Thus, attacks against RBCD have to be performed from either a service account with SPN or a machine account.
Exploitation
If we compromise a frontend service that appears in the RBCD property of a backend service, exploitation is the same as with constrained delegation above. This is however not too common.
A more often-seen attack to RBCD is when we have GenericWrite
, GenericAll
, WriteProperty
, or WriteDACL
permissions to a computer object in the domain. This means we can write the msDS-AllowedToActOnBehalfOfOtherIdentity
property on this machine account to add a controlled SPN or machine account to be trusted for delegation. We can even create a new machine account and add it. This allows us to compromise the target machine in the context of any user, as with constrained delegation.
PowerShell
Abusing domain trust
All commands must be run with DA privileges in the current domain.
Note that if you completely compromise a child domain (currentdomain.targetdomain.com
), you can by definition also compromise the parent domain (targetdomain.com
) due to the implicit trust relationship. The same counts for any trust relationship where SID filtering is disabled (see ‘Abusing inter-forest trust’ below).
Using domain trust key
From the DC, dump the hash of the currentdomain\targetdomain$
trust account using Mimikatz (e.g. with LSADump or DCSync). Then, using this trust key and the domain SIDs, forge an inter-realm TGT using Mimikatz, adding the SID for the target domain’s enterprise admins group to our ‘SID history’.
Plaintext
Pass this ticket with Rubeus.
PowerShell
We can now DCSync the target domain (see below).
Using krbtgt hash
From the DC, dump the krbtgt hash using e.g. DCSync or LSADump. Then, using this hash, forge an inter-realm TGT using Mimikatz, as with the previous method.
Doing this requires the SID of the current domain as the /sid
parameter, and the SID of the target domain as part of the /sids
parameter. You can grab these using PowerView’s Get-DomainSID
. Use a SID History (/sids
) of *-516
and S-1-5-9
to disguise as the Domain Controllers group and Enterprise Domain Controllers respectively, to be less noisy in the logs.
Plaintext
If you are having issues creating this ticket, try adding the ‘target’ flag, e.g.
/target:targetdomain.com
.
Alternatively, generate a domain admin ticket with SID history of enterprise administrators group in the target domain.
We can now immediately DCSync the target domain, or get a reverse shell using e.g. scheduled tasks.
Abusing inter-forest trust
Since a forest is a security boundary, we can only access domain services that have been shared with the domain we have compromised (our source domain). Use e.g. BloodHound to look for users that have an account (with the same username) in both forests and try password re-use. Additionally, we can use BloodHound or PowerView to hunt for foreign group memberships between forests. The PowerView command:
PowerShell
In some cases, it is possible that SID filtering (the protection causing the above), is disabled between forests. If you run Get-DomainTrust
and you see the TREAT_AS_EXTERNAL
property, this is the case! In this case, you can abuse the forest trust like a domain trust, as described above. Note that you still can NOT forge a ticket for any SID between 500 and 1000 though, so you can’t become DA (not even indirectly through group inheritance). In this case, look for groups that grant e.g. local admin on the domain controller or similar non-domain privileges. For more information, refer to this blog post.
To impersonate a user from our source domain to access services in a foreign domain, we can do the following. Extract inter-forest trust key as in ‘Using domain trust key’ above.
Use Mimikatz to generate a TGT for the target domain using the trust key:
Plaintext
Then, use Rubeus to ask a TGS for e.g. the CIFS
service on the target DC using this TGT.
PowerShell
Now we can use the CIFS service on the target forest’s DC as the DA of our source domain (again, as long as this trust was configured to exist).
Abusing MSSQL databases for lateral movement
MSSQL databases can be linked, such that if you compromise one you can execute queries (or even OS commands!) on other databases in the context of a specific user (sa
maybe? 😙). If this is configured, it can even be used to traverse Forest boundaries! If we have SQL execution, we can use the following commands to enumerate database links.
SQL
We can also use PowerUpSQL to look for databases within the domain, and gather further information on (reachable) databases. We can also automatically look for, and execute queries or commands on, linked databases (even through multiple layers of database links).
PowerShell
If you have low-privileged access to a MSSQL database and no links are present, you could potentially force NTLM authentication by using the xp_dirtree
stored procedure to access this share. If this is successful, the NetNTLM for the SQL service account can be collected and potentially cracked or relayed to compromise machines as that service account.
SQL
Example command to relay the hash to authenticate as local admin (if the service account has these privileges) and run calc.exe
. Omit the -c
parameter to attempt a secretsdump
instead.
Bash
Abusing Group Policy Objects for lateral movement
If we identify that we have the permissions to edit and link new Group Policy Objects (GPOs) within the domain (refer to ‘AD Enumeration With PowerView’), we can abuse these privileges to move laterally towards other machines.
As an example, we can use the legitimate Remote System Administration Tools (RSAT) for Windows to create a new GPO, link it to the target, and deploy a registry runkey to add a command that will run automatically the next time the machine boots.
PowerShell
We can also use SharpGPOAbuse to deploy an immediate scheduled task, which will run whenever the group policy is refreshed (every 1-2 hours by default). SharpGPOABuse does not create its own GPO objects, so we first have to run the commands for creating and linking GPOs listed above. After this, we can run SharpGPOAbuse to deploy the immediate task.
PowerShell
Privilege Escalation
For more things to look for (both Windows and Linux), refer to my OSCP cheat sheet and command reference.
PowerUp
PowerShell
UAC Bypass
Using SharpBypassUAC.
Bash
In some cases, you may get away better with running a manual UAC bypass, such as the FODHelper bypass which is quite simple to execute in PowerShell.
PowerShell
Persistence
Startup folder
Just drop a binary. Classic. 😎🚩
In current user folder, will trigger when current user signs in:
Plaintext
Or in the global startup folder, requires administrative privileges but will trigger as SYSTEM on boot and in a user context whenever any user signs in:
Plaintext
Domain Persistence
Must be run with DA privileges.
Mimikatz skeleton key attack
Run from DC. Enables password “mimikatz” for all users. 🚩
Plaintext
Grant specific user DCSync rights with PowerView
Gives a user of your choosing the rights to DCSync at any time. May evade detection in some setups.
PowerShell
Domain Controller DSRM admin
The DSRM admin is the local administrator account of the DC. Remote logon needs to be enabled first.
PowerShell
Now we can login remotely using the local admin hash dumped on the DC before (with lsadump::sam
, see ‘Dumping secrets with Mimikatz’ below). Use e.g. ‘overpass-the-hash’ to get a session (see ‘Mimikatz’ above).
Modifying security descriptors for remote WMI access
Give user WMI access to a machine, using Set-RemoteWMI cmdlet from Nishang. Can be run to persist access to e.g. DCs.
PowerShell
For execution, see ‘Command execution with WMI’ above.
Modifying security descriptors for PowerShell Remoting access
Give user PowerShell Remoting access to a machine, using Set-RemotePSRemoting.ps1 cmdlet from Nishang. Can be run to persist access to e.g. DCs.
PowerShell
For execution, see ‘Command execution with PowerShell Remoting’ above.
Modifying DC registry security descriptors for remote hash retrieval using DAMP
Using DAMP toolkit, we can backdoor the DC registry to give us access on the SAM
, SYSTEM
, and SECURITY
registry hives. This allows us to remotely dump DC secrets (hashes).
We add the backdoor using the Add-RemoteRegBackdoor.ps1
cmdlet from DAMP.
PowerShell
Dump secrets remotely using the RemoteHashRetrieval.ps1
cmdlet from DAMP (run as ‘BackdoorUser’ user).
PowerShell
DCShadow
DCShadow is an attack that masks certain actions by temporarily imitating a Domain Controller. If you have Domain Admin or Enterprise Admin privileges in a root domain, it can be used for forest-level persistence.
Optionally, as Domain Admin, give a chosen user the privileges required for the DCShadow attack (uses Set-DCShadowPermissions.ps1
cmdlet).
PowerShell
Then, from any machine, use Mimikatz to stage the DCShadow attack.
Plaintext
Finally, from either a DA session OR a session as the user provided with the DCShadow permissions before, run the DCShadow attack. Actions staged previously will be performed without leaving any logs 😈
Plaintext
Post-Exploitation
LSASS protection
Sometimes, LSASS is configured to run as a protected process (PPL). You can query this with PowerShell as follows.
PowerShell
If this is the case, you can’t just dump or parse LSASS, and you need to disable the protection with something like mimidrv.sys
. I won’t discuss how to do that here, but there are tools such as PPLDump available to help.
Dumping OS credentials with Mimikatz
Plaintext
Abusing the Data Protection API (DPAPI) with Mimikatz
Mimikatz has quite some functionality to access Windows' DPAPI, which is used to encrypt many credentials, including e.g. browser passwords.
Note that Mimikatz will automatically cache the master keys that it has seen (check cache with dpapi::cache
), but this does NOT work if no Mimikatz session is persisted (e.g. in Cobalt Strike or when using Invoke-Mimikatz
). More information on using Mimikatz for DPAPI is available here.
Plaintext
Dumping secrets without Mimikatz
We can also parse system secrets without using Mimikatz on the target system directly.
Dumping LSASS
The preferred way to run Mimikatz is to do it locally with a dumped copy of LSASS memory from the target. Dumpert, Procdump, or other (custom) tooling can be used to dump LSASS memory.
PowerShell
After downloading the memory dump file on our attacking system, we can run Mimikatz and switch to ‘Minidump’ mode to parse the file as follows. After this, we can run Mimikatz' credential retrieval commands as usual.
Plaintext
Dumping secrets from the registry
We can dump secrets from the registry and parse the files “offline” to get a list of system secrets. 🚩
On the target, we run the following:
PowerShell
Then on our attacking box we can dump the secrets with Impacket:
Bash
Dumping secrets from a Volume Shadow Copy
We can also create a “Volume Shadow Copy” of the SAM
and SYSTEM
files (which are always locked on the current system), so we can still copy them over to our local system. An elevated prompt is required for this.
PowerShell
Windows Defender evasion
Note: All below commands require administrative privileges on the system!
You can query Defender exclusions using PowerShell. If it returns any excluded paths, just execute your malware from there!
PowerShell
Alternatively, you could add an exclusion directory for your shady stuff. 👀
PowerShell
If you’re more aggro, you can disable Defender entirely. It goes without saying that disabling AV/EDR products is never a good idea in practice, best to work around it instead. 🚩
PowerShell
As an alternative to disabling Defender, you can leave it enabled and just remove all virus signatures from it.
PowerShell
Chisel proxying
If you need to proxy traffic over a compromised Windows machine, Chisel (or SharpChisel) is a good choice. Chisel allows port forwarding, but my favorite technique is setting up a reverse SOCKS proxy on the target machine, allowing you to tunnel any traffic over the target system.
On our attacking machine (Linux in this case), we start a Chisel server on port 80 in reverse SOCKS5 mode.
Bash
Then, on our compromised target system, we connect to this server and tell it to proxy all traffic over it via the reverse SOCKS5 tunnel.
PowerShell
A proxy is now open on port 1080 of our linux machine. We can now use e.g. ProxyChains to tunnel over the target system.
Juicy files
There are lots of files that may contain interesting information. Tools like WinPEAS or collections like PowerSploit may help in identifying juicy files (for privesc or post-exploitation).
Below is a list of some files I have encountered to be of relevance. Check files based on the programs and/or services that are installed on the machine.
In addition, don’t forget to enumerate any local databases with
sqlcmd
orInvoke-SqlCmd
!
Last updated