PRACTITIONER GUIDE
Practitioner Guide12 min read

Microsoft Sentinel KQL Detection Rules: Writing Analytics Rules, MITRE ATT&CK Coverage, and Tuning False Positives

5 min
minimum query frequency for Scheduled analytics rules in Microsoft Sentinel; near-real-time detection for high-priority rules that should alert within minutes of a threat event
14 days
maximum query period (look-back window) for a single Scheduled analytics rule execution; longer detection windows require hunting queries or watchlist-based approaches instead
_GetWatchlist()
KQL function that retrieves a Sentinel watchlist in a query, enabling dynamic exclusion of known-good entities (service accounts, approved IPs, authorized admin workstations) from detection rule results
Entity mapping
Sentinel analytics rule configuration that maps KQL query columns to entity types (Account, Host, IP, URL) so that incidents automatically link to entity timelines, enabling one-click investigation of all alerts involving the same account or host

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

Deployed a Microsoft Sentinel instance with 15 connected data sources and enabled all 200 Microsoft-provided analytics rule templates on day one. Within 48 hours, the incident queue had over 800 open incidents — mostly true positives from a security perspective but operationally unmanageable in volume. The root cause was not bad rules; it was that 200 rules were enabled without entity-based alert grouping configured, so each individual authentication event that matched a brute force rule created its own incident. One active brute force attack against a single account generated 400 incidents in 24 hours.

Fixing this required three changes: enabling alert grouping on every authentication-based rule (grouping by Account entity, 24-hour window), creating watchlists for service accounts that legitimately generate high authentication volumes, and establishing a phased rule enablement process that enables rules in batches of 20 with 48 hours of incident volume monitoring between batches. After these changes, the incident queue stabilized at 15-25 incidents per day — a volume the team could investigate and close within the same day. The detection coverage was unchanged; only the incident management overhead was reduced.

Rule authoring: KQL patterns for the most common detection use cases

Effective KQL detection rules share a common structure: filter to relevant event types, normalize entity fields, apply the anomaly condition, and project the columns needed for entity mapping and alert context. The time window and aggregation choices are what distinguish rules that fire on genuine threats from rules that fire on normal operational noise — understanding how to calibrate summarize windows and count thresholds for your specific environment is the core skill of Sentinel detection engineering.

Use the union operator to correlate across Microsoft 365 and Azure AD log tables in a single rule

Sentinel's union operator combines rows from multiple log tables in a single query, enabling detections that span Microsoft 365 email logs, SharePoint audit logs, and Entra ID sign-in logs without running separate rules and correlating results manually. A detection for an account that receives a phishing email, clicks the link (recorded in email gateway logs), and then signs in from an unusual location within 30 minutes uses union EmailEvents, UrlClickEvents | join kind=inner SigninLogs on AccountUpn == UserPrincipalName to combine the three event streams and join on the user account field. The inner join returns only accounts that appear in all three event streams within the time window, creating a high-confidence phishing click followed by sign-in detection that is significantly more specific than any single-source detection.

Build time-series baseline rules using the ago() and bin() functions to detect deviations from normal patterns

Write baseline deviation detections by comparing current activity volume against historical activity for the same time of day and day of week, using bin(TimeGenerated, 1h) for hourly aggregation and the ago() function for the comparison period. A rule detecting unusual authentication volume for a service account compares the current hour's authentication count against the average for the same hour over the preceding 14 days: let baseline = SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == 'svc-account@domain.com' | summarize avg_count = avg(count_) by hourofday(TimeGenerated); let current = SigninLogs | where TimeGenerated > ago(1h) | where UserPrincipalName == 'svc-account@domain.com' | summarize count_ = count(); current | join baseline on hourofday = hourofday | where count_ > (avg_count * 3). This detects a 3x spike over the historical baseline for that specific hour, which accounts for legitimate time-of-day variation in authentication volume.

Operations: alert tuning and MITRE ATT&CK coverage tracking

Sentinel's detection engineering practice has two ongoing operational components: reducing false positive rates through watchlist management and entity mapping refinement, and tracking MITRE ATT&CK coverage to identify detection gaps. Both components require a structured process — ad hoc tuning based on individual analyst complaints produces a detection library with undocumented exceptions and unknown coverage gaps, while systematic tracking produces a defensible coverage matrix with documented rationale for every active rule and exception.

Review the Incidents table weekly for closed incidents marked False Positive and build watchlist entries from the patterns

