Are We Being Kerberoasted? A Four-Hour Hunt
A CISO asks whether the estate is being kerberoasted. You have 45 days of Windows Security events from 6 domain controllers totalling about 90 million events per day, plus Sysmon from 400 servers. Splunk ES has Authentication and Endpoint accelerated for 30 days but no further. EDR covers only 60% of endpoints. The search head cluster has 3 members, 12 concurrent searches each, and current utilisation is 85% with business-critical dashboards in use until 18:00. You have four hours of hunt time and no approval to degrade production search performance. The accelerated Authentication model does not include ticket encryption type as a field.
1. State the hypothesis in falsifiable form and justify how you scope the hunt given the data and capacity constraints.
Read the worked answer
Hypothesis: An actor holding any valid domain user credential has requested RC4-encrypted (0x17) TGS tickets for many distinct service principal names from a single account or host within a short window, consistent with offline cracking of service account passwords.
Falsifiable because it predicts a specific event shape: 4769 events, TicketEncryptionType 0x17, a high count of distinct ServiceNames per source, within a bounded time window, from sources that are not the documented SPN-scanning tooling. If no source exceeds the distinct-SPN baseline, the hypothesis is rejected for this dataset (which is a legitimate result, not a failure).
Scoping decisions:
- Do not run unaccelerated searches across 45 days. The hard ceiling is the 30-day accelerated Authentication range; hunting the 15 unaccelerated days would require raw scans of ~1.35 billion events at 85% search head utilisation.
- Use
tstats summariesonly=tfor candidate generation only - it is cheap and returns the small set of (src, user, hour) tuples with high 4769 counts. - Because ticket encryption type is not in the accelerated model, do the field-level filtering in raw search scoped to
index=wineventlog sourcetype=WinEventLog:Security EventCode=4769 src=<candidate list>over a narrow window. Candidate generation plus targeted enrichment keeps the expensive search to thousands of events, not billions. - Accept and document the 15-day blind spot rather than implying full coverage.
2. Give the detection logic, and explain how you would separate kerberoasting from legitimate RC4 use and SPN inventory tooling.
Read the worked answer
Candidate generation (accelerated, cheap):
| tstats summariesonly=t count from datamodel=Authentication.Authentication
where Authentication.signature_id=4769 earliest=-30d@d
by _time span=1h, Authentication.src, Authentication.user, Authentication.dest
| stats dc(Authentication.dest) as dc_dest sum(count) as tickets by Authentication.src, Authentication.user
| where tickets > 50
Then enrich only those sources with a raw search for TicketEncryptionType 0x17 and compute distinct SPNs and their host/service suffix distribution. Rank by distinct SPN count per user per hour; kerberoasting typically shows dozens of unrelated SPNs (SQL, IIS, backup) from one user in minutes.
Separating benign from malicious:
- Baseline first. Compute the same distinct-SPN-per-hour metric over the previous 3 weeks per account. A service account that always requests 40 SPNs per hour is not evidence; the analyst workstation that suddenly requests 300 is.
- Encryption type is the discriminator. 0x17 (RC4) for accounts that support AES is the classic indicator; note that some applications genuinely negotiate RC4 and some service accounts have no AES support, so check whether the target accounts are AES-capable.
- Account context. Machine accounts ending in
$and documented inventory/vulnerability scanners produce large SPN sets legitimately - exclude by identity lookup category, not by ad-hoc name lists. - Follow-on behaviour. A crack succeeds later: look for 4624 Type 3 to the SPN host, or LSASS access (Sysmon EID 10) on the requesting host, in the following hours. Absence of follow-on weakens a single suspicious burst.
3. One account on a build server requested 214 distinct SPNs in 11 minutes with RC4. What do you deliver, and how does this become a durable detection rather than a one-off hunt?
Read the worked answer
Deliverable: a hunt report with the hypothesis, the coverage limits (30 of 45 days, 60% EDR coverage), the query, the baseline comparison, the named account and host, and an explicit recommendation - not a raw result dump. Recommendation: confirm with the build team whether the SPN sweep matches a known tool run in that window; if not, treat the service account as compromised, rotate it, and check the requested SPNs' hosts for subsequent 4624 Type 3.
Making it durable:
- Convert to a correlation search that scores rather than alerts: risk_score proportional to distinct SPN count,
risk_object= the requesting account (risk_object_type=user) and the source host (risk_object_type=system), with a modest score so a single burst is corroborated by other rules rather than paging on its own. - Keep the exclusion logic data-driven (identity lookup categories for scanners and service accounts) so the rule does not need editing every time a tool changes.
- Record the baseline in the rule, not in the analyst's head: compare against a lookup or a
streamstats/eventstatsbaseline so the threshold survives seasonality. - Feed the final findings back into asset and identity data - the build server's missing business unit and the service account's missing owner are why this took manual work.
- Log the 15-day blind spot as an onboarding request; a hunt that ends with a coverage gap unchanged has only half succeeded.