Detecting Credential Stealing with Cortex XDR

Executive Summary

Credential stealing is an endless cat and mouse game between attackers and defenders. We, the defenders, always try to stay up to date with the latest techniques and protect our customers against the new attack before it has been published and used widely.

One of the most common credential stealing tools is Mimikatz, an open-source tool with different modules used to gather credentials from Windows systems.

In this blog post, we will go over some common credential stealing techniques, mainly focusing on Mimikatz implementation, demonstrate attack scenarios using Mimikatz and explain how Cortex XDR protects our customers against these kinds of attacks.

Credential Stealing on Windows Systems

There are many types and forms of Windows credentials stored in different locations in the system:

  • LSASS process memory - Once a user logs into a Windows system, different credentials are generated and stored in the process memory. Lsass stores different credentials forms, such as NTLM/LM passwords hashes, Kerberos tickets and sometimes even clear text passwords.
    The credentials are stored in LSASS memory in order to provide a single-sign-on (SSO) experience, so the users won’t have to insert their credentials every time they access a resource.
  • SAM database - SAM contains credentials for local users' accounts. An attacker can extract these credentials by dumping the SAM entries from the registry.
  • NTDS.DIT - password hashes for domain users are saved in a database file called NTDS.DIT, saved in the domain controller (DC). One of the techniques used to extract credentials from this file is called DCSync. In this attack, an attacker pretends to be a DC in order to retrieve password hashes remotely from the organization DC, using Microsoft Directory Replication Service Remote Protocol (MS-DRSR).

  • Credentials in DPAPI blobs - DPAPI is a windows mechanism allowing the encryption and decryption of a blob using the logged-on user hash. Different Windows passwords are encrypted using this mechanism such as Chrome, Internet Explorer, email accounts, passwords saved in Credential Manager, etc.
  • LSASS secrets - contain different credentials types such as service accounts passwords. They are stored in the registry path HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets

Of course, there are many other credentials types saved in Windows systems and as a result, many more stealing techniques.

Cortex XDR has multiple layers of defense. Each layer detects and blocks malicious activities using different methods. The first method is based on static analysis - including blocking files based on their reputation, scanning for static signatures, running different machine learning modules, checking for heuristic signatures and more. In addition to the static analysis, Cortex XDR provides behavioral threat protection, which analyzes suspicious files based on their activities in runtime.

Extracting Credentials from LSASS

One of the most popular Mimikatz modules is Sekurlsa. This module extracts different credentials types from LSASS, by reading the process memory. For extracting credentials from the memory, Mimikatz uses the API function ReadProcessMemory, which scans for some known patterns in lsasrv.dll in order to find sensitive structures, like the LogonSessionList variable (list of logon session identifiers).

Mimikatz uses a different pattern for every Windows build

Cortex XDR Prevention

Cortex XDR leverages our BTP engine and blocks the different techniques used by the Sekurlsa module by detֵֵecting suspicious scanning in lsasrv.dll memory. It detects the calls to the NtReadVirtualMemory function (called by ReadProcessMemory) using different offsets and buffer sizes. In addition, it detects reading memory attempts from unaligned base addresses in order to minimize false positives of different legitimate scanners.

Dumping LSASS memory

Another simple and useful attack technique for retrieving credentials from LSASS is dumping LSASS memory completely. An attacker can take the LSASS process dump and extract the credentials offline using tools like Mimikatz.

Legitimate Windows-signed Tools

There are various methods for dumping LSASS. An attacker can use known binaries signed by Microsoft, such as Task Manager, Process Explorer, ProcDump, comsvcs.dll, etc.

He will probably prefer to use tools that already exist on the victim’s machine, especially tools that also have legitimate usage, so their activity can be stealthy. On the other hand, it’s easy for the defender to create a detection for these tools, based on their command line, name convention of the dump file, etc. These tools dump LSASS memory using the same methods we will discuss next.

Cortex XDR Prevention

