The ticket was legitimate. The request was legitimate. That is exactly why Kerberoasting is so hard to spot — the attacker never forges anything, never touches LSASS, never trips an AV signature. They simply ask the domain controller, politely, for a service ticket to a SQL server, take the ticket home, and crack it offline at their leisure. This investigation is about finding the moment they ask.
Kerberoasting targets service accounts whose passwords can be brute-forced offline. Because the ticket is encrypted with the service account's password hash (RC4), anyone who can request a ticket for that service principal name (SPN) gets a free, crackable copy of the hash. The signal is almost always Event ID 4769 — a Kerberos Service Ticket Operation — with RC4 (0x17) encryption, fired off in volume from a workstation that has no business requesting tickets for dozens of services.
The hypothesis
A compromised or malicious user account is requesting service tickets encrypted with the weak RC4 cipher for many different SPNs in a short window — the classic footprint of an offline-cracking (Kerberoasting) enumeration, most often driven by tools like Rubeus or Mimikatz.
Data you'll need
- Microsoft Sentinel / Defender:
SecurityEvent(EventID 4769) from domain controllers, plusDeviceProcessEventsfor Rubeus/Mimikatz process execution. - Splunk:
index=wineventlog(or your Windows Security event index) with EventCode 4769, or the Authentication data model. - Context data: SPN-to-service inventory (which service accounts should be ticketed, and by whom).
Hunting with KQL
RC4 is the tell. Modern Windows prefers AES, so a burst of RC4-encrypted TGS requests is worth an investigator's attention:
// Kerberoasting hunt: RC4 service-ticket requests (4769)
SecurityEvent
| where EventID == 4769
| where TicketEncryptionType == "0x17" // RC4-HMAC: the offline-crackable flavor
| where ServiceName !~ "krbtgt" // exclude the TGT service itself
| where AccountName !~ "krbtgt"
| summarize Requests = count(),
UniqueSPNs = dcount(ServiceName),
SPNs = make_set(ServiceName, 25),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by AccountName, Computer, IpAddress
| where Requests >= 10 and UniqueSPNs >= 3
| extend WindowMinutes = datetime_diff("minute", LastSeen, FirstSeen)
| project AccountName, Computer, IpAddress, Requests, UniqueSPNs, WindowMinutes, FirstSeen, LastSeen, SPNs
| order by Requests desc
What this does: it isolates Kerberos TGS requests (4769) encrypted with RC4, then rolls them up per requesting account and source machine. The thresholds do the discriminating work — a normal user touches one or two services over a day; an attacker tool like Rubeus kerberoast hammers dozens of SPNs in minutes. dcount(ServiceName) on the SPN field is the key discriminator between a user with one mapped drive and an attacker harvesting a full SPN list.
Example true-positive row:
| AccountName | j.doe |
|---|---|
| Computer | WS-1142 |
| IpAddress | 10.4.22.17 |
| Requests / UniqueSPNs | 47 requests to 31 distinct SPNs |
| WindowMinutes | 11 minutes |
| SPNs (sample) | MSSQLSvc/sql01.corp.local:1433, HTTP/webapp02.corp.local, CIFS/filesrv03.corp.local … |
A standard user account requesting 47 RC4 tickets across 31 services in 11 minutes from a workstation is not normal logon behavior — it is the harvest phase.
Field walkthrough: corroborating with the Rubeus process
Once the 4769 burst is identified, pivot to the source workstation in DeviceProcessEvents:
DeviceProcessEvents
| where DeviceName == "WS-1142"
| where TimeGenerated between (datetime("2026-09-26 02:00") .. datetime("2026-09-26 03:30"))
| where FileName in~ ("Rubeus.exe", "powershell.exe")
or ProcessCommandLine has_any ("kerberoast", "asktgt", "tgtdeleg", "Mimikatz")
| project TimeGenerated, FileName, ProcessCommandLine, InitiatingProcessFileName, AccountName
A hit here — e.g., Rubeus.exe kerberoast /outfile:hashes.txt — upgrades the finding from "suspicious ticket pattern" to a confirmed attack tool on the box.
Hunting with Splunk
The same logic against Windows Security events in Splunk:
index=wineventlog EventCode=4769 TicketEncryptionType=0x17 ServiceName!="krbtgt*"
| stats count as requests, dc(ServiceName) as unique_spns,
values(ServiceName) as spns, min(_time) as first, max(_time) as last
by AccountName, Computer, IpAddress
| where requests >= 10 AND unique_spns >= 3
| eval duration_min = round((last - first)/60, 1)
| sort - requests
| table AccountName, Computer, IpAddress, requests, unique_spns, duration_min, first, last, spns
What this does: filters to EventCode 4769 with RC4 encryption, groups by the requesting account and source, and applies the same volume-plus-diversity threshold. Watch for field-name drift — in some CIM-normalized sources the encryption field may appear as Ticket_Encryption_Type; normalize it with an alias before the where clause if needed.
Example hit: a single row for j.doe / WS-1142 showing requests=47, unique_spns=31, duration_min=11. In a small environment, expect this search to return only a handful of rows — review each one.
Validating the hit
- Verify the SPNs are real. Confirm the requested service names map to genuine domain SPNs (use
setspn -Qor your SPN inventory). Attackers sometimes request SPNs that don't exist — both patterns are worth flagging. - Check the workstation. Look at the 11-minute window on
WS-1142for process creation (4688): Rubeus, Mimikatz, renamed binaries, or PowerShell with-EncodedCommand. - Profile the account. Is
j.doean IT admin who might legitimately test tools, or a finance user whose credentials were stolen last week? Cross-reference recent 4624/4672 logons and any password-change activity. - Check whether the crack succeeded. Look for anomalous logons as the service accounts in the hours after the ticket burst — that is how you find out whether the attacker actually recovered a password.
Tuning out false positives
- Legacy applications that only speak RC4 will generate steady, low-volume 4769/0x17 traffic to one or two SPNs — the volume and SPN-diversity thresholds exclude them by design.
- Vulnerability scanners (Tenable, Qualys agents) sometimes enumerate SPNs aggressively; baseline your scanner service accounts and source hosts so you can exclude them with a watchlist.
- Administrative tooling that touches many services at once (backup agents, monitoring) can look bursty — allowlist by known account/host pairs rather than by encryption type alone.
- Non-Windows Kerberos clients defaulting to RC4 may inflate single-SPN counts; the unique-SPN threshold is what saves you here.
What to do next
If the hit validates, treat every ticketed service account as potentially compromised: rotate the service-account passwords immediately (long, random — 25+ characters), review SPN registrations for tampering, and force re-authentication of j.doe. Longer-term, disable RC4 for Kerberos where possible (AES is supported everywhere that matters in 2026), add this 4769/0x17 pattern as a standing detection rule, and consider alerting on SPN enumeration (rapid 4769 bursts) as its own analytic — because by the time the cracking finishes, the lateral movement has already started.

EmoticonEmoticon