Detection Tools

KQL Helper

Search, filter, and reuse curated KQL queries for Microsoft Sentinel, Defender, and Entra ID investigations. Each query is paired with clear operational context so teams can understand when and why it should be used.

Showing 20 of 20 queries

Detect Suspicious PowerShell Execution

Sentinel

Identifies PowerShell commands with encoded payloads, download operations, and common living-off-the-land techniques. Detects when PowerShell is used for encoded commands, web downloads, or reflection-based execution that is characteristic of malware and ransomware loaders.

powershellexecutionlolbasmalware
DeviceProcessEvents
| where FileName == "powershell.exe" or FileName == "pwsh.exe"
| where ProcessCommandLine has_any (
    "Invoke-Expression", "IEX", "DownloadString", "WebClient",
    "FromBase64String", "EncodedCommand", "-enc", "Bypass", "Hidden"
)
| where ProcessCommandLine !has_any ("Get-Help", "Get-Module")
| extend CommandLength = strlen(ProcessCommandLine)
| where CommandLength > 100
| summarize
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp),
    Count = count(),
    Sample = take_any(ProcessCommandLine)
    by DeviceName, AccountName
| project FirstSeen, LastSeen, DeviceName, AccountName, Count, Sample

Detect Brute Force Sign-In Attempts

Azure AD

Identifies accounts with multiple failed sign-in attempts followed by a successful authentication, indicating potential credential stuffing or brute force attacks. Focuses on detecting the pattern of failure-then-success that distinguishes successful account compromise from failed attacks.

brute forceauthenticationcredentialsignin
let threshold = 10;
let timeWindow = 1h;
SigninLogs
| where TimeGenerated > ago(timeWindow)
| summarize
    FailedAttempts = countif(ResultType != "0"),
    SuccessfulLogins = countif(ResultType == "0"),
    IPAddresses = make_set(IPAddress),
    Locations = make_set(Location)
    by UserPrincipalName, bin(TimeGenerated, timeWindow)
| where FailedAttempts >= threshold and SuccessfulLogins > 0
| project UserPrincipalName, FailedAttempts, SuccessfulLogins, IPAddresses, Locations

Detect Kerberoasting Attacks

Sentinel

Detects Kerberoasting by identifying requests for Kerberos service tickets (TGS) for accounts with Service Principal Names using weak encryption types (RC4). Attackers use Kerberoasting to extract service account password hashes offline for cracking.

kerberoastingkerberoslateral movementactive directory
SecurityEvent
| where EventID == 4769
| where TicketEncryptionType == "0x17"
| where ServiceName !endswith "$"
| where ServiceName !in ("krbtgt")
| summarize
    Count = count(),
    Accounts = make_set(ServiceName),
    SourceIPs = make_set(IpAddress)
    by Computer, Account, bin(TimeGenerated, 1h)
| where Count > 2
| project TimeGenerated, Computer, Account, Count, Accounts, SourceIPs

Detect Impossible Travel Sign-Ins

Azure AD

Identifies sign-ins from geographically impossible locations within a short time window, indicating account compromise or VPN/proxy usage. Compares consecutive successful sign-ins from the same account for location changes that cannot be physically achieved.

impossible travelgeolocationauthenticationidentity
SigninLogs
| where ResultType == "0"
| where isnotempty(Location)
| sort by UserPrincipalName, TimeGenerated asc
| extend
    PrevLocation = prev(Location),
    PrevTime = prev(TimeGenerated),
    PrevUser = prev(UserPrincipalName)
| where UserPrincipalName == PrevUser
| where Location != PrevLocation
| extend TimeDiffHours = datetime_diff("hour", TimeGenerated, PrevTime)
| where TimeDiffHours <= 2 and TimeDiffHours >= 0
| project UserPrincipalName, TimeGenerated, Location, PrevLocation, TimeDiffHours

Detect Azure AD Privilege Escalation

Azure AD

Monitors for addition of accounts to privileged Azure AD roles including Global Administrator and Security Administrator. Privilege escalation is a critical step in most significant breaches and should be alerted on in near real-time.