Cortex XDR detects the usage of these tools for dumping LSASS memory based on the static indicators discussed above, such as the command line arguments. It also detects them using behavioral detections based on the methods we will describe next.

Dump LSASS using MiniDumpWriteDump Function

An attacker can create a custom LSASS dumping tool using the documented API function
MiniDumpWriteDump. This function gets a handle to a process (LSASS in our case), reads its memory using ReadProcessMemory, which calls the undocumented API function NtReadVirtualMemory, in order to read the process memory and copy its content.

Cortex XDR Prevention

Cortex XDR detects the calls originated from MiniDumpWriteDump to NtReadVirtualMemory, which read from different offsets in the LSASS memory space. It also detects the creation of a dump file based on its magic signature. Our BTP engine correlates between these two events in order to detect the memory dump attempt.

Dump LSASS using PssCaptureSnapshot Function

Another API function used for dumping LSASS memory is PssCaptureSnapshot which captures a snapshot of a target process. One of the functions called by this function is the undocumented API NtCreateProcessEx which creates a non-executable fork of the process.

Stack trace of the PssCaptureSnapshot function

NTSTATUS NtCreateProcessEx(
[out] PHANDLE ProcessHandle,
[in] ACCESS_MASK DesiredAccess,
[in] POBJECT_ATTRIBUTES ObjectAttributes,
[in] HANDLE ParentProcess,
[in] ULONG Flags,
[in] HANDLE SectionHandle,
[in] HANDLE DebugPort,
[in] HANDLE ExceptionPort,
[in] BOOLEAN InJob
);

In order to create a snapshot, the underlying function PssNtCaptureSnapshot passes the LSASS handle as the ParentProcess argument, and zero as the SectionHandle argument-

Call to ZwCreateProcessEx inside PssNtCaptureSnapshot function

a2 (the fourth argument in the screenshot) is the second argument passed to PssNtCaptureSnapshot by PssCaptureSnapshot and is the handle to LSASS.

Then, in order to create the dump from the snapshot, the created process snapshot handle will be passed as an argument to the MiniDumpWriteDump function in order to create the dump file.

You can see an example of this implementation here.

Cortex XDR Prevention

The function NtCreateProcessEx is not commonly used by Windows operations, so the BTP engine in Cortex XDR considers its usage as an attempt for dumping LSASS using this technique, based on the ParentProcess and SectionHandle arguments.

Hiding LogonSessionList

In case an attacker found a creative way to bypass Cortex XDR and successfully dump LSASS memory, his next step will probably be retrieving the credentials offline.

The attacker can use various tools that extract credentials from a dump file offline, for example, the following Mimikatz commands-
sekurlsa::minidump <path to lsass dump>

sekurlsa::logonpasswords

Cortex XDR Protection

If the dump was taken from a machine with Cortex XDR installed, the credentials’ extraction will fail in most cases, due to another layer of defense. This layer is able to hide the LogonSessionList when it’s not in use. As soon as the machine starts, Cortex XDR agent injects code into LSASS process which searches for certain memory patterns and hooks several shared resources. Then, the injected code replaces the real data inside LogonSessionList with dummy data and restores the real entries only for legitimate access to this list.

 Mimikatz commands to retrieve credentials from a memory dump

As we can see, Mimikatz could not parse the dump file and extract the credentials.

Injecting and Reading Kerberos Tickets

“Pass the ticket” attack uses stolen Kerberos tickets to move laterally within the organization. This attack is composed of two steps - stealing the Kerberos tickets from one system and then injecting them into another system memory.

Injecting Kerberos Tickets

In the case of a Kerberos ticket cache manipulation, an attacker can use the Mimikatz command Kerberos::ptt <ticket file to inject> in order to inject Kerberos tickets.
This command calls LsaCallAuthenticationPackage with a flag message type named KerbSubmitTicketMessage-

Mimikatz calls LsaCallAuthenticationPackage with the message type KerbSubmitTicketMessage

LsaCallAuthenticationPackage is an RPC-based function that triggers an RPC server handler in LSASS. This function handles a variety of requests and routes each request to the proper handler based on the AuthenticationPackage and the ProtocolSubmitBuffer arguments.

