Last Updated: 2019-02-05 15:26:32 UTC
by Rob VandenBrink (Version: 1)
If you are like me, at some point in most penetration tests you'll have a session on a Windows host, and you'll have an opportunity to dump Windows credentials from that host, usually using Mimikatz. Mimikatz parses credentials (either clear-text or hashes) out of the LSASS process, or at least that's where it started - since it's original version back in the day, it has expanded to cover several different attack vectors. An attacker can then use these credentials to "pivot" to attack other resources in the network - this is commonly called "lateral movement", though in many cases you're actually walking "up the tree" to ever-more-valuable targets in the infrastructure.
The defender / blue-teamer (or the blue-team's manager) will often say "this sounds like malware, isnt't that what Antivirus is?". Sadly, this is half right - malware does use this style of attack. The Emotet strain of malware for instance does exactly this, once it gains credentials and persistence it often passes control to other malware (such as TrickBot or Ryuk). Also sadly, it's been pretty easy to bypass AV on this for some time now - there are a number of well-known bypasses that penetration testers use for the Mimikatz + AV combo, many of them outlined on the BHIS blog: https://www.blackhillsinfosec.com/bypass-anti-virus-run-mimikatz
But what about standard Windows mitigations against Mimikatz? Let's start from the beginnning, when Mimikatz first came out, Microsoft patched against that first version of code using KBKB2871997 (for Windows 7 era hosts, way back in 2014).
Since then, this protection has been integrated into Windows 8.x, Windows 10 and Server 2016+.
Unfortunately, even after applying this patch credentials are still stored in memory. You still need to update a registry key to disable this behaviour:
UseLogonCredential, set to 0
(again, this is not required unless you still have Windows 7 or XP)
However, what you'll find is that these protections only protect against the initial vector. Mimikatz and Microsoft are in an ongoing game of "cat and mouse" over this issue, and newer versions of Mimikatz have newer attacks.
So What else can you do?
As with everything, if you have SMBv1 or unsigned connections enabled, there are easier ways to skin the AD credential cat than to use Mimikatz - namely just use responder if you happen to have a host on the inside network:
You might want to scan for hosts that still support SMBv1 and mitigate those ( https://isc.sans.edu/forums/diary/Rooting+Out+Hosts+that+Support+Older+Samba+Versions/22672/ ). You can also disable SMBv1 globally using GPO:
Also, forcing the signature of SMB connections will help against responder-type attacks:
Back to Mimikatz Specific Defenses:
Update your the OS on your Windows Servers.
All too often we still see original-era Server 2008, Windows 7, or even Server 2003 and XP (or in some cases Server 2000! ). Needless to say, the newer Windows Server OS's shine a brighter light on security - newer really is better. If it won't break your server applications, update to Windows Server 2016 and Windows 10 (or 2019 if you are brave)
Update Active Directory's Functional level
Really this restates the first point. Many of the Enterprise Protections that we'll discuss later in this post simply aren't available unless your AD Functional Level is set to some modern version. If you can get the member stations updated, get your AD to 2016 at all possible!
Disable the debug right for local administrators on all servers and workstation
This is a newer attack - Windows has a "debug mode" that allows you to bypass many of it's native protections. This is meant mainly to troubleshoot things like device drivers and other OS or low-level Application components.
If you have developers in your environment, they will absolutely push back against this change. However, this right is only needed if you are running a "real" debugger such as IDA and are doing things like setting breakpoints in compiled binary code - you don't need usually this right to debug more common, higher level languages. Folks like forensics Investigators do need these rights, but if they want those rights on their domain member workstations they need to go back to forensicator school.
To disable this setting on a single host, from MSConfig, navigate to Boot / Advanced Options, and disable "Debug". This is the default setting in newer OS's.
In Group Policy, navigate to Security Settings / Local Policies / User Rights Assignments / Debug Programs.
By default, this is not configured - enable it, and don't add any users or groups to it (or add only the group(s) that truly need it, or who don't need it but won the political knife fight over this issue)
Disable the WDigest protocol across the board
This protocol was introduced way back in the day (XP era) for transparent HTTP authentication, and is still enabled by default in any surviving Windows 7 / Server 2008 hosts. It's disabled by default in Windows 8 and newer.
To disable this, in RegEdit navigate to:
The values UserLogonCredential and Negotiate should both be set to "0"
(Note that "UseLoginCredential" doesn't exist in Server 2016+ and Windows 10)
Adding some monitoring of registry keys allows you to detect if a future attacker changes these settings back.
Enable LSA protection (RunAsPPL registry key)
This provides some protection of the memory used by the LSASS process. To enable this, in the registry, navigate to
and set "RunAsPPL" to "1"
This one does have some risk, as it tries to apply protections to other components that LSASS might call (like 3rd party authentication code). This is the first mitigation that carries risk - this can break things! Fortunately Microsoft has some audit settings that can be deployed in advance to assess if you have a problem in this area first. More details on this, and the setting in general can be found here: https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection
Disable storage of plain text passwords in AD
Sometimes backwards compatibility thing comes back to bite Micosoft every day of the week. The "Reversible Encryption" setting is one of these. Back in olden times (Windows 2000 days), it was decided that people should be able to decrypt passwords, at the time mostly to make RADIUS work (IAS back then, now NPS). Sadly this setting remains with us today, and it allows you to decrypt passwords as fast as they can echo to the screen.
To disable this, in Group Policy navigate to: Computer Configuration / Security Settings / Account Policies / Password Policy, and set "Store Passwords using reversible encryption" to "Disabled":
This setting is also available in the "Fine Grained Password Policy" section of ADAC (Active Directory Admin Console) - clear the checkbox if you are setting this here
More details on this can be found here: https://www.blackhillsinfosec.com/your-password-is-wait-for-it-not-always-encrypted
Enable Restricted Admin Mode (“DisableRestrictedAdmin” and “DisableRestrictedAdminOutboundCreds” registry keys)
This sets up your RDP session to NOT store credentials in the memory of the target host. To start a session in Restricted Admin Mode, run your RDP session as:
mstsc /restrictedadmin /v:targethost
Note however that this means that your credentials aren't cached (that being the point), so from that RDP session you won't be able to use cached credentials to "pivot" to another host - for instance you won't be able to run Server Manager, WMIC, PSRemoting or any other AD admin tool and connect to transparently to another host. That's a good thing, because if you could you would have just defeated your own protection (oops)
You can also control this behaviour with registry keys:
In 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)
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa, the DWORD value to create and set is DisableRestrictedAdminOutboundCreds:
- Default value = doesn’t exist = 0 = Admin Outbound Creds are enabled
- Value =1 == Admin Outbound Creds are disabled
More can be found on these settings here:
Enforce “Enable Restrict delegation of credentials to remote servers” via group policy
This sets "restricted admin mode" as the default for all RDP sessions that are initiated by domain members that are in scope for that GPO. This approach is generally preferred over setting the registry keys as outlined above
The GPO seeting is:
Computer Configurations > Policies > Administrative Templates > System > Credential Delegation, Then Set Restrict Delegation of credential to remote servers to "Enable" and "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 doesn't mitigate against Mimikatz per-se, since Mimikatz attacks are generally against the local machine - it is more of a "prevent password sniffing off the wire" mitigation, so it defends against responder and the like. However, this setting is typically deployed in combination with Restricted Admin Mode and Protected Users Groups (see below for this one).
To enforce this in Group Policy:
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”
Disable password caching
By default Windows will cache the last "x" number of authentications (including the password hashes), in case no Domain Controllers are available. You can disable this in Group Policy at:
Computer Configuration -> Windows Settings -> Local Policy -> Security Options -> Interactive Logon: Number of previous logons to cache -> 0
Note that this might mess things up for people with laptops, who will want to login while away from the office. You can set up your VPN client to force a VPN connection before login, but that'll of course cause you headaches if you need to authenticate to a wireless hotspot first. Often that is mitigated by telling people to allow tethering to their cellphone, and then in written policies and technical controls forbid the use of free/public hotspots such as hotel or coffee shop wifi. This is a simple and effective mitigation, but it needs some thought and communication in advance to make it work in many organizations.
Put administrative accounts in the “Protected Users” AD group, to force Kerberos authentication
Before using the Protected Users group, carefully review at least these two "starter" MS docs on this topic - there are pre-requisits and some gotchas!
From the MS Documentation:
Members of the Protected Users group who are signed-on to Windows 8.1 (and newer) devices and Windows Server 2012 R2 (and newer) hosts can no longer use:
Default credential delegation (CredSSP) - plaintext credentials are not cached even when the Allow delegating default credentials policy is enabled
Windows Digest - plaintext credentials are not cached even when they are enabled
NTLM - NTOWF is not cached
Kerberos long term keys - Kerberos ticket-granting ticket (TGT) is acquired at logon and cannot be re-acquired automatically
Sign-on offline - the cached logon verifier is not created
If the domain functional level is Windows Server 2012 R2 (or higher), members of the group can no longer:
Authenticate by using NTLM authentication
Use Data Encryption Standard (DES) or RC4 cipher suites in Kerberos pre-authentication
Be delegated by using unconstrained or constrained delegation
Renew user tickets (TGTs) beyond the initial 4-hour lifetime
So for our discussion it disables most of the password caching we've discussed, forces Kerberos Authentication, and disables DES and RC4 ciphers.
Note that setting this group membership for servers or workstations will break a number of things (read those MS docs for details before you start working on this one!), this is meant for user accounts only.
As the name implies, Credential Guard, well, guards your credentials.
Essentially it uses the virtualization capabilities inherent in most modern CPUs to protect credentials. The LSA process continues to run in "user" memory, but the process itself no longer stores the credentials directly, it stores those in an "enclave" in memory that's protected by virtualization, using a process called "Virtual Secure Mode", in another related process called "LSA Secure Mode". As Microsoft explains it ( https://blogs.technet.microsoft.com/ash/2016/03/02/windows-10-device-guard-and-credential-guard-demystified/ ), LSA and LSA Secure Mode are both "Pretend VMs" under the same Hypervisor.
The configuration for Credential Guard is somewhat convoluted, but the high points are:
- Install the "Hyper-V Hypervisor" and "Isolated User Mode" Windows Features (Hyper-V itself is not required)
- (This is not required in Windows 10 v1607 and newer)
- Within Group Policy, enable "Turn on Virtualization Based Security", and inside that option, enable "Secure Boot" with "Enable Virtualization Based Protection of Code Integrity"
- Also in GPO, in Computer Configuration / Administrative Templates / System / Device Guard, set Deploy Code Integrity to "Enabled"
- Note that for this train to leave the station your CPU needs to support Intel VT or AMD V, and you need to boot using UEFI. Credential Guard will use TPM if it's available, but that doesn't seem to be well explained, aside from "Virtualization-based Security (VBS) uses the TPM to protect its key" (if anyone has a link for this other than https://docs.microsoft.com/en-us/windows/security/identity-protection/credential-guard/credential-guard-considerations I'd appreciate it)
Again, more details on deployment are here: https://blogs.technet.microsoft.com/ash/2016/03/02/windows-10-device-guard-and-credential-guard-demystified/
Have we mentioned that this is an arms race? In September of 2018, a bypass of this protection was announced in Mimikatz. While prior to this Mimikatz could harvest hashes directly from memory, what this bypass does is harvest credentials as they are entered - before they get to that protected memory area.
I would expect that since this is a virtualization protection, that Mimikatz might in the future use virtualization style attacks to harvest from the LSA Secure Mode memory space. Since LSA can reach that data, I'm sure that Microsoft has an API squirreled away to get there too (there seems to be an API for everything else) - stay tuned as the defenders and attackers amp up their respective games on this.
Restrict Service or other Purpose-created Admin accounts to specific stations or servers
Again, this one doesn't stop Mimikatz from stealing credentials from the machine, but what it does do is prevent the re-use of those credentials for lateral movement to other targets, which is usually the whole point of the attack.
In Active Directory Admin Center (ADAC), under Authentication Policies, the option exists to for instance "pin" a service account to the host that the service runs on. This means that that account (which is likely privileged) can't easily be used for lateral movement, even if the credentials are successfully recovered (using Mimikatz or other methods).
Set long and complex passwords for admin and service accounts
There are always more Mimikatz attacks - I haven't covered Kerberoasting and extraction of password hashes for services for instance, mainly because this story is more for the "Blue Team" defenders than the Red Team (attackers) - stay tuned, we'll get there on attacks.
Many of the Mimikatz attacks extract password hashes - you can often simply re-use these hashes in a "Pass the Hash" attack, but if the password is long and complex (I typically set service passwords to 16 or 32 or even more random characters), then the computation involved in cracking that password can make it cost-prohibitive. Using words or even phrases for privileged accounts is tough to justify, and adding a "L33tspeak" component only slows attackers down a little bit. Password length is the metric that matters the most, and not using real words takes many of the password cracking "short cuts" off the table. Note that this also is an arms race - as GPU hardware improves the "how much computation effort is costly?" value is continually getting higher.
Other defensive measures
There are log entries to look for to detect Mimikatz as well, but that's more detection than prevention - I'll try to cover that in a future post. I'll also run through some Mimikatz attack scenarios if someone doesn't beat me to it :-)
With this list behind us, it's apparent that this game between Mimikatz and Microsoft is an ongoing thing. I'm sure that I've missed things in the list above, but this is a decent "starter" list of mitigations that should give you some decent coverage. A determined attacker is likely to be able to still "get the job done", but implementing everything above will likely slow them down. Automated malware that uses Mimikatz methods has less chance, no surprise there. I'd also not be surprised if an entirely new attack doesn't pop up in the next few months, with a new defense from Microsoft to match it.
Also with everything being said, I've yet to find an AD domain where everything above has been implemented. Most AD Domains that I've assessed or pentested still have Server 2003 or Windows 7 (or even Server 2000!) members in production, so some of the recommended settings above can't be implemented yet.
Challenge to our Readers:
With everything I've described, what Mimikatz attacks do you use that will still execute successfully after the mitigations above are in place? Please, use our comment form and share - I'd count this one as a win if we have more mitigations posted by you, our readers than I have in the write-up above!