privilege escalationglobal adminrbacidentity
AuditLogs
| where OperationName has "Add member to role"
| extend
    TargetUser = tostring(TargetResources[0].userPrincipalName),
    RoleAssigned = tostring(TargetResources[0].displayName),
    ModifiedBy = tostring(InitiatedBy.user.userPrincipalName)
| where RoleAssigned has_any (
    "Global Administrator", "Privileged Role Administrator",
    "Security Administrator", "Exchange Administrator",
    "Application Administrator", "Cloud Application Administrator"
)
| project TimeGenerated, TargetUser, RoleAssigned, ModifiedBy

Detect Large Outbound Data Transfers

Sentinel

Identifies anomalously large outbound data transfers that may indicate data exfiltration. Looks for egress traffic exceeding a configurable threshold. Particularly useful for detecting pre-ransomware double-extortion data staging.

exfiltrationdata theftnetworkegress
let threshold_bytes = 100 * 1024 * 1024;
CommonSecurityLog
| where DeviceAction !has "deny"
| where tolong(SentBytes) > threshold_bytes
| summarize
    TotalSentBytes = sum(tolong(SentBytes)),
    SessionCount = count(),
    DestinationIPs = make_set(DestinationIP)
    by SourceUserName, SourceIP, bin(TimeGenerated, 1h)
| extend TotalSentMB = round(TotalSentBytes / 1048576.0, 2)
| order by TotalSentMB desc

Detect Lateral Movement via SMB

Sentinel

Detects lateral movement through internal network file share access patterns. Identifies accounts accessing multiple internal systems via SMB in a short time frame, which is characteristic of worm-like spread or attacker lateral movement.

lateral movementSMBnetworkworm
DeviceNetworkEvents
| where RemotePort == 445
| where ActionType == "ConnectionSuccess"
| where not(RemoteIPType == "Private" and LocalIPType == "Public")
| summarize
    TargetCount = dcount(RemoteIP),
    Targets = make_set(RemoteIP, 20),
    FirstSeen = min(Timestamp)
    by DeviceName, InitiatingProcessAccountName, bin(Timestamp, 1h)
| where TargetCount >= 5
| project FirstSeen, DeviceName, InitiatingProcessAccountName, TargetCount, Targets

Detect Malware Execution Alerts

Defender

Aggregates Microsoft Defender malware detection alerts with correlated device and account context. Provides a consolidated view of malware activity across the estate with severity prioritisation.

malwareantivirusdefenderthreat
DeviceEvents
| where ActionType == "AntivirusDetection"
| extend
    ThreatName = tostring(AdditionalFields.ThreatName),
    WasRemediated = tostring(AdditionalFields.WasRemediated),
    ThreatFamily = tostring(AdditionalFields.ThreatName) split(":", 0)[0]
| summarize
    DetectionCount = count(),
    Devices = make_set(DeviceName),
    Users = make_set(InitiatingProcessAccountName)
    by ThreatName, ThreatFamily, WasRemediated
| order by DetectionCount desc

Detect RDP from Unusual Countries

Sentinel

Identifies Remote Desktop Protocol connections originating from countries not in the organisation's normal operating territory. RDP from unexpected geographies is a strong indicator of compromised credentials or unauthorised access attempts.

RDPremote accessgeolocationauthentication
let AllowedCountries = dynamic(["GB", "US", "DE", "FR", "NL"]);
SecurityEvent
| where EventID == 4624
| where LogonType == 10
| extend Country = tostring(todynamic(EventData).NetworkInformation)
| where isnotempty(IpAddress)
| join kind=leftouter (
    SigninLogs
    | extend Country2 = Location
    | project UserPrincipalName, Country2, IPAddress
) on $left.TargetUserName == $right.UserPrincipalName
| where Country2 !in (AllowedCountries)
| project TimeGenerated, TargetUserName, IpAddress, Country2, Computer

Detect Password Spray Attacks

Azure AD

Identifies password spray attacks by detecting a single IP address failing authentication against many different accounts within a short period. Unlike brute force which targets one account, spray attacks try one password across many accounts to avoid lockout policies.

