Pass-the-Hash Attack & Defense
A Pass-the-Hash (PtH) attack is a technique in which an attacker leverages a password hash, rather than the plaintext password, to authenticate to a system. Without needing to decrypt the hash, the attacker can gain access by exploiting the authentication protocol taking advantage of the fact that the password hash remains valid across sessions until the user changes their password.
To obtain password hashes, an attacker typically requires administrative or specific elevated privileges on the target machine. These hashes can be acquired through various methods, including:
Dumping the local Security Account Manager (SAM) database from a compromised host.
Extracting hashes from the NTDS database (
ntds.dit
) on a Domain Controller.Retrieving hashes directly from memory by accessing the
lsass.exe
process.
Lab Setup
Before we begin, ensure your home lab meets these requirements:
Domain Controller (DC): A Windows Server configured as an AD domain controller.
Client Machine: A Windows client joined to the domain.
Kali Linux Machine.
Ubuntu Machine (Elasticsearch & Kibana)
Account Configuration
We need to create accounts to simulate the scenario.
Domain Admin Account:
This account will be the target for PtH, as its hash can compromise the entire domain.
Local Admin Account on Client:
Enable Audit Policies
Account Logon: Audit Credential Validation
Captures NTLM authentication attempts, key for PtH detection.
Object Access: Audit Handle Manipulation
Detects Mimikatz accessing LSASS handles.
Logon/Logoff:
Audit Logon: Success, Failure
Tracks logins with stolen hashes (Event ID 4624).
Let's apply GPO:
The Attack - Pass the Hash
NTLM is a legacy Windows authentication protocol that uses a challenge-response mechanism for SSO without transmitting passwords. Despite known security flaws such as susceptibility to Pass-the-Hash attacks due to unsalted password hashes, it remains in use for compatibility with older systems, although Kerberos is the default in modern Active Directory environments.
LSASS is a Windows process (lsass.exe) responsible for handling security functions like authentication, password storage, and credential management. When a user (labadmin) logs into CLIENT01, their NTLM hash, a cryptographic representation of their password is stored in LSASS’s memory to facilitate single sign-on (SSO).
Why attackers target LSASS:
Cached Credentials: LSASS holds NTLM hashes for users who’ve logged in, especially admins like labadmin.
No Password Needed: Extracting the hash allows authentication without knowing the plaintext password.
Privilege Escalation: Admin hashes enable attacks like PtH to access other systems (e.g., DC01).
Think of LSASS as a vault holding keys (hashes). Only someone with a master key (admin rights) can open it. localadmin is our entry point.
Using the localadmin account, we will now initiate the attack simulation from the Windows Machine.
I encountered an error indicating a Windows error code: STATUS_PRIVILEGE_NOT_HELD
. This means the account's security token does not possess the SeDebugPrivilege, preventing Mimikatz from enabling it.
Let's open an elevated PowerShell session as an administrator and enter the credentials for the LocalAdmin account.
Privilege '20' (SeDebugPrivilege) was successfully granted. SeDebugPrivilege allows a process to debug or inspect other processes, including critical system processes like LSASS. This privilege is essential for tools like Mimikatz to access LSASS memory. Although the localadmin account has the necessary administrative rights to enable this privilege, it is not activated by default for security reasons.
Think of SeDebugPrivilege as a VIP pass to the LSASS vault. Normally, even admins don’t carry this pass unless they ask for it. Mimikatz uses localadmin’s authority to grab it.
Let's use Mimikatz to read LSASS memory and extract labadmin’s NTLM hash.
What happens here:
Mimikatz opens the LSASS process (lsass.exe) using SeDebugPrivilege.
It scans LSASS memory for credential structures.
It extracts hashes, passwords (if available), and other data.
sekurlsa::logonpasswords: This command targets the msv1_0 authentication package in LSASS, which stores NTLM credentials for logged-in users.
Now that we have obtained the hash for the 'labadmin' account, we can use a tool like psexec or wmixec to authenticate using the hash directly, rather than attempting to crack the password.
Let's use WMI, which is quieter and less likely to trigger alerts, ideal for stealth.
Evil-WinRM is a valuable tool for authenticating via the Pass-the-Hash technique using PowerShell Remoting. When SMB is blocked or administrative privileges are unavailable, it serves as an effective alternative protocol for connecting to the target machine.
There is another tool called Invoke-TheHash, a collection of PowerShell functions used to perform Pass-the-Hash attacks over WMI and SMB by leveraging .NET’s TCPClient
. It uses NTLMv2 authentication by passing an NTLM hash. While local administrator rights are not needed on the client side, the supplied user and hash must have administrative privileges on the target machine. For example, we use the user labadmin with the hash 10b363f919b7183ee89c253c628fc92b.
When using Invoke-TheHash, we can execute commands via SMB or WMI. To run commands on a target system, specify the following parameters:
Target: Hostname or IP address of the target machine
Username: Account used for authentication
Domain: Authentication domain
Hash: NTLM hash in either
LM:NTLM
orNTLM
formatCommand: Command to execute
I created an account named "john." Let's verify if it exists on the domain controller.
The attack can also be executed from the Kali machine.
Defense Strategy
Now that we’ve executed the attack, let’s explore how to defend against it by identifying detection rules and implementing appropriate mitigations.
Rule 1: Detect Mimikatz Execution
Effective detection rules should not rely solely on filenames like mimikatz.exe
since attackers can easily rename the binary. Instead, we should focus on behavioral patterns and tool artifacts.
Let's create a rule based on this and rerun the attack to verify if the alert is triggered.
This rule means:
At each execution (every 1 minute), the rule analyzes data collected over the last 5 minutes (the look-back time).
For example, if the rule runs at 5:21 PM, it will check data from 5:16 PM to 5:21 PM. Then, at 5:22 PM, it will check data from 5:17 PM to 5:22 PM, and so forth.
Let's save the rule, rerun the attack from the Kali machine, and review the alerts to confirm if the rule was triggered.
Why It Works:
Sysmon Event ID 1: Captures process creation, including the full command line, which reveals Mimikatz’s core functions (sekurlsa::logonpasswords for hash dumping, privilege::debug for enabling SeDebugPrivilege).
Behavioral Focus: sekurlsa is specific to Mimikatz’s credential extraction module, and privilege::debug is a prerequisite for LSASS access. These are consistent even if the binary is renamed (e.g., notmimikatz.exe).
False Positives: Very rare. Legitimate tools rarely use sekurlsa (unique to Mimikatz). privilege::debug might appear in custom scripts, but combining with sekurlsa narrows the scope.
Rule 2: LSASS Unauthorized Memory Access
In the second rule we'll filter for Sysmon Event ID 10, which logs memory access via OpenProcess(), specifically targeting cases where LSASS is accessed, a key indicator of credential dumping.
But we need to exclude legitimate system processes that may access LSASS during normal operation.
Also we can generate alerts only when the access flags are deemed suspicious. When a process attempts to access lsass.exe
, Sysmon logs the type of access requested in the winlog.event_data.GrantedAccess
field. This field contains a hexadecimal access mask that indicates the specific permissions granted, such as read memory, write memory, or full control.
Not all access to LSASS is dangerous. Some processes only read basic info (like Task Manager), while others may request full memory access, which is suspicious. So we can reduce noise by alerting only when the access level is unusually high.
Let's create a rule to detect suspicious access to lsass.exe
using GrantedAccess: 0x1010
, while excluding known legitimate processes.
Let's create a rule based on this and verify whether it triggers an alert.
Let's save the rule, re-execute the attack from the Kali machine, and review the generated alerts to verify whether the rule was successfully triggered.
This rule detects when a process tries to access lsass.exe
with GrantedAccess 0x1010
, which is often used by credential dumping tools like Mimikatz to read LSASS memory.
To avoid false positives, I excluded the trusted system processes known to access LSASS for legitimate reasons. By narrowing it down to suspicious processes using this access mask, the rule provides a precise and actionable alert for possible Pass-the-Hash or credential theft attempts.
Rule 3: Suspicious NTLM Authentication
This rule targets network logons (LogonType 3) that utilize the NTLM authentication package, a method commonly associated with Pass-the-Hash attacks where adversaries authenticate using stolen password hashes.
event.code: 4624
→ Logs successful logonsLogonType: 3
→ Indicates a network logon, not localAuthenticationPackageName: NTLM
→ NTLM is used instead of Kerberos, often a red flag in modern environmentsTargetUserName
→ filters for privileged accounts that attackers typically targethost.hostname: "WIN-1EIBKDJTJMK"
→ Narrowing detection to our domain controller, which shouldn’t normally receive NTLM logons for these accounts.
Q) Is it normal for users to authenticate using NTLM?
Yes, it can be normal in certain cases.
Legacy applications or services that don’t support Kerberos
Accessing file shares across workgroups or from non-domain devices
Cross-forest or cross-domain trust scenarios
When time synchronization fails, and Kerberos cannot issue a TGT
Local logon attempts (even if to a domain-joined machine)
Authentication from non-Windows systems or old clients (e.g., printers, Linux, embedded devices)
But it's still a Red Flag in these cases:
NTLM logon to a Domain Controller (DC)
DCs should primarily use Kerberos for authentication.
NTLM used on a DC, especially from unusual systems is suspicious.
If you see
AuthenticationPackageName: NTLM
combined withTargetUserName: Administrator
orsvc_*
accounts andLogonType: 3
, it's a big red flag.
NTLM isn't always malicious, but when combined with sensitive accounts, systems, or logon patterns, it becomes a strong signal of compromise, especially in Pass-the-Hash attacks.
NTLM over network logon (type 3) to a domain controller, especially for admin accounts, is not normal in modern, secure environments. Kerberos should be used for these authentications.
Let's proceed to create a rule based on this and verify whether it triggers an alert.
Let's save the rule, reinitiate the attack from the Kali machine, and review the generated alerts to verify that the rule was successfully triggered.
These rules are not the final production-ready versions. When deploying them in real-world environments, they need to be continuously tuned to minimize false positives as much as possible.
Other Mitigation
Restrict NTLM Authentication
NTLM is an old authentication protocol that allows attackers to use stolen hashes for PtH attacks without needing the password. Restricting NTLM means forcing Windows to use Kerberos (a safer protocol using tickets) or blocking NTLM entirely on DC01 and CLIENT01.
Why It Helps:
PtH relies on NTLM to pass hashes (e.g., from KALI to DC01). If NTLM is disabled or restricted, the stolen hash becomes useless, stopping the attack.
Kerberos requires a valid ticket from DC01, which attackers can’t generate with just a hash.
Our ELK rule monitors NTLM, so restricting it reduces alerts to only suspicious attempts, making detection easier.
Let's now create a domain policy to restrict the use of NTLM.
Let's assign a name to the policy, then right-click on it to edit its settings.
We need to set these policies:
Network security: Restrict NTLM: Incoming NTLM traffic:
It blocks NTLM logins to DC01 and CLIENT01.
Network security: Restrict NTLM: Outgoing NTLM traffic to remote servers:
It prevents CLIENT01 from using NTLM to other servers, reducing hash exposure.
Network security: Restrict NTLM: Audit Incoming NTLM Traffic:
It Logs NTLM attempts for monitoring in ELK (Event ID 4624/4625).
On DC01 and CLIENT01, let's force GPO update:
Let's attempt the Pass-the-Hash (PtH) attack again to verify whether we can still authenticate using the NTLM hash of the user labadmin.
This means:
The target rejected the NTLM authentication.
Most likely reason: we enabled NTLM restrictions on that host.
By restricting or disabling NTLM (via Group Policy or registry), the host no longer accepts NTLM logons, even if the attacker has a valid hash.
Enable Protected Users Group
The Protected Users group in Active Directory restricts how sensitive accounts authenticate, preventing their credentials from being cached in memory (LSASS) on machines like CLIENT01 and limiting NTLM usage.
Why It Helps:
In PtH attack, Mimikatz on CLIENT01 extracts labadmin’s hash from LSASS because labadmin logged in interactively. Protected Users ensures these credentials aren’t stored, stopping hash theft.
Forces Kerberos for labadmin, reducing NTLM exposure.
Applies to DC01 and CLIENT01, protecting labadmin domain-wide.
Let's add the labadmin account to Protected Users:
We need to log out of the labadmin account, if currently logged in, to clear the cached credentials from LSASS, and then log in again.
Let's execute Mimikatz once more to dump the hashes and verify if we can still retrieve the NTLM hash of the labadmin account.
Enable LSASS Protection (RunAsPPL)
LSASS (Local Security Authority Subsystem Service) is a Windows process that stores credentials, like labadmin’s NTLM hash, in memory on CLIENT01 and DC01. RunAsPPL (Run as Protected Process Light) locks down LSASS, requiring processes accessing it to have a special digital signature. This prevents unauthorized tools, like Mimikatz, from extracting hashes.
Why It Helps:
In PtH attack, we used localadmin (password: Local123!) to compromise CLIENT01, then run Mimikatz to steal labadmin’s NTLM hash from LSASS. RunAsPPL stops Mimikatz by blocking its access to LSASS memory, preventing the hash theft that enables PtH to DC01.
Works alongside other mitigations (e.g., Restrict NTLM, Protected Users) for layered defense.
Let's Backup Registry (Safety First) before doing this:
Let's save the file as RegistryBackup.reg. This will allow us to restore the registry in case any issues occur.
Next, we need to enable RunAsPPL by modifying the Windows Registry.
Right-click Lsa > New > DWORD (32-bit) Value.
This sets LSASS to run as a Protected Process Light, blocking unsigned access.
If an attacker gains local administrative privileges, they often try to use tools like Mimikatz to dump password hashes from LSASS. By enabling LSASS protection with RunAsPPL, it makes this much harder.
Next, we need to reboot the machine and then attempt to run Mimikatz to verify whether it can still extract hashes from the LSASS process.
Other Techniques for Attacking LSASS
Let's also discuss common techniques attackers use to target LSASS.
To extract credentials from LSASS, it's advisable to first generate a memory dump of the LSASS process. This allows for offline analysis on an attack host, offering greater flexibility and minimizing time on the target system. There are various methods to create a memory dump; we'll focus on techniques using built-in Windows tools.
With an interactive graphical session on the target, we can use Task Manager to generate a memory dump by following these steps:
The Task Manager method requires a GUI-based session, whereas using rundll32.exe
via the command line offers a faster and more flexible way to dump LSASS memory, especially when only shell access is available. However, this technique is commonly flagged as malicious by modern antivirus tools.
Before creating the dump file, we need to identify the process ID (PID) of lsass.exe.
After identifying the LSASS process PID, we can proceed to create the dump file.
rundll32
: A Windows tool to run functions inside DLL files (like small programs).C:\windows\system32\comsvcs.dll
: A Windows system file that has a built-in function to create memory backups.MiniDump
: The function insidecomsvcs.dll
that creates the backup.740
: The Process ID (PID) oflsass.exe
.C:\lsass.dmp
: Where the backup file will be saved (here, toC:\
).full
: Makes a complete backup (not just parts).
This command uses rundll32.exe
to invoke an exported function in comsvcs.dll
, which in turn calls MiniDumpWriteDump
to dump the LSASS process memory to C:\lsass.dmp
.
We need to transfer the file to our attack machine to extract potential credentials from LSASS memory.
Next, let's transfer the lsass.dmp
file to the attacker's machine.
Pypykatz, a Python-based Mimikatz implementation, allows us to extract credentials from a .dmp
file on a Linux attack host, eliminating the need to run Mimikatz directly on a Windows system.
LSASS stores credentials for active logon sessions; by dumping its memory, we captured a snapshot of those credentials. Let's analyze the dump with Pypykatz.
The command uses pypykatz to parse LSASS secrets from a minidump file located at /home/fares/lsass.dmp
and outputs the results.
Thank you for your time, I hope you find this helpful.
Last updated