Run a KQL query against the SecurityIncident table to identify false positive patterns in closed incidents: SecurityIncident | where TimeGenerated > ago(30d) | where Classification == 'FalsePositive' | summarize count() by AlertName, Entities | order by count_ desc. The high-count rows identify which analytics rules are generating the most false positives and which entity types are most commonly involved. For each high-count row, examine the entity values from the recent false positive incidents to identify the pattern: if 80% of false positives for a brute force rule involve the same three service accounts, create a watchlist entry for those accounts and add a _GetWatchlist() exclusion to the rule. Track false positive rate per rule as count of FalsePositive incidents divided by total incidents for that AlertName over the 30-day window — rules with false positive rates above 20% need immediate tuning before they train analysts to batch-close incidents without investigation.

Use Sentinel's MITRE ATT&CK blade to prioritize new rule development for high-risk technique gaps

Review the MITRE ATT&CK coverage blade in Sentinel quarterly to identify technique gaps and prioritize new rule development based on the threat techniques most relevant to your organization's risk profile. Export the coverage matrix and cross-reference it against recent threat intelligence reports identifying techniques actively used by threat actors targeting your sector — gaps in techniques that are currently being exploited in the wild by relevant threat groups are higher priority than gaps in techniques that are theoretical risks. For each identified high-priority gap, check whether a Sentinel Content Hub solution covers the technique before writing a custom rule: installing a solution with existing MITRE-mapped rules is faster than authoring custom KQL. Document the rationale for each gap decision in a detection engineering register: either a rule exists and is scheduled for deployment, or the gap is accepted with a documented compensating control.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

The bottom line

Microsoft Sentinel KQL analytics rules provide the detection layer for threats across Microsoft 365, Azure, and connected third-party sources, but the default template library covers only generic attack patterns. Write custom rules for organization-specific threat patterns using KQL join operators for multi-source correlations, union for cross-table detections, and the ago()/bin() pattern for baseline deviation detection. Configure entity mapping on every rule to enable one-click incident investigation via entity timelines. Use _GetWatchlist() exclusions for known-good entities rather than hardcoding exceptions in rule conditions, enabling exception management without rule review cycles. Configure alert grouping by entity on all authentication and network-based rules to prevent incident flooding from high-volume detections. Review the MITRE ATT&CK coverage blade quarterly to track detection gaps and prioritize new rule development against the techniques most relevant to your threat model.

Frequently asked questions

How do I write a KQL analytics rule to detect brute force login attempts?

Write a Scheduled analytics rule that counts failed login events per account within a time window and fires when the count exceeds a threshold. The KQL query: SigninLogs | where TimeGenerated > ago(1h) | where ResultType != 0 | summarize FailedAttempts = count(), IPs = make_set(IPAddress) by UserPrincipalName | where FailedAttempts > 10 | project UserPrincipalName, FailedAttempts, IPs. In the analytics rule configuration, set Query frequency to 1 hour, Query period to 1 hour, Alert threshold to Is greater than 0 (one result triggers an alert since the WHERE clause already applies the 10-attempt threshold). Map the UserPrincipalName column to the Account entity type so that the generated incident links directly to the user's entity timeline. Set MITRE ATT&CK tactic to Credential Access and technique to T1110.001 (Brute Force: Password Guessing). Add an alert grouping rule to group alerts by the Account entity so that repeated brute force attempts against the same account create one incident with updated alert counts rather than hundreds of separate incidents.

How do I use KQL joins to detect multi-source threat patterns in Sentinel?

Use KQL join operators to correlate events across different log tables and detect threats that span multiple data sources, which is Sentinel's primary advantage over single-source SIEM detections. A detection that identifies accounts performing Azure resource enumeration (in AzureActivity) immediately followed by a suspicious sign-in from an unusual location (in SigninLogs) joins the two tables on the UserPrincipalName field: let enumeration = AzureActivity | where TimeGenerated > ago(1h) | where OperationNameValue contains 'Microsoft.Resources/subscriptions/read' | summarize count() by Caller, bin(TimeGenerated, 5m) | where count_ > 20; let suspicious_signin = SigninLogs | where TimeGenerated > ago(1h) | where RiskLevelDuringSignIn in ('high', 'medium') | project UserPrincipalName, IPAddress, Location; enumeration | join kind=inner suspicious_signin on $left.Caller == $right.UserPrincipalName. The inner join returns only accounts that appear in both result sets — reconnaissance activity combined with a suspicious sign-in — a higher-confidence indicator than either signal alone. Set the analytics rule alert threshold to Is greater than 0 and the severity to High.

How do I use Sentinel watchlists to reduce false positives in detection rules?

