The hypothesis is that the detection rule identifies unusual activity patterns in Azure Sentinel that may indicate adversarial behavior such as data exfiltration or lateral movement. SOC teams should proactively hunt for these anomalies to uncover potential threats that traditional detection methods may have missed.
KQL Query
// You can leave out Anomalies that are already monitored through other Analytics Rules
//let _MonitoredRules = dynamic(["TestAlertName"]);
let query_frequency = 1h;
let query_lookback = 3d;
Anomalies
| where TimeGenerated > ago(query_frequency)
//| where not(RuleName has_any (_MonitoredRules))
| join kind = leftanti (
Anomalies
| where TimeGenerated between (ago(query_frequency + query_lookback)..ago(query_frequency))
| distinct RuleName
) on RuleName
| extend Name = tostring(split(UserPrincipalName, "@")[0]), UPNSuffix = tostring(split(UserPrincipalName, "@")[1])
id: d0255b5f-2a3c-4112-8744-e6757af3283a
name: Unusual Anomaly
description: |
'Anomaly Rules generate events in the Anomalies table. This scheduled rule tries to detect Anomalies that are not usual, they could be a type of Anomaly that has recently been activated, or an infrequent type. The detected Anomaly should be reviewed, if it is relevant enough, eventually a separate scheduled Analytics Rule could be created specifically for that Anomaly Type, so an alert and/or incident is generated everytime that type of Anomaly happens.'
severity: Medium
requiredDataConnectors: []
queryFrequency: 1h
queryPeriod: 4d
triggerOperator: gt
triggerThreshold: 0
tactics: []
techniques: []
query: |
// You can leave out Anomalies that are already monitored through other Analytics Rules
//let _MonitoredRules = dynamic(["TestAlertName"]);
let query_frequency = 1h;
let query_lookback = 3d;
Anomalies
| where TimeGenerated > ago(query_frequency)
//| where not(RuleName has_any (_MonitoredRules))
| join kind = leftanti (
Anomalies
| where TimeGenerated between (ago(query_frequency + query_lookback)..ago(query_frequency))
| distinct RuleName
) on RuleName
| extend Name = tostring(split(UserPrincipalName, "@")[0]), UPNSuffix = tostring(split(UserPrincipalName, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: UserPrincipalName
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: Unusual Anomaly - {{RuleName}}
alertTacticsColumnName: Tactics
alertDynamicProperties:
- alertProperty: Techniques
value: Techniques
version: 1.0.3
kind: Scheduled
Scenario: A scheduled job for log rotation is generating a high volume of anomaly events due to frequent log file creation and deletion.
Filter/Exclusion: Exclude events where the source is the log rotation tool (e.g., logrotate or rsyslog), or filter by process name like logrotate or rsyslogd.
Scenario: A system administrator is manually reviewing logs using a tool like splunk or ELK Stack, which triggers anomaly detection due to increased query activity.
Filter/Exclusion: Exclude events where the user is a known admin (e.g., user = admin), or filter by the source IP of the admin console.
Scenario: A backup job using Veeam or Commvault is causing temporary spikes in system resource usage, which is flagged as an anomaly.
Filter/Exclusion: Exclude events associated with backup processes (e.g., process_name = VeeamBackup or process_name = Commvault).
Scenario: A security tool like CrowdStrike or Microsoft Defender is generating false positives during a signature update or scan.
Filter/Exclusion: Exclude events related to signature updates or scheduled scans (e.g., event_type = signature_update or task_name = Defender_Scan).
Scenario: A DevOps team is running CI/CD pipelines using Jenkins or GitLab CI, which temporarily increases system activity and triggers anomaly alerts.
Filter/Exclusion: Exclude events where the source is a CI/CD tool (e.g., process_name = jenkins or job_name = GitLab_CI).