In our offensive engagements we often utilise various credential-based attacks and in this defensive piece, we’re going to look at a one method of aiding the detection of Pass the Ticket (PtT) attacks.
As far as we’re aware detection methods seem to be few and far between, some requiring client-side scripts, others command execution. This could be a mammoth challenge in a medium – large organisation, so the approach we’ve taken in this article is based on anomaly detection.
There are caveats with this approach…
- It is assumed each user in the environment is assigned an individual device (shared devices quickly break the underlying logic)
- The logic is based on the logging of a Kerberos Service Ticket event (ID 4769), so if services aren’t requested from the account, events won’t be logged and therefore will not be evaluated by the query
Collection of the following events is recommended, with 4769 being of particular interest in this instance.
We’re using Microsoft Sentinel for this example, hence KQL will be used in the post.
Starting off we look for Kerberos service ticket requests.
SecurityEvent | where EventID == 4769
The TargetUserName and originating IpAddress will be extracted from the EventData field included within the 4769 event (shown below).
| parse EventData with * 'TargetUserName">' TargetUserName "<" * 'IpAddress">' IpAddress "<" *
We’re not interested in capturing computer objects.
| where TargetUserName !contains '$@' | where TargetUserName !endswith '$'
We then create a list of users based on unique IpAddress.
| summarize PotentialPtTEvents=make_set(TargetUserName) by IpAddress
The resulting query now resembles the following.
This logic can be expanded to capture events within a 60-minute (or any other preferred) time period.
| summarize PotentialPtTEvents=make_set(TargetUserName) by IpAddress, bin(TimeGenerated, 60min)
Finally, we check for buckets that include two or more unique usernames.
| where array_length(PotentialPtTEvents) >= 2 | sort by array_length(PotentialPtTEvents)
If we assume that a user jsmith is assigned a dedicated device, we should only see associated ticket events for this user from the IpAddress associated with this device.
The completed query and corresponding example results from our lab environment show two accounts (jsmith and smorrison) with activity associated with 192.168.2.6. This might be something we wish to dig into a little further to see if it’s expected or potentially malicious behaviour.
SecurityEvent | where EventID == 4769 | parse EventData with * 'TargetUserName">' TargetUserName "<" * 'IpAddress">' IpAddress "<" * | where TargetUserName !contains '$@' | where TargetUserName !endswith '$' | summarize PotentialPtTEvents=make_set(TargetUserName) by IpAddress, bin(TimeGenerated, 60min) | where array_length(PotentialPtTEvents) >= 2 | sort by array_length(PotentialPtTEvents)
There’s further work that could be done here, perhaps even cross-referencing these with user logon events to get a true record on who is authenticated to each device at any time.
If this has you interested, why not check out some of our other blue orientated posts below.
- Detecting AD CS subjectAltName (SAN) Abuse Using KQL
- KQL & LOLBAS Detection Ideas
- Logstash, Sentinel, Round Two…
- Logstash, Meet Sentinel… Sentinel, Meet Logstash!
- Detecting Pass-the-Ticket (PtT) Attacks
- PsExec. I thought we were friends
In.security was formed by Will and Owen, two cyber security specialists driven to help other organisations stay safe and secure against cyber threats and attacks. After having worked together since 2011 in several former companies, they each gained considerable experience in system/network administration, digital forensics, penetration testing plus training. Based in Cambridgeshire, but operating nationally, we can provide a range of services and training for businesses and individuals alike. Read more about our services below:
- Penetration testing
- Vulnerability assessments
- Build reviews
- Red team testing
- Phishing assessments
- Password auditing
- Cloud security auditing