Listing Kerberos Tickets

An attacker can also use Mimikatz in order to dump Kerberos tickets from the memory using the command Kerberos::list

Listing Kerberos ticket also calls the LsaCallAuthenticationPackage function. First, it uses this call with the message KerbQueryTicketCacheExMessage which returns information about all of the cached tickets for the specified user logon session-

Mimikatz calls LsaCallAuthenticationPackage with the message type KerbQueryTicketCacheExMessage

Then, it calls this function using KerbRetrieveEncodedTicketMessage message for every found ticket, in order to retrieve the specified ticket and save it locally-

Mimikatz calls LsaCallAuthenticationPackage with the message type KerbRetrieveEncodedTicketMessage

Cortex XDR Prevention

For this activity, Cortex XDR has an RPC tracking capability which allows us to track relevant events that were generated on the system and identify the source process that requested the RPC operation. It can detect ticket injection and ticket listing by observing the flag message type which was sent to the RPC server. The flag message type is part of the ProtocolSubmitBuffer parameter and LSASS reads it from the injector process by calling the NtReadVirtuaMemory function-

Stack trace of the RPC server handler function

The Behavioral Threat Protection (BTP) engine in Cortex XDR correlates between the RPC function context and the flag message type that was copied from the malicious process. Based on this advanced correlation, the agent can block this attack and any Kerberos tickets injections and listing.

DCSync

One of the most severe credential stealing attacks is DCSync. In this attack, an attacker pretends to be a DC and uses the Directory Replication Service Remote Protocol in order to extract NTLM hashes of users in the domain. One of the accounts he can extract using this protocol is the KRBTGT account, allowing the attacker to create golden tickets and as a result, compromise the domain completely.

To perform this attack, the attacker must have compromised an account with special rights allowing the domain replication. These permissions are granted by default to domain admins, administrators, enterprise admins and domain controllers groups.

The Mimikatz command performing this attack is-
lsadump::dcsync /domain:<domain name> /user:<domain user account>

As mentioned, in order to perform the replication, the attacker uses the RPC Directory Replication Service Remote Protocol and calls the DRSGetNcChanges RPC with the required arguments. We can see the RPC call in Mimikatz code-

Mimikatz calls DRSGetNcChanges RPC call

The third argument passed to the function is a pointer to the structure DRS_MSG_GETCHGREQ_V8 which is initialized before the call-

Mimikatz initializes DRS_MSG_GETCHGREQ_V8

We can see that the uFlags member contains the required operation we want to perform. In Mimikatz, for example, one of the operations is DRS_SYNC_URGENT which performs the requested replication immediately. This structure also contains the Invocation ID of the source DC (second member), which will be zero in Mimikatz execution since there is no real DC performing this request.

Cortex XDR Prevention

As mentioned in the Kerberos attacks, Cortex XDR has an RPC tracking capability and full visibility on the RPC calls arguments. Using this capability, we can examine the function arguments and prevent the DRSGetNcChanges RPC call. By observing the arguments sent to the RPC call, we can decide if this call is a legitimate one, initiated for innocent purposes, or if it is part of a malicious operation, with the purpose to steal credentials from the DC.

DPAPI Blobs

DATA Protection API (DPAPI) is used widely by Windows itself and by different Windows applications. It enables symmetric encryption and decryption of any kind of data using the functions CryptProtectData and CryptUnprotectData, respectively. Only a user with the same credentials as the user who called the CryptProtectData for encrypting the data is able to decrypt it using UCryptUnprotectData.

This mechanism is used widely by developers, as it is simple to use and doesn’t require them to understand cryptography.

In this section, we will discuss two methods to abuse this mechanism. The first one is decrypting Google Chrome passwords and cookies, and the second is retrieving the backup key from the DC, allowing the attacker to decrypt every Master Key in the domain. But first, let's go over some DPAPI background in order to fully understand the attacks.

DPAPI Background

