Microsoft Defender's Advanced Hunting is genuinely useful — possibly the most useful thing in the portal that does not have a flashy dashboard. We are currently building our own on-premises log management stack, but before going all-in we wanted to see how far we could get with Advanced Hunting KQL queries against the Defender data we already have, without committing to a full Microsoft Sentinel workspace. The short answer: surprisingly far.
Key Takeaways
- Advanced Hunting in Microsoft Defender XDR lets us run KQL queries against device, email, and identity telemetry without a Sentinel workspace.
- A short
summarizeoverDeviceLogonEventsis enough to surface noisy or misbehaving service accounts in seconds. - An
EmailEventsquery grouped bySenderFromDomainturns inbound threat telemetry into a concrete blocklist candidate list. - A
let-and-joinpattern betweenDeviceLogonEventsandDeviceNetworkEventscan hint at which human is behind a shared service-account logon. - None of this replaces a SIEM, but for spot checks, validation, and small investigations it is faster than firing up Sentinel.
Environment
- Microsoft 365 tenant with Microsoft Defender XDR (formerly Microsoft 365 Defender) — Advanced Hunting is part of the unified Defender portal.
- All users on Microsoft 365 E5, which includes Defender for Endpoint Plan 2 and Defender for Office 365 Plan 2.
- No Microsoft Sentinel workspace in use for this work — queries run inside Defender XDR directly.
- Tables referenced:
DeviceLogonEvents,DeviceNetworkEvents,EmailEvents.
The Problem
Like many teams, we are slowly moving toward a setup where the bulk of our log management runs on premises, on our own terms. The plan does not change — but the plan also takes a while to roll out. In the meantime, we still need to answer questions like "which user is hammering the directory with logons today?" or "which inbound sender domains are responsible for most of the spam getting filtered?" without spinning up a parallel Sentinel deployment.
Defender's Advanced Hunting fills that gap. It is a KQL query interface over the same data Microsoft uses to power its alerts, sitting right inside the Defender portal. Microsoft maintains a large library of pre-defined queries — useful as a starting point — and the full Advanced Hunting schema reference is on Microsoft Learn. But the queries we end up running over and over are short, narrow, and embarrassingly simple. The three below are the ones we have actually pinned and re-used.
The Solution
Step 1 — Find the noisiest accounts with DeviceLogonEvents
Occasionally we just want to know who is authenticating a lot. The usual reason is a service account that has decided to misbehave — a stuck loop, a misconfigured scheduled task, or an integration that lost its mind after a credential rotation. A short summarize on DeviceLogonEvents answers that in about two seconds:
DeviceLogonEvents
| summarize LogonCount = count() by AccountName
| top 10 by LogonCount
| render piechart
The output is a pie chart of the top 10 most active accounts in whatever time range is selected at the top of the page. If one slice eats half the chart, you have your answer. We tend to scope the time range to the last 24 hours by default — short enough to catch a runaway, long enough to spot a slow drip. Once an account stands out, the same query without the top and render lines and with a where AccountName == "..." filter gives a per-day breakdown to confirm the trend is real.
A couple of small caveats. DeviceLogonEvents only sees logon activity on devices onboarded to Defender for Endpoint. Sign-ins to cloud apps go to SigninLogs or AADSignInEventsBeta instead — different tables, different schema, same KQL. And render piechart is a presentation hint: it has no effect when the query runs from the API or as a scheduled detection, so do not rely on it for anything except the in-portal view. If you are wondering which underlying logon types these rows correspond to, our post on essential Windows event IDs for security monitoring covers the mapping in more detail.
Step 2 — Surface the worst inbound sender domains
This one started life in the Azure-Sentinel GitHub repository and we kept it because it tells us something useful we cannot easily see in the standard Defender for Office 365 reports. The point is to find sender domains whose inbound mail is mostly junk — malware, phish, or spam — so we can decide whether to block them at the connector instead of relying on the filter to catch every message.
EmailEvents
| where EmailDirection == "Inbound"
| where Timestamp > ago(30d)
| summarize TotalEmailCount = count(),
SpamEmailCount = countif(ThreatTypes has_any ("Malware", "Phish", "Spam")) by SenderFromDomain
| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount) * 100, 2))
| where SpamEmailCount != 0
| sort by SpamEmailCount desc
| project SenderFromDomain, SpamEmailCount, TotalEmailCount, Bad_Traffic_Percentage_Inbound
| top 100 by SpamEmailCount
Each row is a sender domain, the number of messages it sent us in the last 30 days, the number that tripped at least one threat type, and the resulting "bad traffic" percentage. Defender blocked most of those, of course — but a domain with a 98.5% block rate is still a domain we have no business accepting mail from. Once you have the list, it is straightforward to push the worst offenders into a tenant-wide block entry in Exchange Online Protection or your secure email gateway.
Two things to watch out for. First, countif with has_any counts a message once even if it carries more than one threat type — so the count is the number of threat-bearing messages, not the number of threats. Second, low-volume domains with one or two malicious messages will rocket to 100% bad traffic and crowd out the real signal. Sort by SpamEmailCount first and only consider Bad_Traffic_Percentage_Inbound meaningful on domains with a non-trivial sample.
Step 3 — Tie a service-account logon to a probable human user
This one is more situational, and we will say upfront: if service accounts are being used by humans for interactive sign-ins, that is the problem you should be fixing, not a query you should be writing. That said, when you inherit an environment and need to figure out who is using a shared account to log into a particular box, this pattern helps you correlate it back to a likely person. We are using it strictly for authorized internal attribution in environments we own.
The idea is to pull the most recent logons by a service-account-looking name on a device of interest, capture the remote IP they came from, and then join that back to DeviceNetworkEvents to see which actual user on the remote endpoint had network sessions from that IP:
let Logons =
DeviceLogonEvents
| where AccountName contains "..."
| where DeviceName contains "..."
| summarize LatestTimestamp = max(Timestamp)
by AccountName, DeviceName, RemoteIP;
Logons
| join kind=leftouter (
DeviceNetworkEvents
| summarize LatestSeen = max(Timestamp) by RemoteIP, DeviceName, InitiatingProcessAccountName
) on RemoteIP
Replace the two "..." placeholders with the service-account name fragment and the target device fragment. The leftouter join keeps the logon row even when no matching network event exists, which is useful — it tells us "we saw this account log in from IP X, but the remote side is not onboarded, so we cannot attribute it further." When a match does come back, InitiatingProcessAccountName on the network-event side is usually the breadcrumb you want: it is the user context under which the connecting process was running on the remote machine.
The right long-term fix is per-person service principals or managed identities, not better forensics on the symptom. Once you have the data to make that case to whoever owns the workflow, this query has done its job. Our write-up on SIEM correlation rules for real attacks covers the next step — turning patterns like this into scheduled detections rather than ad-hoc lookups.
Frequently Asked Questions
Do I need Microsoft Sentinel to run Advanced Hunting KQL queries?
No. Advanced Hunting runs inside the Microsoft Defender XDR portal against the data Defender already collects from endpoints, mailboxes, and identities. Sentinel adds a workspace, longer retention, and a broader correlation surface across non-Microsoft sources, but for the queries above you only need Defender XDR.
Which licenses do I need for DeviceLogonEvents and EmailEvents?
DeviceLogonEvents and DeviceNetworkEvents require Defender for Endpoint Plan 2. EmailEvents requires Defender for Office 365 Plan 2. Both ship with Microsoft 365 E5 and are available as standalone add-ons for lower SKUs.
How far back can I query in Advanced Hunting?
Advanced Hunting retains 30 days of data by default. Anything older needs to be exported to a Sentinel workspace, a Log Analytics workspace, or a downstream log store before it ages out. If you regularly need 90- or 180-day lookback, that is the cue to start streaming to Sentinel or to your own SIEM.
Can I save these queries and re-use them?
Yes. The Advanced Hunting page supports personal and shared saved queries. For team use, version-controlling them in a small internal repository alongside the rest of your detection content is preferable to relying solely on the portal — it makes them reviewable, diffable, and easier to migrate later.
Will render piechart work outside the Defender portal?
No. render directives are interpreted by the Advanced Hunting UI and ignored everywhere else. If you take a query out of the portal and run it via the API, Logic Apps, or a custom detection rule, drop the render line — it does not error, but it does nothing useful either.
Conclusion
Advanced Hunting is not going to replace a real SIEM, and it is not meant to. What it does well is give a small team a fast way to ask sharp questions about data we already pay for. The three queries above are nothing clever — a count, a group-by, and a join — but they answer questions that come up every week and that would otherwise sit in someone's "I should look into that" pile.
We will eventually move most of this to our on-premises stack, where the retention, cost model, and correlation are on our own terms. Until then, KQL inside Defender XDR is good enough for the day-to-day, and it is the rare Microsoft feature that does what it claims without a chain of licensing surprises.
Related Posts
- From Logs to Threats: SIEM Correlation Rules for Real Attacks — the natural next step once these ad-hoc queries graduate into scheduled detections.
- Essential Windows Event IDs for Security Monitoring — useful context for what
DeviceLogonEventsis actually surfacing under the hood. - Windows Security: Best Practices for Securing Windows Services — relevant if Step 3 reveals service accounts being used for interactive sign-ins.

0 comments:
Post a Comment