Detection rules › Kusto
High severity malicious activity detected
Identifies high severity malicious activity in Azure Firewall IDPS logs.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Execution | |
| Credential Access | |
| Exfiltration |
Rule body
id: 504257c1-81e2-4609-8d40-b395e62f11c7
name: High severity malicious activity detected
description: |
Identifies high severity malicious activity in Azure Firewall IDPS logs.
severity: High
status: Available
requiredDataConnectors:
- connectorId: AzureFirewall
dataTypes:
- AZFWIdpsSignature
queryFrequency: 1h
queryPeriod: 24h
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- Exfiltration
- CredentialAccess
- CommandAndControl
- Execution
relevantTechniques:
- T1190
- T1041
- T1003
- T1204
query: |
let TimeWindow = 90d; // How far back to look
let HitThreshold = 10; // Minimum hits to alert per SourceIp + Category
let MinSeverity = 1; // Set Minimum Severity
let EnableCategoryFilter = true; // Filter 1: use CategoriesOfInterest
let EnableDescriptionFilter = false; // Filter 2: use DescriptionsOfInterest
let EnableActionFilter = false; // Filter 3: use MatchActions
let CategoriesOfInterest = dynamic([
"Targeted Malicious Activity was Detected",
"Exploit Kit Activity Detected",
"Domain Observed Used for C2 Detected",
"Successful Credential Theft Detected",
"Malware Command and Control Activity Detected",
"Executable code was detected",
"A Network Trojan was detected"
]);
let DescriptionsOfInterest = dynamic([
"targeted-activity",
"exploit-kit",
"domain-c2",
"credential-theft",
"command-and-control",
"shellcode-detect",
"trojan-activity"
]);
let MatchActions = dynamic(["Deny", "alert"]);
AZFWIdpsSignature
| where TimeGenerated >= ago(TimeWindow)
| where Severity >= MinSeverity
// Filter 1: Category filter (optional)
| where (EnableCategoryFilter == false) or (Category has_any (CategoriesOfInterest))
// Filter 2: Description filter (optional)
| where (EnableDescriptionFilter == false) or (Description has_any (DescriptionsOfInterest))
// Filter 3: Action filter (optional)
| where (EnableActionFilter == false) or (Action in~ (MatchActions))
| summarize
StartTime = min(TimeGenerated),
EndTime = max(TimeGenerated),
TotalHits = count(),
MaxSeverity = max(Severity),
Actions = make_set(Action, 5),
Signatures = make_set(SignatureId, 20),
Description = make_set(substring(tostring(Description), 0, 120), 3)
by SourceIp, ThreatCategory = Category
| where TotalHits >= HitThreshold
| project
StartTime,
EndTime,
SourceIp,
ThreatCategory,
TotalHits,
MaxSeverity,
Actions,
Signatures,
Description
| order by MaxSeverity desc, TotalHits desc
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SourceIp
version: 1.0.1
kind: Scheduled
Stages and Predicates
Parameters
let TimeWindow = 90d;
let HitThreshold = 10;
let MinSeverity = 1;
let EnableCategoryFilter = true;
let EnableDescriptionFilter = false;
let EnableActionFilter = false;
let MatchActions = dynamic(["Deny", "alert"]);
Let binding: CategoriesOfInterest
let CategoriesOfInterest = dynamic([
"Targeted Malicious Activity was Detected",
"Exploit Kit Activity Detected",
"Domain Observed Used for C2 Detected",
"Successful Credential Theft Detected",
"Malware Command and Control Activity Detected",
"Executable code was detected",
"A Network Trojan was detected"
]);
Let binding: DescriptionsOfInterest
let DescriptionsOfInterest = dynamic([
"targeted-activity",
"exploit-kit",
"domain-c2",
"credential-theft",
"command-and-control",
"shellcode-detect",
"trojan-activity"
]);
Stage 1: source
AZFWIdpsSignature
Stage 2: where
| where TimeGenerated >= ago(TimeWindow)
Stage 3: where
| where Severity >= MinSeverity
Stage 4: where
| where (EnableCategoryFilter == false) or (Category has_any (CategoriesOfInterest))
Stage 5: where
| where (EnableDescriptionFilter == false) or (Description has_any (DescriptionsOfInterest))
Stage 6: where
| where (EnableActionFilter == false) or (Action in~ (MatchActions))
Stage 7: summarize
| summarize
StartTime = min(TimeGenerated),
EndTime = max(TimeGenerated),
TotalHits = count(),
MaxSeverity = max(Severity),
Actions = make_set(Action, 5),
Signatures = make_set(SignatureId, 20),
Description = make_set(substring(tostring(Description), 0, 120), 3)
by SourceIp, ThreatCategory = Category
Stage 8: where
| where TotalHits >= HitThreshold
Stage 9: project
| project
StartTime,
EndTime,
SourceIp,
ThreatCategory,
TotalHits,
MaxSeverity,
Actions,
Signatures,
Description
Stage 10: sort
| order by MaxSeverity desc, TotalHits desc
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Action | in |
| field:"Action" kind:in |
Category | match |
| field:"Category" kind:match |
Description | match |
| field:"Description" kind:match |
Severity | ge |
| field:"Severity" kind:ge value:"1" |
TotalHits | ge |
| field:"TotalHits" kind:ge value:"10" |
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Actions | project |
Description | project |
EndTime | project |
MaxSeverity | project |
Signatures | project |
SourceIp | project |
StartTime | project |
ThreatCategory | project |
TotalHits | project |