Defending Against Mimikatz

Intro to Mimikatz

One of the most interesting tools in a penetration tester’s arsenal is mimikatz.  Mimikatz is a tool that scrapes the memory of the process responsible for Windows authentication(LSASS) and reveals cleartext passwords and NTLM hashes that an attacker can use to pivot around a network.  From that point they escalate privilege either by authenticating with the clear text credentials or passing the hash. Sounds deadly right? Most people have the reaction “Why hasn’t Microsoft come up with a solution to this?”.

If you Google the phrase “defending against mimikatz” the information you find is a bit lackluster. The best article I have found was this one. It has a lot of good suggestions like using the “Protected Users” group(SID: S-1-5-21-<domain>-525) available in recent versions of Active Directory and also limiting administrator usage, and taking advantage of not storing passwords in memory with a registry setting. You can limit the number of services running as system or remove debug privilege to help prevent an attacker from being able to run mimikatz. What this and other articles make you believe is that you need to have Windows 8 or 8.1 or 10 rolled out everywhere. What about the large number of Windows 7/2008 R2 machines out there? Well it turns out you can defend against mimikatz on these versions of Windows, here is how.

GIANT EDIT

It seems that some have felt this article is claiming that the Protected Users group is the be all and end all for defending against mimikatz.  While this article does spend a decent amount of time on this feature fleshing out how this feature works and proving that it works on more platforms than Microsoft’s own documentation states, the Protected Users group should not be the only defense against mimikatz.  Other than scanning for malicious activity and files as well as other more traditional and general security controls, the primary defense against mimikatz is limiting administrative privileges to only those users that need it.

Step One:  Active Directory 2012 R2 Functional Level

The first thing that you can do is upgrade the schema and functional level of your forest and domain(s) to 2012 R2.  This domain functional level adds a new group called “Protected Users”.  If you read the TechNet article on Protected Users you might get the feeling that this is the thing that will make mimikatz password scraping impossible against a Protected User.  But what does that look like?

Notice that NTLM hashes are visible when running mimikatz against a non Protected User

This is pretty standard mimikatz output, notice that NTLM hashes are visible when running mimikatz against a non Protected User

And when a user is added to the Protected Users group we see that there aren't any NTLM hashes or plain text passwords.

And when a user is added to the Protected Users group we see that there aren’t any NTLM hashes or plain text passwords.

So clearly the Protected Users group works.  But what happens when a user is in the Protected Users group on a Windows 7 or 2008 R2 box?

Notice that even in the Protected Users group the passwords and hash is visible on 2008 R2

Notice that even in the Protected Users group the passwords and hash is visible on 2008 R2

This machine is unpatched though.  If you think about it, the group “Protected Users” is meaningless to the computer without it knowing what being in that group means.  Fortunately Microsoft backported the functionality of Windows 8.1 and 2012 R2 to older versions of Windows.

Step Two: Install KB2871997

So if you have been keeping up with your Windows updates, as you should, then KB2871997 has already been installed.  This is the update that backports the functionality to older, but still supported versions of Windows.  Once we install the update we see 2008 R2, as an example behaves in a similar matter.

This is what things look like post KB2871997 with the user not in the Protected Users group

This is what things look like on 2008 R2/Win 7 box post update KB2871997 with the user not in the Protected Users group

Once in the Protected Users group we see the same behavior as on 2012 R2

Once in the Protected Users group we see the same behavior on 2008 R2/Win 7 as on 2012 R2

Step Three: Eliminate Passwords Storage in Memory

So this step is probably optional, as any account you care about you are going to want to make a Protected User, however you won’t be able to do this with every account in your domain.  Microsoft itself recommends against putting computer accounts and service accounts into the Protected Users group. So this step strictly relates to users who are not in the Protected Users group.

If you have a keen eye, you will have no doubt noticed that in the screenshots of 2012 R2 the password is never revealed by mimikatz while under 2008 R2 the password is revealed when not a protected user.  The storage of passwords in memory is governed by a registry setting.  Just like the Protected Users group functionality, password storage in memory is disallowed in newer versions of Windows(8.1+ & 2012 R2+) by default.  Also like the Protected Users group functionality, password storage in memory was backported in the same KB2871997 update.  Unfortunately even after the update these older versions of Windows still default to storing the password in memory by default, you know… because compatibility.  Simply set the “UseLogonCredential” registry setting, at the path below, to ‘0’ and you are golden.

registry settings modified

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\WDigest

This user is not in the Protected Users group but is logged into a machine where the registry entry is set.

This user is not in the Protected Users group but is logged into a machine where the registry entry is set thus we now see no password stored in memory as we would on 2012 R2.

Conclusion

So essentially, update Active Directory functional level to 2012 R2, keep up with Windows Update, put important accounts into the Protected Users group and set a registry setting.  Also don’t give account more admin rights than they need.  I hope this post finally serves as a unified perspective on how to best defend against this.  Another thing to mention about the Protected Users functionality is that members of that group are protected against Kerberos related “Golden Ticket” attacks as Kerberos tickets for Protected Users go from potentially valid for up to 10 years, to 4 hours.  As always you should test this functionality before rolling it out as applications that do not support Kerberos authentication are going to break.  Happy hacking.

 

EDIT: I want to thank everyone for the great feedback to the article.  As @Iansus pointed out ADSecurity talked about this a while ago.  I’m going to leave my post up, as it is a more hands-on, cause and effect post.

8 thoughts on “Defending Against Mimikatz

  1. sekurlsa::pth /name:administrator /domain:domain.tld /ntlm: starts a cmd.exe with the given identity.
    Any action done throught the given identity will be done with this given identity.

    If the NTLM-Hash is not stored in the lsacache it could be obtained through the AD database.

    As far as I know there is actually no real protection – even with up to date hotfixes.

    See also: Bastion Forest

    1. I used the domain Administrator account for simplicity in a test domain, but probably should have minted a generic account for demonstration purposes. You won’t always be lucky enough to pop a domain admin or pop him while he is logged into a domain controller. These mitigations are about helping prevent someone from getting to domain admin.

  2. Question, if the actions described in Steps 2 and 3 above are taken, but the domain functionality level is not set to 2012 R2 as required in Step 1, would the password storage in memory be protected?

    1. The password would not be if you had set the registry entry mentioned in the article. The NTLM hash would still be stored. I’ve heard reports that if you host the PDF emulator FSMO role on a 2012 R2 box you actually get the protected users functionality, helping to protect the hash, but I’m not sure whether or not this is a ‘supported configuration’ of Microsoft.

  3. Unfortunately a am not on AD Functional Level 2012 R2 yet, trying, old apps involved. The KB was already on our machines, I implemented step 3 and rebooted. It does what is says. I have confirmed that but use your admin account to connect to another machine and voila, there is the password.

  4. hi, thanks first of all.

    I’ve got a question, wouldn’t it be also an idea to reboot in a very regular base? because mimikatz is only capable of retrieving passwords or hashes which are in memory. Can you give us some common example use cases where passwords are in the memory? Is it when a service is running, is it when one connects via RDP, is it when a sched task is started or when are the passwords in memory? TIA

Leave a Reply