password spraybrute forceauthenticationsignin
let lookback = 1h;
let threshold = 20;
SigninLogs
| where TimeGenerated > ago(lookback)
| where ResultType != "0"
| summarize
    FailedAccounts = dcount(UserPrincipalName),
    AccountList = make_set(UserPrincipalName, 10),
    ErrorCodes = make_set(ResultType)
    by IPAddress, bin(TimeGenerated, 10m)
| where FailedAccounts >= threshold
| project TimeGenerated, IPAddress, FailedAccounts, AccountList

Monitor Defender ASR Rule Violations

Defender

Tracks Attack Surface Reduction rule violations from Microsoft Defender, highlighting the most frequently triggered rules. ASR violations often indicate attempted abuse of common attack vectors including Office macro execution and credential theft.

ASRattack surface reductiondefenderoffice
DeviceEvents
| where ActionType startswith "AsrBlocked"
| extend
    RuleName = ActionType,
    ProcessPath = FolderPath
| summarize
    BlockCount = count(),
    AffectedDevices = dcount(DeviceName),
    SampleProcess = take_any(InitiatingProcessFileName)
    by RuleName, bin(Timestamp, 1d)
| order by BlockCount desc

Find Non-Compliant Intune Devices

Intune

Lists devices enrolled in Microsoft Intune that are currently non-compliant with security policies. Non-compliant devices represent a security risk and should be blocked from accessing corporate resources via Conditional Access.

intunecomplianceendpointMDM
IntuneDeviceComplianceOrg
| where ComplianceState == "noncompliant"
| summarize
    NonCompliantCount = count(),
    DeviceList = make_set(DeviceName, 20),
    Users = make_set(UPN, 20)
    by OS, PolicyName
| order by NonCompliantCount desc

Detect Anomalous Service Principal Activity

Azure AD

Identifies service principals performing actions outside their expected patterns — creating new credentials, assigning roles, or accessing unusual resources. Compromised service principals are high-impact since they often carry excessive permissions.

service principalmanaged identityapp registrationoauth
AuditLogs
| where OperationName has_any (
    "Add credentials to application",
    "Update application",
    "Add service principal credentials"
)
| extend
    SPName = tostring(TargetResources[0].displayName),
    ModifiedBy = tostring(InitiatedBy.app.displayName)
| where isnotempty(SPName)
| project TimeGenerated, OperationName, SPName, ModifiedBy, Result

Sentinel Incident Trend Analysis

Sentinel

Provides a daily trend of Sentinel incidents by severity over the past 30 days. Useful for operational dashboards, management reporting, and identifying spikes in alert volume that may indicate active threats or detection rule tuning opportunities.

incidenttrendmetricsoperations
SecurityIncident
| where TimeGenerated > ago(30d)
| summarize
    CriticalCount = countif(Severity == "High"),
    HighCount = countif(Severity == "Medium"),
    TotalCount = count()
    by bin(TimeGenerated, 1d)
| order by TimeGenerated asc
| project TimeGenerated, CriticalCount, HighCount, TotalCount

Find Devices with Vulnerable Software

Defender

Lists devices running software versions with known CVE vulnerabilities via Microsoft Defender Vulnerability Management. Prioritises by CVSS score and counts of affected devices to guide patching efforts.

vulnerabilityCVEpatchingCVSS
DeviceTvmSoftwareVulnerabilities
| where CvssScore >= 7.0
| summarize
    AffectedDeviceCount = dcount(DeviceName),
    ExposedDevices = make_set(DeviceName, 10)
    by SoftwareName, SoftwareVersion, CveId, CvssScore, VulnerabilitySeverityLevel
| order by CvssScore desc, AffectedDeviceCount desc
| project CveId, SoftwareName, SoftwareVersion, CvssScore, VulnerabilitySeverityLevel, AffectedDeviceCount

Alert on Watchlist IP Matches

Sentinel

Correlates incoming network connections against a Sentinel watchlist of known malicious IP addresses and threat intelligence indicators. Generates alerts when any traffic originates from or terminates at a watchlisted indicator.

