This is the first in a 3-part blog series, that will be followed by a webinar February 28th.
Lateral movement techniques are one of the most common approaches attackers can use to infiltrate your network and obtain privileged access to your credentials and data. This has been seen recently with modern ransomware such as SamSam and Ryuk.
We’ve looked recently at how to detect pass-the-hash attacks using honeypots and in doing research into the most effective ways to detect this type of attack I came across several other interesting approaches. I figured it was worth putting them to the test and taking a closer look at how to detect pass-the-hash in action.
This post will walk you through how to detect pass-the-hash using native Windows event logs and some practical advice on how to implement these techniques. I won’t go into what pass-the-hash is here, but if you want to you can read about it and watch a video of it in action on our Attack Site.
To understand how to detect pass the hash we need to come up with a good scenario that will work reliably. Pass-the-Hash relies on NTLM authentication so we need a method that will leverage NTLM.
To reliably create NTLM authentication I used the Sqlcmd utility to connect to a Microsoft server by its IP address. This command will generate NTLM authentication to the SQL database:
Sqlcmd –S [IP ADDRESS]
So, before we look at how to detect pass-the-hash, let’s get a baseline of what events are normally generated when performing NTLM logon activity. To do that from my PC workstation, I’ll first launch a new command prompt as an administrative user by using their actual password:
Now in the new command prompt, I will use Sqlcmd to connect to a SQL host. For good measure I will run the SELECT SYSTEM_USER command to show the user I am authenticated as:
Great! That worked. Now let’s see what logs get generated.
On my local workstation I will see the following events.
4648 – A logon was attempted using explicit credentials.
4624 – An account was successfully logged on.
The 4624 event gets logged to show a Logon Type of 2, which means an Interactive logon. This aligns with the way I used runas where I typed in the credentials interactively.
4672 – Special privileges assigned to new logon.
Because the Franklin Bluth account I am using is an administrative account, 4672 gets logged to show what privileges are being assigned. This is a useful way to track administrative account activity.
On my SQL server I see the following events:
4624 – An account was successfully logged on.
On the SQL Server now you see a similar 4624 event, however this one has a Logon Type of 3 which is a Network logon.
More importantly, this shows the Authentication Package used was NTLM. This confirms that we are performing NTLM authentication using this approach.
We also will see a 4672 event because the user account we are leveraging is a privileged account.
On the domain controller I will see signs of the user Franklin Bluth being authenticated. In this case, I will see artifacts of both Kerberos and NTLM authentication. The Kerberos authentication happens first, which is the default authentication method for Active Directory. That will generate two events:
4768 – A Kerberos authentication ticket (TGT) was requested.
This shows a request for a TGT from the domain controller for our user we are impersonating.
4769 – A Kerberos service ticket was requested.
Once we have our TGT we request a TGS for the host we are impersonating the user on. With this, our user Franklin can now interact with the PC to launch the command prompt.
4776 – The computer attempted to validate the credentials for an account.
The 4776 event is specific to NTLM and will come last. This occurs when we execute the command using Sqlcmd which forces NTLM authentication.
Here is a summary of the logs we see when performing NTLM authentication without using pass-the-hash. This gives us a baseline for normal behavior.
Source Host | Target Host | Domain Controller |
4648 – A logon was attempted using explicit credentials. | 4624 – An account was successfully logged on. Logon Type 3, NTLM | 4768 – A Kerberos authentication ticket (TGT) was requested. |
4624 – An account was successfully logged on. Logon type 2 | 4672 – Special privileges assigned to new logon. | 4769 – A Kerberos service ticket was requested. |
4672 – Special privileges assigned to new logon. | 4776 – The computer attempted to validate the credentials for an account. |
Now, let’s take a look at what we see when we Pass-the-Hash.
To perform a pass-the-hash test, we are going to do the same exercise, only this time instead of using Runas to launch a process as a user we’re going to use Mimikatz and the pass-the-hash command.
I can easily get the NTLM hash for the user Franklin from memory with the mimikatz command of:
Now that I have that I will perform a pass-the-hash with the following command:
sekurlsa::logonpasswords
Now that I have that I will perform a pass-the-hash with the following command:
Sekurlsa::pth /user:Franklin.Bluth /ntlm:[ntlm] /domain:jefflab.local
A new command window will open and if I use the same Sqlcmd command to connect to the IP address of my SQL Server, you can see I am now authenticated there as Franklin Bluth:
So, let’s take a look at what events get generated after doing this pass-the-hash:
On my local workstation I will see events 4648, 4624, and 4672 the same as if I was doing legitimate NTLM authentication. However, there are a few key differences.
First, the 4624 event will have a Logon Type of 9. This is a NewCredential logon type and a very useful way to identify that a pass-the-hash took place. This was identified by a security researcher, and I reliably reproduced it in my lab.
Logon Type 9 is very rare. However, I was able to generate some false positives running applications that use impersonation. The main difference to key off of is the Logon Process will always be “seclogo” for pass-the-hash (from my tests), so you can filter on that to reduce false positive rates. You can see here I was able to get StealthAUDIT to generate the Logon Type 9 events but it uses the Advapi logon process.
Also, I noticed a difference in the 4672 event. Previously, this identified a privileged logon for my impersonated account Franklin Bluth. In this case, this registers for the user I am logged into my workstation as.
Outside of that, the logs on the SQL server are identical. On the domain controller the key difference is that you will not see Kerberos authentication. However, that isn’t a very reliable way to detect pass-the-hash because it can happen for lots of valid reasons like authentications originating from non-trusted domains.
So here is a summary of what we see when doing pass-the-hash.
Source Host | Target Host | Domain Controller |
4648 – A logon was attempted using explicit credentials. | 4624 – An account was successfully logged on. Logon Type 3, NTLM | 4776 – The computer attempted to validate the credentials for an account. |
4624 – An account was successfully logged on. (Logon type = 9 Logon Process = Seclogo) | 4672 – Special privileges assigned to new logon. | |
4672 – Special privileges assigned to new logon. (Logged on user, not impersonated user) |
To conclusively detect pass-the-hash I used Sysmon, which helps to monitor process access events. We used this in the honeypot detection as well so you can read up on how to set that up in that post.
With Sysmon in place when a pass-the-hash occurs you will see Event ID 10 showing access to the LSASS process from Mimikatz or your pass-the-hash tool of choice.
Now that we’ve looked at all the evidence, the simplest way to build detections for pass the hash is to look for:
With a custom event log filter you can easily see when these two things happen at the same exact time, you’ve got pass-the-hash activity on your network!
Here is a custom event filter you can use to surface that specific information.
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[System[(EventID='4624')]
and
EventData[Data[@Name='LogonType']='9']
and
EventData[Data[@Name='LogonProcessName']='seclogo']
and
EventData[Data[@Name='AuthenticationPackageName']='Negotiate']
]
</Select>
</Query>
<Query Id="0" Path="Microsoft-Windows-Sysmon/Operational">
<Select Path="Microsoft-Windows-Sysmon/Operational">
*[System[(EventID=10)]]
and
*[EventData[Data[@Name='GrantedAccess'] and (Data='0x1010' or Data='0x1038')]]
</Select>
</Query>
</QueryList>
Hopefully that helps to shine some light on how to detect pass-the-hash using event logs. This does require enabling logging on all endpoints. For simpler detections of pass-the-hash that use more advanced techniques you may want to look at a third-party threat detection product like StealthDEFEND.
In the next post on lateral movement, I will be doing a similar dive into pass-the-ticket and how to detect that.
In writing this post I used a lot of great research on the topic that can provide further information on how to understand and detect pass-the-hash:
Jeff Warren is Stealthbits’ General Manager of Products. Jeff has held multiple roles within the Technical Product Management group since joining the organization in 2010, initially building Stealthbits’ SharePoint management offerings before shifting focus to the organization’s Data Access Governance solution portfolio as a whole. Before joining Stealthbits, Jeff was a Software Engineer at Wall Street Network, a solutions provider specializing in GIS software and custom SharePoint development.
With deep knowledge and experience in technology, product and project management, Jeff and his teams are responsible for designing and delivering Stealthbits’ high quality, innovative solutions.
Jeff holds a Bachelor of Science degree in Information Systems from the University of Delaware.
Learn why Active Directory security should be a priority for your organization and ways to mitigate against a data breach with this free white paper!
Read more© 2021 Stealthbits Technologies, Inc.
Excellent post!
Absolutely brilliant. Good job
Thanks! Glad you found it useful, the credit goes to all of the great research done by the authors of the referenced articles, it was fun to put it all to the test.
Awesome, beutifully explained tricks with commands
Coorelating these events with WDATP Detections for Mimikatz and other pass-the-hash capable tools makes the detection even better. -We’ve combined the 4264 logontype=9 and 4672 events with the WDATP detections into a single PowerBI dashboard and it’s really useful for monitoring what shenanigans RedTeams are up to. (Helps see strange things like one RedTeam member passing a hash as another RedTeam member and then further passing other hashes as that 2nd user (for l0ls when the SOC responds and thinks RT member #2 did it)… -That view gets lost without the context on who’s running the hack tools and who’s not.
That’s really interesting, it’s great to hear these types of detections are working for you and adding the Defender events to complete the chain of events makes a lot of sense. Thanks for sharing!
Hi Jeff,
Thank you for an informative blog post. I am hoping you may have information on event ID 4624 on the target host where svchost is the process name and Object is seclogo
Hello! In my testing I saw 4624 events on the host from which the pass-the-hash attack is originating that have the seclogo Logon Process and the service host (svchost.exe) as the Process Name. I did not observe any on the target host. Are you seeing different? Let me know what additional information you are after and I’ll see if I can look into it.
Hi Jeff.
Excellent post. Thank you. I tested PTH attack and i examined target logs. I authenticated via RDP and i examined target logs again. I couldn’t see a difference between them. The only difference is that RDP creates more logs (4624,4672,etc.). I did not understand the trick that allowed us to detect the PTH attack? What is the trick? Can you help me?
You should see a 4624 event on the computer from where you initiated the remote desktop connection from with a logon type of 9. This is the NewCredential logon type, which indicates a process launched which will impersonate another user for outbound connections (you would see the same for runas with the /netonly flag). In addition you can add the Sysmon log I mention for extra accuracy. This is targeted towards pass-the-hash with Mimikatz.
Hi Jeff.
Thanks this post. How can i detect PTH attack from different sources? (KALI (Metasploit, pth-winexe,etc.))
Good question! I focused on testing with Mimikatz from Windows, but I want to do the same exercise for WMI Exec and SMB Exec which can be used from Metasploit and Kali in addition to the Mimikatz approach. I will try to get some research done there soon and post findings!
Hi Jeff Warren! Thank you for the detailed post. I have a question – If the authentication protocol used here is NTLM, why there you get kerberos ticket? Hope my question make sense.
Thank you!
Good observation! And I can see the confusion. That is in the original baseline behavior and actually related to the runas command I issue to launch a command prompt as an impersonated user. Once I run the Sqlcmd with the IP address target, that generates the 4776 NTLM logon event, so the Kerberos ticket could be ignored I only included it as it was part of the observed activity for my end to end test scenario comparing genuine impersonation with impersonation through Pass-the-Hash. Appreciate you reading and commenting! Let me know if there’s anything else you would want to discuss on the topic.
Thanks for the really helpful reading especially for a beginner like me from the security event lock prospective. Will it be possible if you can do a further write up or an extension on what are the other impacts areas from forensic point of view for this case? examples such as the other event logs powershell evt or prefetch etc. It will be perfect if you can do it in the manner you explained the above.