A DPAPI blob is encrypted using a key called DPAPI Master Key. There are two types of Master Keys - user Master Keys and system Master Keys.

For this blog, we will focus on user Master Keys which are commonly stored in the path %APPDATA%\Microsoft\Protect\<user SID>. The user Master Keys are encrypted using the user password hash.

In order to decrypt a user-based DPAPI blob, we first need to extract the Master Key GUID from the blob’s metadata. Then, we can get the Master Key and decrypt it using the password hash of the logged-on user. Eventually, we can decrypt the blob using the decrypted Master Key.

There is a copy for every user Master Key which is encrypted with the domain Backup Key that is known only to the DC. The reason for saving a backup for all the Master Keys is for having the option to restore Master Keys that are inaccessible for the user due to password reset. In this case, the Master Keys are restored using the Backup Key and thus, access to the DPAPI blobs is still possible.

Extracting Chrome Passwords and Cookies

Chrome also uses the DPAPI mechanism for encrypting and decrypting saved websites' passwords and cookies. In the latest Chrome versions, passwords and cookies are encrypted using AES-256 encryption. The AES encryption key is encrypted using DPAPI and stored in %appdatalocal%\google\chrome\user data\local state.

If an attacker compromises a machine, he can extract Chrome’s passwords and cookies of the logged-on user, without knowing his password. For that, he can use the following Mimikatz command -

dpapi::chrome /in:"%localappdata%\Google\Chrome\User Data\Default\Login Data" /unprotect

Mimikatz uses the API function CryptUnprotectData in order to decrypt the AES key located in the “local state” file, and then it uses BCryptGenerateSymmetricKey in order to create a key object from the decrypted symmetric key-

Mimikatz calls BCryptGenerateSymetricKey function

Then, it iterates the database entries for Chrome’s passwords and cookies and decrypts them using the API function BCryptDecrypt-

Mimikatz calls BCryptDecrypt function

CryptUnprotectData is an RPC-based function that triggers an RPC server handler in dpapi.dll, loaded by LSASS.

Cortex XDR Prevention

Due to the RPC tracking capability of Cortex XDR, it can detect that the access to the Master Key file, used for decrypting the AES key, was done in the context of the RPC call CryptUnprotectData. In addition, it detects the access to the encrypted AES key saved in the “local state” file and to the “cookies” and “login data” files in order to decrypt the SQL entries and get Chrome’s cookies and passwords, respectively. Correlating all these events allows the BTP engine to detect attempts to extract Chrome passwords and cookies.

Extracting DPAPI Backup Key

If an attacker has domain admin permissions, he can steal the DC backup key and as a result, decrypt all the domain users’ master keys.

The Mimikatz module allowing to extract the domain backup key is lsadump::backupkeys.

This module first calls the API functions LsaOpenPolicy with POLICY_GET_PRIVATE_INFORMATION as the DesiredAccess argument, so it will be able to call the function LsaRetrievePrivateData after-

Mimikatz calls the API functions LsaOpenPolicy and LsaRetrievePrivateData

It calls the function with G$BCKUPKEY_PREFERRED as the KeyName argument, in order to get the remote backup key from the DC-

Mimikatz uses the G$BCKUPKEY_PREFERRED KeyName

LsaOpenPolicy and LsaRetrievePrivateData are also RPC-based functions.

Cortex XDR Prevention

In order to detect the domain backup key stealing, Cortex XDR uses its RPC tracking capabilities and its visibility on the RPC calls arguments. It detects triggering these two RPC functions and examines their arguments. By observing the arguments, we can decide if this activity is malicious or not.

Conclusion

Windows saves different password forms in different locations; As a result, many credential stealing techniques exist in the wild. In this blog post, we discussed some of the most common credential stealing techniques and explained how Cortex XDR protects its customers against these attacks.

In order to detect and prevent known and unknown stealing techniques, Cortex XDR has different capabilities and defense layers and is kept up to date with the latest threats. Please run the latest Cortex XDR agent and content version to remain protected.