watchlistthreat intelligenceTIIP reputation
let ThreatIntelIPs = _GetWatchlist("ThreatIntelIPs") | project SearchKey;
CommonSecurityLog
| where TimeGenerated > ago(1d)
| where DeviceAction !has "deny"
| where DestinationIP in (ThreatIntelIPs) or SourceIP in (ThreatIntelIPs)
| project
    TimeGenerated,
    SourceIP,
    DestinationIP,
    DeviceVendor,
    DeviceProduct,
    Activity
| order by TimeGenerated desc

Detect MFA Disabled for User Account

Azure AD

Monitors Azure AD audit logs for MFA being disabled on user accounts. Attackers who have access to an admin account may disable MFA to facilitate persistent access. This detection helps identify both malicious actions and accidental policy changes.

MFAmulti-factor authenticationconditional accessidentity
AuditLogs
| where OperationName has_any (
    "Disable Strong Authentication",
    "Update user",
    "Update StrongAuthenticationRequirement"
)
| extend
    TargetAccount = tostring(TargetResources[0].userPrincipalName),
    ChangedBy = tostring(InitiatedBy.user.userPrincipalName),
    PropertyChanged = tostring(TargetResources[0].modifiedProperties[0].displayName)
| where PropertyChanged has "StrongAuth" or OperationName has "Disable Strong"
| project TimeGenerated, TargetAccount, ChangedBy, PropertyChanged, OperationName

Detect Suspicious Azure Cloud Shell Usage

Sentinel

Identifies unusual Azure Cloud Shell sessions including sessions initiated from unfamiliar locations, sessions of unusual duration, or sessions running high-risk commands. Cloud Shell provides a fully privileged shell in Azure and abuse can lead to full tenant compromise.

cloud shellAzureprivileged accesscommand execution
AzureActivity
| where OperationNameValue has "Microsoft.Portal/cloudshell"
| where ActivityStatusValue == "Success"
| extend
    CallerIP = tostring(HTTPRequest.clientIpAddress),
    UserAgent = tostring(HTTPRequest.userAgent)
| summarize
    SessionCount = count(),
    UniqueIPs = dcount(CallerIP),
    IPList = make_set(CallerIP)
    by Caller, bin(TimeGenerated, 1d)
| where SessionCount > 10 or UniqueIPs > 2
| project TimeGenerated, Caller, SessionCount, UniqueIPs, IPList

Detect Public Access Enabled on Storage Accounts

Sentinel

Monitors Azure Policy and Activity Logs for storage accounts where public blob access has been enabled or where the security configuration has been weakened. Public storage accounts are a leading cause of Azure data breaches.

Azure storagedata exposuremisconfigurationCSPM
AzureActivity
| where OperationNameValue has "microsoft.storage/storageaccounts/write"
| where ActivityStatusValue == "Success"
| extend
    ResourceGroup = tostring(parse_json(Properties).resourceGroupName),
    AccountName = tostring(parse_json(Properties).resource)
| join kind=leftouter (
    AzureDiagnostics
    | where Category == "StorageWrite"
    | where StatusCode_d == 200
) on $left.ResourceId == $right.ResourceId
| where Properties has "allowBlobPublicAccess" and Properties has "true"
| project TimeGenerated, Caller, ResourceGroup, AccountName

Detect Disabled Sentinel Analytics Rules

Sentinel

Tracks when Microsoft Sentinel analytics rules are disabled. Disabling detection rules is a known attacker technique to reduce alert noise during an attack. Monitoring for this action can help detect insider threats and compromised admin accounts.

analytics rulesdetection gapinsider threatalert suppression
AzureActivity
| where OperationNameValue has "microsoft.securityinsights/alertrules/write"
| extend Properties_parsed = parse_json(Properties)
| where Properties_parsed.isDataAction == false
| where Properties_parsed has "disabled" and Properties_parsed has "true"
| project
    TimeGenerated,
    Caller,
    ResourceGroup,
    OperationNameValue,
    ActivityStatusValue