Query Details
// =========================================================
// HUNT-02 | AD-ASREP-Roastable-Accounts-Audit-90d
// Description : Full audit of all accounts with
// DONT_REQ_PREAUTH (AS-REP Roastable) and
// historical AS-REP request patterns. Surfaces
// accounts that have never required pre-auth,
// and correlates with actual roasting attempts.
// Period : 90 days
// Use Case : Attack surface exposure assessment,
// DONT_REQ_PREAUTH hygiene review
// Tables : SecurityEvent
// =========================================================
let Period = 90d;
// All 4768 events with tostring(column_ifexists("PreAuthType", "")) = 0 (no pre-auth required)
let ASREPRequests = SecurityEvent
| where TimeGenerated > ago(Period)
| where EventID == 4768
| where tostring(column_ifexists("PreAuthType", "")) == "0"
| where TargetUserName !endswith "$"
| extend
IsOffHours = hourofday(TimeGenerated) < 8 or hourofday(TimeGenerated) >= 19
| summarize
TotalASREP = count(),
UniqueRequesters = dcount(IpAddress),
RequestingIPs = make_set(IpAddress, 20),
OffHoursRequests = countif(IsOffHours),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
RecentRequests = countif(TimeGenerated > ago(7d))
by RoastableAccount = TargetUserName,
AccountDomain = TargetDomainName;
// Normal 4768 events (with pre-auth, for baseline comparison)
let NormalTGTs = SecurityEvent
| where TimeGenerated > ago(Period)
| where EventID == 4768
| where tostring(column_ifexists("PreAuthType", "")) != "0"
| where TargetUserName !endswith "$"
| summarize NormalTGTCount = count()
by TargetUserName, TargetDomainName;
ASREPRequests
| join kind=leftouter (NormalTGTs) on
$left.RoastableAccount == $right.TargetUserName,
$left.AccountDomain == $right.TargetDomainName
| extend
OffHoursRatio = round(todouble(OffHoursRequests) / todouble(TotalASREP), 2),
// If this account ONLY appears with tostring(column_ifexists("PreAuthType", ""))=0 it's permanently set DONT_REQ_PREAUTH
OnlySeenASREP = isnull(NormalTGTCount) or NormalTGTCount == 0,
RiskScore = (TotalASREP * 3)
+ (UniqueRequesters * 5)
+ iff(OffHoursRequests > 0, 10, 0)
+ iff(RecentRequests > 0, 20, 0)
| extend
RiskLevel = case(
RiskScore >= 60, "Critical",
RiskScore >= 25, "High",
"Medium"
),
Recommendation = case(
OnlySeenASREP, "Set PreAuthentication required, rotate password immediately",
TotalASREP > 5, "Review why account lacks pre-authentication requirement",
"Monitor for further requests"
)
| project
RoastableAccount,
AccountDomain,
RiskLevel,
RiskScore,
TotalASREP,
UniqueRequesters,
OffHoursRatio,
OnlySeenASREP,
RecentRequests,
FirstSeen,
LastSeen,
Recommendation,
RequestingIPs
| order by RiskScore desc
This query is designed to identify and assess the risk of accounts in a network that are vulnerable to a specific type of attack known as AS-REP Roasting. Here's a simple breakdown of what the query does:
Objective: The query aims to audit accounts that do not require pre-authentication (DONT_REQ_PREAUTH), making them susceptible to AS-REP Roasting attacks. It analyzes these accounts over the past 90 days to identify potential security risks.
Data Source: It uses data from the SecurityEvent table, specifically focusing on events with an ID of 4768, which are related to Kerberos authentication requests.
AS-REP Requests: The query first filters for accounts that have made AS-REP requests without pre-authentication. It gathers various statistics about these requests, such as:
TotalASREP).UniqueRequesters).Comparison with Normal Requests: It then compares these accounts with those that have made normal authentication requests (with pre-authentication) to establish a baseline.
Risk Assessment: The query calculates a risk score for each account based on factors like the total number of AS-REP requests, the number of unique requesters, off-hours activity, and recent activity. It assigns a risk level (Critical, High, or Medium) based on this score.
Recommendations: For each account, it provides recommendations such as setting pre-authentication requirements or monitoring the account further.
Output: The final output includes details like the account name, domain, risk level, risk score, total AS-REP requests, unique requesters, off-hours request ratio, whether the account is only seen in AS-REP requests, recent request activity, first and last seen times, recommendations, and the IPs making requests.
The query helps in identifying potentially vulnerable accounts and provides actionable insights to improve security posture.

David Alonso
Released: March 24, 2026
Tables
Keywords
Operators