Mitigating Mimikatz

8 min readJun 3, 2021

TL;DR an overview of how to implement various mitigations against Mimikatz such as putting domain admins in the Protected Users group, restricting debug rights, auditing AD, etc.

In a previous post I ran through a scenario involving an attacker gaining local admin access on a workstation, grabbing a domain admin’s hash with Mimikatz, escalating privilege via passing the hash, executing DCSync to grab the krbtgt hash, and then generating a Golden Ticket to maintain persistence ( I glazed over mitigating against Mimikatz style attacks in that post. This is a follow up on how to implement various countermeasures.

Put Domain Admins in the Protected Users AD group

One of the best tactics is to simply put all privileged user accounts in the Protected Users group in Active Directory with very few, management approved exemptions. At the very least do this for those with Domain Admin rights. This prevents workstations from caching a NT hash when the user logins and forces Kerberos authentication to the domain. It has the added benefit of preventing a workstation from caching the protected user’s credentials even if an attacker re-enables WDigest by abusing local admin rights.

This is illustrated by a tale of two domain admins on the lab domain corp.local. One is named Frisky McRisky, the other is Living Dangerously. Both log into random domain workstations constantly because they ‘just need to get work done and those security guys just don’t understand how we do things’. Living Dangerously though has been put in the AD group Protected Users whereas Frisky has not. This is transparent to both of them as long as they login to systems that are online at the time. In the unlikely event that Living Dangerously attempts to login to an offline workstation they will see:

This is all an attacker will see if they run Mimikatz as the local admin after a Protected User such as Living Dangerously logs in to the compromised workstation:

On the other hand the attacker will see the following information for Frisky McRisky:

Given this information the attacker can easily execute a pass the hash attack to escalate to Frisky’s privileges by simply running

sekurlsa::pth /user:frisky.mcrisky /ntlm:1ea0dced5755e5f138373c81ab872a70 /domain:corp.local

It only gets worse after that as both of these domain admins have the privileges ‘Replicating Directory Changes’ and ‘Replicating Directory Changes All’. This allows the attacker to in turn generate an infamous Golden Ticket and take over the entire domain for the next 10 years.

At this point it is game over. Detective measure are great, but by the time they log this and an analyst inspects the event the domain is already done for. Even if the attacker is manually typing the commands he can still perform the attack in less than a minute given local admin access to a workstation that Frisky McRisky uses. This type of attack requires prevention, and one of the best ways to stop it is to put these admins in the Protected Users group in AD.

Audit AD to identify these high value accounts via BloodHound

How do you easily identify those higher level privileged users who should be members of Protected Users? By regularly auditing Active Directory of course. BloodHound is one free tool for doing this. We previously covered how to get BloodHound setup and running here.

All that is required to pull the data from AD is the ability to run SharpHound as a domain user. Any domain user can read AD information, with a few exceptions such as confidential attributes like ms-Mcs-AdmPwd.

Plug the resulting *.zip file into BloodHound and it presents a nice graphical representation of the groups that have privileges to run DCSync, the relationships that are giving them those privileges, and what users are contained in those groups and are in turn inheriting the privileges. To make things even easier, BloodHound has a built in query for ‘Find Principals with DCSync Rights’ as shown below on corp.local. The results may surprise some auditors as a live domain environment can get messy over time with new groups being created, groups getting nested inside other groups, and so on.

BloodHound even helpfully explains what the relationships mean if one right clicks on them.

Audit AD to identify these high value accounts via ADUC

Unfortunately the tool that is built in to Active Directory Users & Computers (ADUC) is not terribly useful for answering the question “so who has privileges to pull this krbtgt NT hash on our domain?”. It can let you, or any domain user, know if a given user has the privileges. However it is limited to auditing one user or group at a time. This can be done by viewing the Advanced Security settings on the domain root, then clicking the tab Effective Access.

Buried in that long list of privileges are the two all important ones that give a user the ability to execute DCSync:

Audit AD to identify these high value accounts via PowerShell

A somewhat more efficient method of querying this though is to simply use PowerShell. We can use Microsoft’s mapping of access right to Identifying GUID to see that:


DS-Replication-Get-Changes 1131f6aa-9c07–11d1-f79f-00c04fc2dcd2

DS-Replication-Get-Changes-All 1131f6ad-9c07–11d1-f79f-00c04fc2dcd2

Microsoft makes this a bit more confusing than it needs to be by using “DS-Replication-Get-Changes” in one place in the documentation while using “Replicating Directory Changes” in ADUC. Luckily Google helps figure out the query.

PS C:\> Import-Module ActiveDirectory
PS C:\> Set-Location AD:
PS AD:\> (Get-ACL 'dc=corp,dc=local').Access | Where {$_.ObjectType -Like "1131f6aa-9c07–11d1-f79f-00c04fc2dcd2" -and "1131f6ad-9c07–11d1-f79f-00c04fc2dcd2"}

Then run another PowerShell query to list all user accounts that are nested under BUILTIN\Administrators:

Get-ADGroupMember “CN=Administrators,CN=Builtin,DC=corp,DC=local” -Recursive | Select-Object Name

Of course if desired then you can save the results to a CSV file so managers, auditors, etc can review the list and decide if those on it should have their privileges reduced.

Get-ADGroupMember “CN=Administrators,CN=Builtin,DC=corp,DC=local” -Recursive | Select-Object Name | Export-Csv “C:\Data\list.csv”

Of course if there are other groups listed besides BUILTIN\Administrators, DCs, and RODCs then one would want to make sure they are there legitimately and list their members as well.

Please note; I orginally wrote this two years ago. Here at test.local we have since expanded on this and created a much more comprehensive query here.

Stop Mimikatz from grabbing hashes in the first place

However it would of course be better to prevent them from running Mimikatz in the first place. This can be aided by preventing them from abusing the all-important debug right. By default the local admin account on domain workstations has this privilege, but why would this be necessary? At the very least this should be restricted to specific domain user accounts that have approved exemptions.

Like most policies in a Windows Domain, this is easily set via GPO. It is located under Computer Configuration\Policies\Windows Settings\Security Settings\Local Policies\User Rights Assignment. Simply define the policy and only add the users or groups who have an approved exemption.

This is what an attacker will see after this GPO is applied.

Other mitigating controls

There are a few other additional mitigations such as restricting what workstations those with Domain Admin rights can log in to. After all, Mimikatz cannot capture a Domain Admin’s NT hash if a system administrator never logins to the compromised workstation in the first place. Policy could dictate the usage of lower level privileged user accounts that only have delegated rights to the domain workstation OU for performing day to day helpdesk tasks. This can be set under Computer Configuration\Policies\Windows Settings\Security Settings\Local Policies\User Rights Assignment, then simply link the GPO to the OU containing the domain workstations that normal users utilize.

Delegate OU permissions rather than making lower level privileged users Domain Admins or putting them in a group that in turn inherits Domain Admin rights. The account ‘Playing It Safe’ (SamAccountName = is delegated the ability to join computers to the domain and is given rights to add and delete child objects in the OU containing domain workstations.


Don’t live dangerously. Audit AD, find the privileged users that have the rights necessary to run DCSync, put them in the Protected Users group, and then decide if they really need those rights or not. Follow least privilege. Don’t let domain admins get in the habit of using their privileged account for day to day tasks. Delegate OU rights to lower level helpdesk accounts and use those for fixing people’s email issues and such. Use GPOs to restrict debug privileges. Deploy LAPS to domain workstations if it isn’t already.

There is an idea for the truly paranoid that leverages LAPS to prevent credential theft by not having any domain credentials present on workstations in the first place. That is an entire howto on its own.

These best practices will go a long way towards protecting the domain from being harmed by the compromise of one domain workstation.





I work various IT jobs & like Windows domain security as a hobby. Most of what’s here is my notes from auditing or the lab.