Create Sentinel watchlists containing known-good entities and reference them in KQL detection rules using the _GetWatchlist() function to exclude false positive sources from rule results. Create a watchlist named trusted-service-accounts containing the UPN and display name of all service accounts that legitimately generate large authentication volumes, then reference it in any authentication-based detection: SigninLogs | where UserPrincipalName !in ( (_GetWatchlist('trusted-service-accounts') | project UPN) ) | <rest of detection logic>. Create a watchlist named approved-admin-ips containing the IP addresses of jump hosts, VPN egress IPs, and administrative network ranges, then reference it in network-based detections: AzureActivity | where CallerIpAddress !in ( (_GetWatchlist('approved-admin-ips') | project IPAddress) ). Watchlists are maintained in the Sentinel portal and can be updated without modifying the KQL rule — adding a new VPN IP or approved service account to the watchlist takes effect on the next rule execution without a rule change review cycle. This separation of exception data from detection logic is the Sentinel equivalent of Falco's list/macro pattern.

How do I map Sentinel analytics rules to MITRE ATT&CK and measure coverage?

Map Sentinel analytics rules to MITRE ATT&CK by configuring the Tactics and Techniques fields in each analytics rule with the relevant ATT&CK identifiers, then use the Sentinel MITRE ATT&CK blade to visualize coverage across all enabled rules. In the analytics rule editor, the Tactics section shows all 14 ATT&CK tactics as checkboxes — select all applicable tactics, then expand each selected tactic to select specific technique IDs (T1110, T1078, T1133, etc.). After mapping all enabled rules, navigate to Threat management > MITRE ATT&CK in the Sentinel portal to see a coverage matrix showing which techniques have active detections (green) versus gaps (grey). Techniques with gaps in the matrix are attack paths currently undetected by your Sentinel rules — they are the priority candidates for new custom rule development. Export the coverage matrix to a CSV for compliance reporting and track coverage percentage over time as new rules are added. The Microsoft Sentinel Content Hub solutions automatically include MITRE ATT&CK mappings for all included detection rules, so deploying a content hub solution like the Microsoft Entra ID solution also increases the coverage matrix automatically.

How do I configure alert grouping to prevent incident flooding from high-volume rules?

Configure alert grouping in Sentinel analytics rules to group multiple matching alerts into a single incident during a configurable time window rather than creating one incident per alert trigger. In the analytics rule configuration under Incident settings, enable alert grouping and set the grouping period (typically 5 minutes to 24 hours depending on the rule's detection pattern). Choose the grouping key: Group all alerts into one incident (any alert from this rule in the window creates one incident, subsequent alerts update the existing incident), Group alerts that share entity values into the same incident (alerts involving the same account, host, or IP are grouped together — this is the most useful option for entity-centric detections), or Group alerts if all entities match (strict grouping only for identical entity combinations). For a brute force detection rule, group by Account entity so that all brute force alerts against the same user account create one incident with a growing alert count, enabling analysts to see the full scope of an attack on one account in a single incident rather than dozens of incidents from the same 24-hour window.

How do I test a KQL detection rule before enabling it in production?

Test Sentinel KQL detection rules before enabling them by using the View query results button in the analytics rule editor, which runs the query against live Sentinel data in the current 14-day look-back period and shows how many results the query returns. Review the sample results to verify the query is returning the expected columns and data types that will be used for entity mapping and alert grouping. For rules that should fire on specific known events (like a test brute force attack or a known-good account being excluded by a watchlist), run the query with the time range adjusted to include the known-test-event time period and verify it appears in results or is excluded as expected. Before enabling a high-volume rule in production, run it with Alert threshold: Is greater than 99999 (which will never trigger an alert) for 48 hours while monitoring the query result counts manually — a rule returning hundreds of results per hour needs additional filtering before it is safe to enable at normal thresholds. Use the Alert simulation feature in the rule editor to generate a sample incident with test data so you can verify entity mapping, MITRE ATT&CK display, and incident severity appear correctly in the Incidents blade.

How do I deploy detection rules from the Sentinel Content Hub at scale?

Deploy detection rules from the Sentinel Content Hub by installing content solutions that package relevant data connectors, analytics rules, workbooks, and hunting queries for specific data sources or threat domains. Navigate to Content hub in Sentinel, search for a solution relevant to your connected data sources (Microsoft Entra ID, Microsoft Defender for Endpoint, Amazon Web Services, Palo Alto Networks, etc.) and click Install. After installation, navigate to Analytics > Rule templates to see the newly available rules in a disabled state. Review each rule's description, required data sources (verify the required table has ingested data in the last 24 hours before enabling), and MITRE ATT&CK mapping. Enable rules selectively based on the data sources you have connected and your organization's threat model — do not enable all 200+ templates at once, as many will produce false positives or no results without their required data source. Start with the high-severity rules for the data sources you actively monitor, verify they produce meaningful results after 48 hours, then progressively enable medium-severity rules with alert grouping configured.

Sources & references

  1. Microsoft Sentinel Analytics Rules
  2. Sentinel KQL Reference
  3. Sentinel MITRE ATT&CK Coverage
  4. Sentinel Content Hub

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.