Detection rules › Kusto
Kusto rules: 04
App Gateway WAF - XSS Detection
#'Identifies a match for an XSS attack in the App Gateway WAF logs. The threshold value in the query can be changed as per your infrastructure's requirements. References: https://owasp.org/www-community/attacks/xss/'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Execution | |
| Execution |
Rule Body
id: 1c7ff502-2ad4-4970-9d29-9210c6753138
name: App Gateway WAF - XSS Detection
description: |
'Identifies a match for an XSS attack in the App Gateway WAF logs. The threshold value in the query can be changed as per your infrastructure's requirements.
References: https://owasp.org/www-community/attacks/xss/'
severity: High
status: Available
requiredDataConnectors:
- connectorId: WAF
dataTypes:
- AzureDiagnostics
queryFrequency: 6h
queryPeriod: 6h
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- Execution
relevantTechniques:
- T1189
- T1203
- T0853
tags:
- Cross Site Scripting
query: |
let Threshold = 3;
AGWFirewallLogs
| where Action == "Matched"
| where Message has "XSS"
| project TransactionId, Hostname, RequestUri, TimeGenerated, ClientIp, Message
| join kind = inner(
AGWFirewallLogs
| where Action == "Blocked"
| extend transactionId_g = tostring(TransactionId)) on TransactionId
| extend Uri = strcat(Hostname,RequestUri)
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), TransactionID = make_set(transactionId_g,100), Message = make_set(Message,100), Total_TransactionId = dcount(transactionId_g) by ClientIp, Uri, Action
| where Total_TransactionId >= Threshold
# The Threshold value above can be changed as per your infrastructure's requirement
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Uri
- entityType: IP
fieldMappings:
- identifier: Address
columnName: ClientIp
version: 1.0.2
kind: Scheduled
Stages and Predicates
Parameters
let Threshold = 3;
Stage 1: source
AGWFirewallLogs
Stage 2: where
| where Action == "Matched"
Stage 3: where
| where Message has "XSS"
Stage 4: project
| project TransactionId, Hostname, RequestUri, TimeGenerated, ClientIp, Message
Stage 5: join
| join kind = inner(
AGWFirewallLogs
| where Action == "Blocked"
| extend transactionId_g = tostring(TransactionId)) on TransactionId
Stage 6: extend
extend Uri
Stage 7: summarize
summarize EndTime, Message, StartTime, Total_TransactionId, TransactionID by ClientIp, Uri, Action
Stage 8: where
where Total_TransactionId >= 3
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Action | eq |
| field:"Action" kind:eq |
Message | match |
| field:"Message" kind:match value:"XSS" |
Total_TransactionId | ge |
| field:"Total_TransactionId" kind:ge value:"3" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Action | summarize |
ClientIp | summarize |
EndTime | summarize |
Message | summarize |
StartTime | summarize |
Total_TransactionId | summarize |
TransactionID | summarize |
Uri | summarize |
Brute Force Attack against GitHub Account
#Attackers who are trying to guess your users' passwords or use brute-force methods to get in. If your organization is using SSO with Microsoft Entra ID, authentication logs to GitHub.com will be generated. Using the following query can help you identify a sudden increase in failed logon attempt of users.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry Coverage
Rule Body
id: 97ad74c4-fdd9-4a3f-b6bf-5e28f4f71e06
name: Brute Force Attack against GitHub Account
description: |
'Attackers who are trying to guess your users' passwords or use brute-force methods to get in. If your organization is using SSO with Microsoft Entra ID, authentication logs to GitHub.com will be generated. Using the following query can help you identify a sudden increase in failed logon attempt of users.'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- SigninLogs
- connectorId: AzureActiveDirectory
dataTypes:
- AADNonInteractiveUserSignInLogs
queryFrequency: 1h
queryPeriod: 7d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- CredentialAccess
relevantTechniques:
- T1110
query: |
let LearningPeriod = 7d;
let BinTime = 1h;
let RunTime = 1h;
let StartTime = 1h;
let sensitivity = 2.5;
let EndRunTime = StartTime - RunTime;
let EndLearningTime = StartTime + LearningPeriod;
let aadFunc = (tableName:string){
table(tableName)
| where TimeGenerated between (ago(EndLearningTime) .. ago(EndRunTime))
| where AppDisplayName =~ "GitHub.com"
| where ResultType != 0
| make-series FailedLogins = count() on TimeGenerated from ago(LearningPeriod) to ago(EndRunTime) step BinTime by UserPrincipalName, Type
| extend (Anomalies, Score, Baseline) = series_decompose_anomalies(FailedLogins, sensitivity, -1, 'linefit')
| mv-expand FailedLogins to typeof(double), TimeGenerated to typeof(datetime), Anomalies to typeof(double), Score to typeof(double), Baseline to typeof(long)
| where TimeGenerated >= ago(RunTime)
| where Anomalies > 0 and Baseline > 0
| join kind=inner (
table(tableName)
| where TimeGenerated between (ago(StartTime) .. ago(EndRunTime))
| where AppDisplayName =~ "GitHub.com"
| where ResultType != 0
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), IPAddresses = make_set(IPAddress,100), Locations = make_set(LocationDetails,20), Devices = make_set(DeviceDetail,20) by UserPrincipalName, UserId, AppDisplayName
) on UserPrincipalName
| project-away UserPrincipalName1
| extend Name = tostring(split(UserPrincipalName,'@',0)[0]), UPNSuffix = tostring(split(UserPrincipalName,'@',1)[0])
| extend IPAddressFirst = tostring(IPAddresses[0])
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
union isfuzzy=true aadSignin, aadNonInt
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: UserPrincipalName
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: UserId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPAddressFirst
version: 2.0.2
kind: Scheduled
Stages and Predicates
Parameters
let LearningPeriod = 7d;
let BinTime = 1h;
let RunTime = 1h;
let StartTime = 1h;
let sensitivity = 2.5;
let EndRunTime = StartTime - RunTime;
let EndLearningTime = StartTime + LearningPeriod;
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
Let Binding: aadFunc
let aadFunc = (tableName:string){
table(tableName)
| where TimeGenerated between (ago(EndLearningTime) .. ago(EndRunTime))
| where AppDisplayName =~ "GitHub.com"
| where ResultType != 0
| make-series FailedLogins = count() on TimeGenerated from ago(LearningPeriod) to ago(EndRunTime) step BinTime by UserPrincipalName, Type
| extend (Anomalies, Score, Baseline) = series_decompose_anomalies(FailedLogins, sensitivity, -1, 'linefit')
| mv-expand FailedLogins to typeof(double), TimeGenerated to typeof(datetime), Anomalies to typeof(double), Score to typeof(double), Baseline to typeof(long)
| where TimeGenerated >= ago(RunTime)
| where Anomalies > 0 and Baseline > 0
| join kind=inner (
table(tableName)
| where TimeGenerated between (ago(StartTime) .. ago(EndRunTime))
| where AppDisplayName =~ "GitHub.com"
| where ResultType != 0
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), IPAddresses = make_set(IPAddress,100), Locations = make_set(LocationDetails,20), Devices = make_set(DeviceDetail,20) by UserPrincipalName, UserId, AppDisplayName
) on UserPrincipalName
| project-away UserPrincipalName1
| extend Name = tostring(split(UserPrincipalName,'@',0)[0]), UPNSuffix = tostring(split(UserPrincipalName,'@',1)[0])
| extend IPAddressFirst = tostring(IPAddresses[0])
};
Union isfuzzy=true (2 Sources)
Each leg below queries one source; the rule matches if any leg does. Sources: aadSignin, aadNonInt
Leg 1: aadSignin
Leg 2: aadNonInt
Cisco WSA - Unexpected file type
#'Detects unexpected file type.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule Body
id: 8e9d1f70-d529-4598-9d3e-5dd5164d1d02
name: Cisco WSA - Unexpected file type
description: |
'Detects unexpected file type.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: SyslogAma
datatypes:
- Syslog
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
relevantTechniques:
- T1189
query: |
CiscoWSAEvent
| where isnotempty(AmpFileName)
| where isempty(AmpThreatName)
| where ResponseBodyMimeType =~ 'application/octet-stream'
| where AmpFileName !endswith '.exe'
| extend IPCustomEntity = SrcIpAddr, AccountCustomEntity = SrcUserName
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPCustomEntity
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountCustomEntity
version: 1.0.2
kind: Scheduled
Stages and Predicates
Stage 1: source
CiscoWSAEvent
Stage 2: where
| where isnotempty(AmpFileName)
Stage 3: where
| where isempty(AmpThreatName)
Stage 4: where
| where ResponseBodyMimeType =~ 'application/octet-stream'
Stage 5: where
| where AmpFileName !endswith '.exe'
Stage 6: extend
| extend IPCustomEntity = SrcIpAddr, AccountCustomEntity = SrcUserName
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
AmpFileName | is_not_null | field:"AmpFileName" kind:is_not_null | |
AmpThreatName | is_null | field:"AmpThreatName" kind:is_null | |
ResponseBodyMimeType | eq |
| field:"ResponseBodyMimeType" kind:eq value:"application/octet-stream" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
AmpFileName | ends_with | .exe | excludes:AmpFileName field:"AmpFileName" value:".exe" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountCustomEntity | extend |
IPCustomEntity | extend |
CyberArkEPM - Renamed Windows binary
#'Detects renamed windows binaries.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Stealth |
Rule Body
id: 9281b7cc-8f05-45a9-bf10-17fb29492a84
name: CyberArkEPM - Renamed Windows binary
description: |
'Detects renamed windows binaries.'
severity: High
requiredDataConnectors:
- connectorId: CyberArkEPM
dataTypes:
- CyberArkEPM
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Execution
- DefenseEvasion
relevantTechniques:
- T1204
- T1036
query: |
CyberArkEPM
| where EventSubType != 'AttackAttempt'
| where ActingProcessName has @'\'
| where ActingProcessName !has ActingProcessFileInternalName
| project EventEndTime, EventMessage, ActorUsername, ActingProcessFileInternalName
| extend AccountCustomEntity = ActorUsername
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountCustomEntity
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
CyberArkEPM
Stage 2: where
| where EventSubType != 'AttackAttempt'
Stage 3: where
| where ActingProcessName has @'\'
Stage 4: where
| where ActingProcessName !has ActingProcessFileInternalName
Stage 5: project
| project EventEndTime, EventMessage, ActorUsername, ActingProcessFileInternalName
Stage 6: extend
| extend AccountCustomEntity = ActorUsername
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ActingProcessName | match |
| field:"ParentImage" kind:match value:"\" |
EventSubType | ne |
| field:"EventSubType" kind:ne value:"AttackAttempt" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActingProcessFileInternalName | project |
ActorUsername | project |
EventEndTime | project |
EventMessage | project |
AccountCustomEntity | extend |
Dataverse - New user agent type that was not used before
#Identifies users accessing Dataverse from a User Agent that has not been seen in any Dataverse instance in the last 14 days.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Stealth | |
| Initial Access | |
| Lateral Movement |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | any: Dataverse and model-driven apps audit (catch-all) |
Rule Body
id: 34a5d79b-8f9a-420c-aa64-7f4d262ac29a
kind: Scheduled
name: Dataverse - New user agent type that was not used before
description: Identifies users accessing Dataverse from a User Agent that has not been
seen in any Dataverse instance in the last 14 days.
severity: Low
status: Available
requiredDataConnectors:
- connectorId: Dataverse
dataTypes:
- DataverseActivity
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- DefenseEvasion
relevantTechniques:
- T1078
- T0866
- T0819
- T1036
query: |
let query_lookback = 14d;
let query_frequency = 1h;
let known_useragents = dynamic([
// Enter known user agents to exclude.
// example:
// "Agent1", "Agent2", "Agent3"
]);
DataverseActivity
| where TimeGenerated between(ago(query_lookback) .. ago(query_frequency))
| where isnotempty(UserAgent)
| summarize by UserAgent
| join kind = rightanti (DataverseActivity
| where TimeGenerated > ago(query_frequency)
| where not (UserId has_any ("@onmicrosoft.com", "@microsoft.com", "Unknown"))
| where isnotempty(UserAgent)
| where UserAgent !in~ (known_useragents)
| where UserAgent !hasprefix "azure-logic-apps" and UserAgent !hasprefix "PowerApps")
on UserAgent
// Exclude user agents with a render agent to reduce noise.
| join kind = leftanti(
DataverseActivity
| where TimeGenerated > ago(query_frequency)
| where UserAgent has_any ("Gecko", "WebKit", "Presto", "Trident", "EdgeHTML", "Blink"))
on UserAgent
| summarize
FirstSeen = min(TimeGenerated),
LatestIP = arg_max(ClientIp, TimeGenerated)
by UserAgent, UserId, InstanceUrl
| extend
AccountName = tostring(split(UserId, '@')[0]),
UPNSuffix = tostring(split(UserId, '@')[1]),
CloudAppId = int(32780)
| project
FirstSeen,
UserId,
UserAgent,
LatestIP,
InstanceUrl,
CloudAppId,
AccountName,
UPNSuffix
eventGroupingSettings:
aggregationKind: AlertPerResult
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: CloudApplication
fieldMappings:
- identifier: AppId
columnName: CloudAppId
- identifier: InstanceName
columnName: InstanceUrl
- entityType: IP
fieldMappings:
- identifier: Address
columnName: LatestIP
alertDetailsOverride:
alertDisplayNameFormat: 'Dataverse - new user agent detected in {{{InstanceUrl}} '
alertDescriptionFormat: |
{{UserId}} with new agent not seen previously in the Dataverse activity log.
Agent: {{UserAgent}}
Latest IP: {{LatestIP}}
version: 3.2.0
Stages and Predicates
Parameters
let query_lookback = 14d;
let query_frequency = 1h;
Let Binding: known_useragents
let known_useragents = dynamic([
]);
Stage 1: source
DataverseActivity
Stage 2: where
where TimeGenerated between (ago(1209600s) .. ago(3600s))
Stage 3: where
where isnotempty(UserAgent)
Stage 4: summarize
summarize by UserAgent
Stage 5: join
| join kind = rightanti (DataverseActivity
| where TimeGenerated > ago(query_frequency)
| where not (UserId has_any ("@onmicrosoft.com", "@microsoft.com", "Unknown"))
| where isnotempty(UserAgent)
| where UserAgent !in~ (known_useragents)
| where UserAgent !hasprefix "azure-logic-apps" and UserAgent !hasprefix "PowerApps")
on UserAgent
Stage 6: join (negated)
join kind=leftanti (DataverseActivity) on UserAgent
Stage 7: summarize
summarize FirstSeen, LatestIP by UserAgent, UserId, InstanceUrl
Stage 8: extend
extend AccountName, CloudAppId, UPNSuffix
Stage 9: project
project AccountName, CloudAppId, FirstSeen, InstanceUrl, LatestIP, UPNSuffix, UserAgent, UserId
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
UserAgent | is_not_null | field:"UserAgent" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
UserAgent | eq | [] | excludes:UserAgent field:"UserAgent" value:"[]" |
UserAgent | starts_with | PowerApps | excludes:UserAgent field:"UserAgent" value:"PowerApps" |
UserAgent | starts_with | azure-logic-apps | excludes:UserAgent field:"UserAgent" value:"azure-logic-apps" |
UserId | match | @onmicrosoft.com, @microsoft.com, Unknown | excludes:UserId field:"UserId" value:"@onmicrosoft.com" field:"UserId" value:"@microsoft.com" field:"UserId" value:"Unknown" |
UserAgent | match | Gecko, WebKit, Presto, Trident, EdgeHTML, Blink | excludes:UserAgent |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountName | project |
CloudAppId | project |
FirstSeen | project |
InstanceUrl | project |
LatestIP | project |
UPNSuffix | project |
UserAgent | project |
UserId | project |
Failed AzureAD logons but success logon to host
#Identifies a list of IP addresses with a minimum number (default of 5) of failed logon attempts to Microsoft Entra ID. Uses that list to identify any successful remote logons to hosts from these IPs within the same timeframe.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Credential Access |
Telemetry Coverage
Rule Body
id: 8ee967a2-a645-4832-85f4-72b635bcb3a6
name: Failed AzureAD logons but success logon to host
description: |
'Identifies a list of IP addresses with a minimum number (default of 5) of failed logon attempts to Microsoft Entra ID.
Uses that list to identify any successful remote logons to hosts from these IPs within the same timeframe.'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- SigninLogs
- connectorId: AzureActiveDirectory
dataTypes:
- AADNonInteractiveUserSignInLogs
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: Syslog
dataTypes:
- Syslog
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvents
- connectorId: WindowsForwardedEvents
dataTypes:
- WindowsEvent
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- CredentialAccess
relevantTechniques:
- T1078
- T1110
query: |
//Adjust this threshold to fit the environment
let signin_threshold = 5;
//Make a list of all IPs with failed signins to AAD above our threshold
let aadFunc = (tableName:string){
let suspicious_signins =
table(tableName)
| where ResultType !in ("0", "50125", "50140")
| where IPAddress !in ('127.0.0.1', '::1', '')
| summarize count() by IPAddress
| where count_ > signin_threshold
| summarize make_set(IPAddress);
//See if any of these IPs have sucessfully logged into *nix hosts
let linux_logons =
Syslog
| where Facility contains "auth" and ProcessName != "sudo"
| where SyslogMessage has "Accepted"
| extend SourceIP = extract("(([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.(([0-9]{1,3})))",1,SyslogMessage)
| where SourceIP in (suspicious_signins)
| extend Reason = "Multiple failed AAD logins from IP address"
| project TimeGenerated, Computer, HostIP, IpAddress = SourceIP, SyslogMessage, Facility, ProcessName, Reason;
//See if any of these IPs have sucessfully logged into Windows hosts
let win_logons = (union isfuzzy=true
(SecurityEvent
| where EventID == 4624
| where LogonType in (10, 7, 3)
| where IpAddress != "-"
| where IpAddress in (suspicious_signins)
| extend Reason = "Multiple failed AAD logins from IP address"
| project TimeGenerated, Account, AccountType, Computer, Activity, EventID, LogonProcessName, IpAddress, LogonTypeName, TargetUserSid, TargetUserName, TargetDomainName, _ResourceId, Reason
),
(WindowsEvent
| where EventID == 4624 and has_any_ipv4(EventData, toscalar(suspicious_signins))
| extend LogonType = tostring(EventData.LogonType)
| where LogonType in (10, 7, 3)
| extend IpAddress = tostring(EventData.IpAddress)
| where IpAddress != "-"
| where IpAddress in (suspicious_signins)
| extend Reason = "Multiple failed AAD logins from IP address"
| extend Activity = "4624 - An account was successfully logged on."
| extend TargetUserName = tostring(EventData.TargetUserName), TargetDomainName = tostring(EventData.TargetDomainName)
| extend Account = strcat(TargetDomainName,"\\", TargetUserName)
| extend TargetUserSid = tostring(EventData.TargetUserSid)
| extend TargetAccount = strcat(EventData.TargetDomainName,"\\", EventData.TargetUserName)
| extend AccountType =case(Account endswith "$" or TargetUserSid in ("S-1-5-18", "S-1-5-19", "S-1-5-20"), "Machine", isempty(TargetUserSid), "", "User")
| extend LogonProcessName = tostring(EventData.LogonProcessName)
| project TimeGenerated, Account, AccountType, Computer, Activity, EventID, LogonProcessName, IpAddress, TargetUserSid, TargetUserName, TargetDomainName, _ResourceId, Reason
)
);
union isfuzzy=true linux_logons,win_logons
| extend timestamp = TimeGenerated
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex+1), Computer)
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
union isfuzzy=true aadSignin, aadNonInt
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Account
- identifier: Name
columnName: TargetUserName
- identifier: NTDomain
columnName: TargetDomainName
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
- identifier: HostName
columnName: HostName
- identifier: NTDomain
columnName: HostNameDomain
- entityType: Host
fieldMappings:
- identifier: AzureID
columnName: _ResourceId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IpAddress
version: 1.3.2
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
support:
tier: Community
categories:
domains: [ "Security - Others", "Identity" ]
Stages and Predicates
Parameters
let signin_threshold = 5;
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
Let Binding: aadFunc
let aadFunc = (tableName:string){
let suspicious_signins =
table(tableName)
| where ResultType !in ("0", "50125", "50140")
| where IPAddress !in ('127.0.0.1', '::1', '')
| summarize count() by IPAddress
| where count_ > signin_threshold
| summarize make_set(IPAddress);
Union isfuzzy=true (2 Sources)
Each leg below queries one source; the rule matches if any leg does. Sources: linux_logons, win_logons
Leg 1: linux_logons
Leg 2: win_logons
Applied to the Combined Result
| extend timestamp = TimeGenerated | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.')) | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex+1), Computer)
};
union isfuzzy=true aadSignin, aadNonInt
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventID | eq |
| field:"EventID" kind:eq value:"4624" |
Facility | contains |
| field:"Facility" kind:contains value:"auth" |
IpAddress | in |
| field:"IpAddress" kind:in value:"suspicious_signins" |
IpAddress | ne |
| field:"IpAddress" kind:ne value:"-" |
LogonType | in |
| field:"LogonType" kind:in |
ProcessName | ne |
| field:"ProcessName" kind:ne value:"sudo" |
SourceIP | in |
| field:"SourceIP" kind:in value:"suspicious_signins" |
SyslogMessage | match |
| field:"SyslogMessage" kind:match value:"Accepted" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Account | project |
AccountType | project |
Activity | project |
Computer | project |
EventID | project |
IpAddress | project |
LogonProcessName | project |
Reason | project |
TargetDomainName | project |
TargetUserName | project |
TargetUserSid | project |
TimeGenerated | project |
_ResourceId | project |
timestamp | extend |
DomainIndex | extend |
HostName | extend |
HostNameDomain | extend |
Google Threat Intelligence - Threat Hunting Domain
#Google Threat Intelligence domain correlation.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 22: DNSEvent (DNS query) |
Rule Body
id: "d9e1646c-dc17-4150-ac85-581f5c9cb41f"
name: Google Threat Intelligence - Threat Hunting Domain
description: |
'Google Threat Intelligence domain correlation.'
severity: Medium
requiredDataConnectors:
- connectorId: ThreatIntelligence
dataTypes:
- ThreatIntelIndicators
queryFrequency: 30m
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
relevantTechniques:
- T1071
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 1h
matchingMethod: AllEntities
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: 'Google Threat Intelligence Match'
alertDescriptionFormat: 'Correlation found from the {{Type}} table.'
query: |
let ioc_lookBack = 1d;
_Im_Dns
| where isnotempty(DnsQuery)
| extend lowerDomain=tolower(DnsQuery)
| join kind=inner (
ThreatIntelIndicators
| where ObservableKey == 'domain-name:value'
| where isnotempty(ObservableValue)
| where SourceSystem == "Google Threat Intelligence"
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
| where IsActive == true and (isnull(ValidUntil) or ValidUntil > now())
| extend lowerDomain=tolower(ObservableValue)
) on lowerDomain
| project Domain=ObservableValue, Description=Data.description, Type, TimeGenerated
entityMappings:
- entityType: DNS
fieldMappings:
- identifier: DomainName
columnName: Domain
version: 1.0.0
kind: Scheduled
Stages and Predicates
Parameters
let ioc_lookBack = 1d;
Stage 1: source
_Im_Dns
Stage 2: where
| where isnotempty(DnsQuery)
Stage 3: extend
| extend lowerDomain=tolower(DnsQuery)
Stage 4: join
| join kind=inner (
ThreatIntelIndicators
| where ObservableKey == 'domain-name:value'
| where isnotempty(ObservableValue)
| where SourceSystem == "Google Threat Intelligence"
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
| where IsActive == true and (isnull(ValidUntil) or ValidUntil > now())
| extend lowerDomain=tolower(ObservableValue)
) on lowerDomain
Stage 5: project
project Description, Domain, TimeGenerated, Type
Stage 6: summarize aggregation inside the join branch
summarize by Id
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DnsQuery | is_not_null | field:"DnsQuery" kind:is_not_null | |
IsActive | eq |
| field:"IsActive" kind:eq value:"true" |
ObservableKey | eq |
| field:"ObservableKey" kind:eq value:"domain-name:value" |
ObservableValue | is_not_null | field:"ObservableValue" kind:is_not_null | |
SourceSystem | eq |
| field:"SourceSystem" kind:eq value:"Google Threat Intelligence" |
ValidUntil | is_null | field:"ValidUntil" kind:is_null |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Id | summarize |
Guardian- Language Detection Policy Violation Detection
#'This alert creates an incident when Language Detection Policy Violation detected from the Guardian.'
Rule Body
id: e65938c4-1379-4f7a-bd22-78f670a239c3
name: Guardian- Language Detection Policy Violation Detection
description: |
'This alert creates an incident when Language Detection Policy Violation detected from the Guardian.'
severity: Informational
status: Available
requiredDataConnectors:
- connectorId: BoschAIShield
dataTypes:
- Guardian
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: |
Guardian
| where PolicyViolatedControlFeature =~ 'Language Detection'
| where Severity =~ 'Informational'
entityMappings:
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: HostName
- identifier: NTDomain
columnName: NTDomain
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SourceIP
eventGroupingSettings:
aggregationKind: SingleAlert
alertDetailsOverride:
alertDisplayNameFormat: Guardian- Language Detection Policy Violation detection
alertDescriptionFormat: |
This query detects Language Detection Policy Violation detected from the Guardian generated at {{TimeGenerated}}.\n\nPlease check the source for more information and investigate further.
alertTacticsColumnName: null
alertSeverityColumnName: Severity
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
Guardian
Stage 2: where
| where PolicyViolatedControlFeature =~ 'Language Detection'
Stage 3: where
| where Severity =~ 'Informational'
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
PolicyViolatedControlFeature | eq |
| field:"PolicyViolatedControlFeature" kind:eq value:"Language Detection" |
Severity | eq |
| field:"Severity" kind:eq value:"Informational" |
Identify Mango Sandstorm powershell commands
#The query below identifies powershell commands used by the threat actor Mango Sandstorm. Reference: https://www.microsoft.com/security/blog/2022/08/25/mercury-leveraging-log4j-2-vulnerabilities-in-unpatched-systems-to-target-israeli-organizations/
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Lateral Movement |
Telemetry Coverage
Rule Body
id: ce74dc9a-cb3c-4081-8c2f-7d39f6b7bae1
name: Identify Mango Sandstorm powershell commands
description: |
'The query below identifies powershell commands used by the threat actor Mango Sandstorm.
Reference: https://www.microsoft.com/security/blog/2022/08/25/mercury-leveraging-log4j-2-vulnerabilities-in-unpatched-systems-to-target-israeli-organizations/'
severity: High
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceProcessEvents
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- LateralMovement
relevantTechniques:
- T1570
tags:
- Mango Sandstorm
- Schema: ASIMFileEvent
SchemaVersion: 0.1.0
query: |
(union isfuzzy=true
(SecurityEvent
| where EventID == 4688
| where Process has_any ("powershell.exe","powershell_ise.exe","pwsh.exe") and CommandLine has_cs "-exec bypass -w 1 -enc"
| where CommandLine contains_cs "UwB0AGEAcgB0AC0ASgBvAGIAIAAtAFMAYwByAGkAcAB0AEIAbABvAGMAawAgAHsAKABzAGEAcABzACAAKAAiAHAA"
| extend DvcHostname = Computer, ProcessId = tostring(ProcessId), ActorUsername = Account
),
(DeviceProcessEvents
| where FileName =~ "powershell.exe" and ProcessCommandLine has_cs "-exec bypass -w 1 -enc"
| where ProcessCommandLine contains_cs "UwB0AGEAcgB0AC0ASgBvAGIAIAAtAFMAYwByAGkAcAB0AEIAbABvAGMAawAgAHsAKABzAGEAcABzACAAKAAiAHAA"
| extend DvcHostname = DeviceName, ProcessId = tostring(InitiatingProcessId), ActorUsername = strcat(AccountDomain, @"\", AccountName)
),
(imProcessCreate
| where Process has_any ("powershell.exe","powershell_ise.exe","pwsh.exe") and CommandLine has_cs "-exec bypass -w 1 -enc"
| where CommandLine contains_cs "UwB0AGEAcgB0AC0ASgBvAGIAIAAtAFMAYwByAGkAcAB0AEIAbABvAGMAawAgAHsAKABzAGEAcABzACAAKAAiAHAA"
| extend ProcessId = tostring(TargetProcessId)
)
)
| extend AccountName = tostring(split(ActorUsername, "\\")[0]), AccountNTDomain = tostring(split(ActorUsername, "\\")[1])
| extend HostName = tostring(split(DvcHostname, ".")[0]), DomainIndex = toint(indexof(DvcHostname, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(DvcHostname, DomainIndex + 1), DvcHostname)
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: ActorUsername
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountNTDomain
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: DvcHostname
- identifier: HostName
columnName: HostName
- identifier: NTDomain
columnName: HostNameDomain
- entityType: Process
fieldMappings:
- identifier: ProcessId
columnName: ProcessId
version: 1.0.5
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
support:
tier: Community
categories:
domains: [ "Security - Threat Intelligence" ]
Stages and Predicates
Union isfuzzy=true (3 Sources)
Each leg below queries one source; the rule matches if any leg does. Sources: SecurityEvent, DeviceProcessEvents, imProcessCreate
Leg 1: SecurityEvent
SecurityEvent
| where EventID == 4688
| where Process has_any ("powershell.exe","powershell_ise.exe","pwsh.exe") and CommandLine has_cs "-exec bypass -w 1 -enc"
| where CommandLine contains_cs "UwB0AGEAcgB0AC0ASgBvAGIAIAAtAFMAYwByAGkAcAB0AEIAbABvAGMAawAgAHsAKABzAGEAcABzACAAKAAiAHAA"
| extend DvcHostname = Computer, ProcessId = tostring(ProcessId), ActorUsername = Account
Leg 2: DeviceProcessEvents
DeviceProcessEvents
| where FileName =~ "powershell.exe" and ProcessCommandLine has_cs "-exec bypass -w 1 -enc"
| where ProcessCommandLine contains_cs "UwB0AGEAcgB0AC0ASgBvAGIAIAAtAFMAYwByAGkAcAB0AEIAbABvAGMAawAgAHsAKABzAGEAcABzACAAKAAiAHAA"
| extend DvcHostname = DeviceName, ProcessId = tostring(InitiatingProcessId), ActorUsername = strcat(AccountDomain, @"\", AccountName)
Leg 3: imProcessCreate
imProcessCreate
| where Process has_any ("powershell.exe","powershell_ise.exe","pwsh.exe") and CommandLine has_cs "-exec bypass -w 1 -enc"
| where CommandLine contains_cs "UwB0AGEAcgB0AC0ASgBvAGIAIAAtAFMAYwByAGkAcAB0AEIAbABvAGMAawAgAHsAKABzAGEAcABzACAAKAAiAHAA"
| extend ProcessId = tostring(TargetProcessId)
Applied to the Combined Result
| extend AccountName = tostring(split(ActorUsername, "\\")[0]), AccountNTDomain = tostring(split(ActorUsername, "\\")[1])
| extend HostName = tostring(split(DvcHostname, ".")[0]), DomainIndex = toint(indexof(DvcHostname, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(DvcHostname, DomainIndex + 1), DvcHostname)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
CommandLine | contains |
| field:"CommandLine" kind:contains value:"UwB0AGEAcgB0AC0ASgBvAGIAIAAtAFMAYwByAGkAcAB0AEIAbABvAGMAawAgAHsAKABzAGEAcABzACAAKAAiAHAA" |
CommandLine | match |
| field:"CommandLine" kind:match value:"-exec bypass -w 1 -enc" |
EventID | eq |
| field:"EventID" kind:eq value:"4688" |
FileName | eq |
| field:"process_basename" kind:eq value:"powershell.exe" |
Process | match |
| field:"Process" kind:match |
ProcessCommandLine | contains |
| field:"CommandLine" kind:contains value:"UwB0AGEAcgB0AC0ASgBvAGIAIAAtAFMAYwByAGkAcAB0AEIAbABvAGMAawAgAHsAKABzAGEAcABzACAAKAAiAHAA" |
ProcessCommandLine | match |
| field:"CommandLine" kind:match value:"-exec bypass -w 1 -enc" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActorUsername | extend |
DvcHostname | extend |
ProcessId | extend |
AccountNTDomain | extend |
AccountName | extend |
DomainIndex | extend |
HostName | extend |
HostNameDomain | extend |
Log4j vulnerability exploit aka Log4Shell IP IOC
#Identifies a match across various data feeds for IP IOCs related to the Log4j vulnerability exploit aka Log4Shell described in CVE-2021-44228. References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=2021-44228
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
Rule Body
id: 6e575295-a7e6-464c-8192-3e1d8fd6a990
name: Log4j vulnerability exploit aka Log4Shell IP IOC
description: |
'Identifies a match across various data feeds for IP IOCs related to the Log4j vulnerability exploit aka Log4Shell described in CVE-2021-44228.
References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=2021-44228'
severity: High
status: Available
tags:
- Log4j
- Log4Shell
- CVE-2021-44228
- Schema: ASIMDns
SchemaVersion: 0.1.1
- Schema: ASIMNetworkSession
SchemaVersion: 0.2.0
requiredDataConnectors:
- connectorId: Office365
dataTypes:
- OfficeActivity
- connectorId: DNS
dataTypes:
- DnsEvents
- connectorId: AzureMonitor(VMInsights)
dataTypes:
- VMConnection
- connectorId: CiscoASA
dataTypes:
- CommonSecurityLog
- connectorId: CiscoAsaAma
dataTypes:
- CommonSecurityLog
- connectorId: PaloAltoNetworks
dataTypes:
- CommonSecurityLog
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: AzureActiveDirectory
dataTypes:
- SigninLogs
- connectorId: AzureActiveDirectory
dataTypes:
- AADNonInteractiveUserSignInLogs
- connectorId: AzureMonitor(WireData)
dataTypes:
- WireData
- connectorId: AzureMonitor(IIS)
dataTypes:
- W3CIISLog
- connectorId: AzureActivity
dataTypes:
- AzureActivity
- connectorId: AWS
dataTypes:
- AWSCloudTrail
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceNetworkEvents
- connectorId: AzureFirewall
dataTypes:
- AzureDiagnostics
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
relevantTechniques:
- T1071
query: |
let IPList = externaldata(IPAddress:string)[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Log4j_IOC_List.csv"] with (format="csv", ignoreFirstRecord=True);
let IPRegex = '[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}';
//Network logs
let CSlogSourceIP = CommonSecurityLog | summarize by IPAddress = SourceIP, Type;
let CSlogDestIP = CommonSecurityLog | summarize by IPAddress = DestinationIP, Type;
let CSlogMsgIP = CommonSecurityLog | extend MessageIP = extract(IPRegex, 0, Message) | summarize by IPAddress = MessageIP, Type;
let DnsIP = DnsEvents | summarize by IPAddress = IPAddresses, Type;
// If you have enabled the _Im_Dns and/or imNetworkSession normalization in your workspace, you can uncomment one or both below. Reference - https://docs.microsoft.com/azure/sentinel/normalization
//let imDnsIP = _Im_Dns (response_has_any_prefix=IPList) | summarize by IPAddress = ResponseName, Type;
//let imNetSessIP = imNetworkSession (dstipaddr_has_any_prefix=IPList) | summarize by IPAddress = DstIpAddr, Type;
//Cloud service logs
let officeIP = OfficeActivity | summarize by IPAddress = ClientIP, Type;
let signinIP = SigninLogs | summarize by IPAddress, Type;
let nonintSigninIP = AADNonInteractiveUserSignInLogs | summarize by IPAddress, Type;
let azureActIP = AzureActivity | summarize by IPAddress = CallerIpAddress, Type;
let awsCtIP = AWSCloudTrail | summarize by IPAddress = SourceIpAddress, Type;
//Device logs
let vmConnSourceIP = VMConnection | summarize by IPAddress = SourceIp, Type;
let vmConnDestIP = VMConnection | summarize by IPAddress = DestinationIp, Type;
let iisLogIP = W3CIISLog | summarize by IPAddress = cIP, Type;
let devNetIP = DeviceNetworkEvents | summarize by IPAddress = RemoteIP, Type;
//need to parse to get IP
let azureDiagIP = AzureDiagnostics | where ResourceType == "AZUREFIREWALLS" | where Category in ("AzureFirewallApplicationRule", "AzureFirewallNetworkRule")
| where msg_s has_any (IPList) | parse msg_s with Protocol 'request from ' SourceHost ':' SourcePort 'to ' DestinationHost ':' DestinationPort '. Action:' Action | summarize by IPAddress = DestinationHost, Type;
let sysEvtIP = Event | where Source == "Microsoft-Windows-Sysmon" | where EventID == 3 | where EventData has_any (IPList) | extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend SourceIP = tostring(EventDetail.[9].["#text"]), DestinationIP = tostring(EventDetail.[14].["#text"])
| where SourceIP in (IPList) or DestinationIP in (IPList) | extend IPAddress = iff(SourceIP in (IPList), SourceIP, DestinationIP) | summarize by IPAddress, Type;
// If you have enabled the _Im_DNS and/or imNetworkSession normalization in your workdspace, you can uncomment below and include. Reference - https://docs.microsoft.com/azure/sentinel/normalization
//let ipsort = union isfuzzy=true CSlogDestIP, CSlogMsgIP, CSlogSourceIP, DnsIP, officeIP, signinIP, nonintSigninIP, azureActIP, awsCtIP, vmConnDestIP, vmConnSourceIP, azureDiagIP, sysEvtIP, imDnsIP, imNetSessIP
// If you uncomment above, then comment out the line below
let ipsort = union isfuzzy=true CSlogDestIP, CSlogMsgIP, CSlogSourceIP, DnsIP, officeIP, signinIP, nonintSigninIP, azureActIP, awsCtIP, vmConnDestIP, vmConnSourceIP, azureDiagIP, sysEvtIP
| summarize by IPAddress
| where isnotempty(IPAddress) | where not(ipv4_is_private(IPAddress)) and IPAddress !in ('0.0.0.0','127.0.0.1');
let ipMatch = ipsort | where IPAddress in (IPList);
(union isfuzzy=true
(CommonSecurityLog
| where SourceIP in (ipMatch) or DestinationIP in (ipMatch) or Message has_any (ipMatch)
| project TimeGenerated, SourceIP, DestinationIP, Message, SourceUserID, RequestURL, Type
| extend MessageIP = extract(IPRegex, 0, Message)
| extend IPMatch = case(SourceIP in (ipMatch), "SourceIP", DestinationIP in (ipMatch), "DestinationIP", MessageIP in (ipMatch), "Message", "No Match")
| extend timestamp = TimeGenerated, IPEntity = case(IPMatch == "SourceIP", SourceIP, IPMatch == "DestinationIP", DestinationIP, IPMatch == "Message", MessageIP, "No Match")
),
(OfficeActivity
| where ClientIP in (ipMatch)
| project TimeGenerated, UserAgent, Operation, RecordType, UserId, ClientIP, Type
| extend SourceIPAddress = ClientIP, Account = UserId
| extend timestamp = TimeGenerated , IPEntity = SourceIPAddress , AccountEntity = Account
),
(DnsEvents
| where IPAddresses has_any (ipMatch)
| project TimeGenerated, Computer, IPAddresses, Name, ClientIP, Type
| extend DestinationIPAddress = IPAddresses, Host = Computer
| extend timestamp = TimeGenerated, IPEntity = DestinationIPAddress, HostEntity = Host
),
(VMConnection
| where SourceIp in (ipMatch) or DestinationIp in (ipMatch)
| project TimeGenerated, Computer, SourceIp, DestinationIp, Type
| extend IPMatch = case( SourceIp in (ipMatch), "SourceIP", DestinationIp in (ipMatch), "DestinationIP", "None")
| extend timestamp = TimeGenerated , IPEntity = case(IPMatch == "SourceIP", SourceIp, IPMatch == "DestinationIP", DestinationIp, "None"), Host = Computer
),
(Event
| where Source =~ "Microsoft-Windows-Sysmon"
| where EventID == 3
| where EventData has_any (ipMatch)
| project TimeGenerated, EventData, UserName, Computer, Type
| extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend SourceIP = tostring(EventDetail.[9].["#text"]), DestinationIP = tostring(EventDetail.[14].["#text"])
| where SourceIP in (ipMatch) or DestinationIP in (ipMatch)
| extend IPMatch = case( SourceIP in (ipMatch), "SourceIP", DestinationIP in (ipMatch), "DestinationIP", "None")
| extend timestamp = TimeGenerated, AccountEntity = UserName, HostEntity = Computer , IPEntity = case(IPMatch == "SourceIP", SourceIP, IPMatch == "DestinationIP", DestinationIP, "None")
),
(SigninLogs
| where IPAddress in (ipMatch)
| project TimeGenerated, UserPrincipalName, IPAddress, Type
| extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress
),
(AADNonInteractiveUserSignInLogs
| where IPAddress in (ipMatch)
| project TimeGenerated, UserPrincipalName, IPAddress, Type
| extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress
),
(W3CIISLog
| where cIP in (ipMatch)
| project TimeGenerated, Computer, cIP, csUserName, Type
| extend timestamp = TimeGenerated, IPEntity = cIP, HostEntity = Computer, AccountEntity = csUserName
),
(AzureActivity
| where CallerIpAddress in (ipMatch)
| project TimeGenerated, CallerIpAddress, Caller, Type
| extend timestamp = TimeGenerated, IPEntity = CallerIpAddress, AccountEntity = Caller
),
(
AWSCloudTrail
| where SourceIpAddress in (ipMatch)
| project TimeGenerated, SourceIpAddress, UserIdentityUserName, Type
| extend timestamp = TimeGenerated, IPEntity = SourceIpAddress, AccountEntity = UserIdentityUserName
),
(
DeviceNetworkEvents
| where RemoteIP in (ipMatch)
| where ActionType =~ "InboundConnectionAccepted"
| project TimeGenerated, RemoteIP, DeviceName, Type
| extend timestamp = TimeGenerated, IPEntity = RemoteIP, HostEntity = DeviceName
),
(
AzureDiagnostics
| where ResourceType =~ "AZUREFIREWALLS"
| where Category in ("AzureFirewallApplicationRule", "AzureFirewallNetworkRule")
| where msg_s has_any (ipMatch)
| project TimeGenerated, msg_s, Type
| parse msg_s with Protocol 'request from ' SourceIP ':' SourcePort 'to ' DestinationIP ':' DestinationPort '. Action:' Action
| where DestinationIP has_any (ipMatch)
| extend timestamp = TimeGenerated, IPEntity = DestinationIP
)
// If you have enabled the _Im_Dns and/or imNetworkSession normalization in your workdspace, you can uncomment below and include. Reference - https://docs.microsoft.com/azure/sentinel/normalization
//,
//(_Im_Dns (response_has_any_prefix=IPList)
//| project TimeGenerated, ResponseName, SrcIpAddr, Type
//| extend DestinationIPAddress = ResponseName, Host = SrcIpAddr
//| extend timestamp = TimeGenerated, IPEntity = DestinationIPAddress, HostEntity = Host
//),
//(imNetworkSession (dstipaddr_has_any_prefix=IPList)
//| project TimeGenerated, DstIpAddr, SrcIpAddr, Type
//| extend timestamp = TimeGenerated, IPEntity = DstIpAddr, HostEntity = SrcIpAddr
//)
)
| extend Name = tostring(split(AccountEntity, '@', 0)[0]), UPNSuffix = tostring(split(AccountEntity, '@', 1)[0])
| extend HostName = tostring(split(HostEntity, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(HostEntity, '.'), 1, -1), '.'))
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: DnsDomain
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPEntity
version: 2.0.6
kind: Scheduled
Stages and Predicates
Parameters
let IPRegex = '[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}';
Let Binding: IPList
let IPList = externaldata(IPAddress:string)[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Log4j_IOC_List.csv"] with (format="csv", ignoreFirstRecord=True);
Let Binding: CSlogSourceIP
let CSlogSourceIP = CommonSecurityLog | summarize by IPAddress = SourceIP, Type;
Let Binding: CSlogDestIP
let CSlogDestIP = CommonSecurityLog | summarize by IPAddress = DestinationIP, Type;
Let Binding: CSlogMsgIP
let CSlogMsgIP = CommonSecurityLog | extend MessageIP = extract(IPRegex, 0, Message) | summarize by IPAddress = MessageIP, Type;
Let Binding: DnsIP
let DnsIP = DnsEvents | summarize by IPAddress = IPAddresses, Type;
Let Binding: officeIP
let officeIP = OfficeActivity | summarize by IPAddress = ClientIP, Type;
Let Binding: signinIP
let signinIP = SigninLogs | summarize by IPAddress, Type;
Let Binding: nonintSigninIP
let nonintSigninIP = AADNonInteractiveUserSignInLogs | summarize by IPAddress, Type;
Let Binding: azureActIP
let azureActIP = AzureActivity | summarize by IPAddress = CallerIpAddress, Type;
Let Binding: awsCtIP
let awsCtIP = AWSCloudTrail | summarize by IPAddress = SourceIpAddress, Type;
Let Binding: vmConnSourceIP
let vmConnSourceIP = VMConnection | summarize by IPAddress = SourceIp, Type;
Let Binding: vmConnDestIP
let vmConnDestIP = VMConnection | summarize by IPAddress = DestinationIp, Type;
Let Binding: iisLogIP
let iisLogIP = W3CIISLog | summarize by IPAddress = cIP, Type;
Let Binding: devNetIP
let devNetIP = DeviceNetworkEvents | summarize by IPAddress = RemoteIP, Type;
Let Binding: azureDiagIP
let azureDiagIP = AzureDiagnostics | where ResourceType == "AZUREFIREWALLS" | where Category in ("AzureFirewallApplicationRule", "AzureFirewallNetworkRule")
| where msg_s has_any (IPList) | parse msg_s with Protocol 'request from ' SourceHost ':' SourcePort 'to ' DestinationHost ':' DestinationPort '. Action:' Action | summarize by IPAddress = DestinationHost, Type;
Let Binding: sysEvtIP
let sysEvtIP = Event | where Source == "Microsoft-Windows-Sysmon" | where EventID == 3 | where EventData has_any (IPList) | extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend SourceIP = tostring(EventDetail.[9].["#text"]), DestinationIP = tostring(EventDetail.[14].["#text"])
| where SourceIP in (IPList) or DestinationIP in (IPList) | extend IPAddress = iff(SourceIP in (IPList), SourceIP, DestinationIP) | summarize by IPAddress, Type;
Let Binding: ipsort
let ipsort = union isfuzzy=true CSlogDestIP, CSlogMsgIP, CSlogSourceIP, DnsIP, officeIP, signinIP, nonintSigninIP, azureActIP, awsCtIP, vmConnDestIP, vmConnSourceIP, azureDiagIP, sysEvtIP
| summarize by IPAddress
| where isnotempty(IPAddress) | where not(ipv4_is_private(IPAddress)) and IPAddress !in ('0.0.0.0','127.0.0.1');
Let Binding: ipMatch
let ipMatch = ipsort | where IPAddress in (IPList);
Union isfuzzy=true (12 Sources)
Each leg below queries one source; the rule matches if any leg does. Sources: CommonSecurityLog, OfficeActivity, DnsEvents, VMConnection, Event, SigninLogs, AADNonInteractiveUserSignInLogs, W3CIISLog, AzureActivity, AWSCloudTrail, DeviceNetworkEvents, AzureDiagnostics
Leg 1: CommonSecurityLog
CommonSecurityLog
| where SourceIP in (ipMatch) or DestinationIP in (ipMatch) or Message has_any (ipMatch)
| project TimeGenerated, SourceIP, DestinationIP, Message, SourceUserID, RequestURL, Type
| extend MessageIP = extract(IPRegex, 0, Message)
| extend IPMatch = case(SourceIP in (ipMatch), "SourceIP", DestinationIP in (ipMatch), "DestinationIP", MessageIP in (ipMatch), "Message", "No Match")
| extend timestamp = TimeGenerated, IPEntity = case(IPMatch == "SourceIP", SourceIP, IPMatch == "DestinationIP", DestinationIP, IPMatch == "Message", MessageIP, "No Match")
Leg 2: OfficeActivity
OfficeActivity
| where ClientIP in (ipMatch)
| project TimeGenerated, UserAgent, Operation, RecordType, UserId, ClientIP, Type
| extend SourceIPAddress = ClientIP, Account = UserId
| extend timestamp = TimeGenerated , IPEntity = SourceIPAddress , AccountEntity = Account
Leg 3: DnsEvents
DnsEvents
| where IPAddresses has_any (ipMatch)
| project TimeGenerated, Computer, IPAddresses, Name, ClientIP, Type
| extend DestinationIPAddress = IPAddresses, Host = Computer
| extend timestamp = TimeGenerated, IPEntity = DestinationIPAddress, HostEntity = Host
Leg 4: VMConnection
VMConnection
| where SourceIp in (ipMatch) or DestinationIp in (ipMatch)
| project TimeGenerated, Computer, SourceIp, DestinationIp, Type
| extend IPMatch = case( SourceIp in (ipMatch), "SourceIP", DestinationIp in (ipMatch), "DestinationIP", "None")
| extend timestamp = TimeGenerated , IPEntity = case(IPMatch == "SourceIP", SourceIp, IPMatch == "DestinationIP", DestinationIp, "None"), Host = Computer
Leg 5: Event
Event
| where Source =~ "Microsoft-Windows-Sysmon"
| where EventID == 3
| where EventData has_any (ipMatch)
| project TimeGenerated, EventData, UserName, Computer, Type
| extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend SourceIP = tostring(EventDetail.[9].["#text"]), DestinationIP = tostring(EventDetail.[14].["#text"])
| where SourceIP in (ipMatch) or DestinationIP in (ipMatch)
| extend IPMatch = case( SourceIP in (ipMatch), "SourceIP", DestinationIP in (ipMatch), "DestinationIP", "None")
| extend timestamp = TimeGenerated, AccountEntity = UserName, HostEntity = Computer , IPEntity = case(IPMatch == "SourceIP", SourceIP, IPMatch == "DestinationIP", DestinationIP, "None")
Leg 6: SigninLogs
SigninLogs
| where IPAddress in (ipMatch)
| project TimeGenerated, UserPrincipalName, IPAddress, Type
| extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress
Leg 7: AADNonInteractiveUserSignInLogs
AADNonInteractiveUserSignInLogs
| where IPAddress in (ipMatch)
| project TimeGenerated, UserPrincipalName, IPAddress, Type
| extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress
Leg 8: W3CIISLog
W3CIISLog
| where cIP in (ipMatch)
| project TimeGenerated, Computer, cIP, csUserName, Type
| extend timestamp = TimeGenerated, IPEntity = cIP, HostEntity = Computer, AccountEntity = csUserName
Leg 9: AzureActivity
AzureActivity
| where CallerIpAddress in (ipMatch)
| project TimeGenerated, CallerIpAddress, Caller, Type
| extend timestamp = TimeGenerated, IPEntity = CallerIpAddress, AccountEntity = Caller
Leg 10: AWSCloudTrail
AWSCloudTrail
| where SourceIpAddress in (ipMatch)
| project TimeGenerated, SourceIpAddress, UserIdentityUserName, Type
| extend timestamp = TimeGenerated, IPEntity = SourceIpAddress, AccountEntity = UserIdentityUserName
Leg 11: DeviceNetworkEvents
DeviceNetworkEvents
| where RemoteIP in (ipMatch)
| where ActionType =~ "InboundConnectionAccepted"
| project TimeGenerated, RemoteIP, DeviceName, Type
| extend timestamp = TimeGenerated, IPEntity = RemoteIP, HostEntity = DeviceName
Leg 12: AzureDiagnostics
AzureDiagnostics
| where ResourceType =~ "AZUREFIREWALLS"
| where Category in ("AzureFirewallApplicationRule", "AzureFirewallNetworkRule")
| where msg_s has_any (ipMatch)
| project TimeGenerated, msg_s, Type
| parse msg_s with Protocol 'request from ' SourceIP ':' SourcePort 'to ' DestinationIP ':' DestinationPort '. Action:' Action
| where DestinationIP has_any (ipMatch)
| extend timestamp = TimeGenerated, IPEntity = DestinationIP
Applied to the Combined Result
| extend Name = tostring(split(AccountEntity, '@', 0)[0]), UPNSuffix = tostring(split(AccountEntity, '@', 1)[0])
| extend HostName = tostring(split(HostEntity, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(HostEntity, '.'), 1, -1), '.'))
Indicators
These rows show field, operator, and value matches.
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
TimeGenerated | project |
Type | project |
msg_s | project |
IPEntity | extend |
timestamp | extend |
Name | extend |
UPNSuffix | extend |
DnsDomain | extend |
HostName | extend |
Microsoft Entra ID Hybrid Health AD FS New Server
#This detection uses AzureActivity logs (Administrative category) to identify the creation or update of a server instance in an Microsoft Entra ID Hybrid Health AD FS service. A threat actor can create a new AD Health ADFS service and create a fake server instance to spoof AD FS signing logs. There is no need to compromise an on-premises AD FS server. This can be done programmatically via HTTP requests to Azure. More information in this blog: https://o365blog.com/post/hybridhealthagent/
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- Azure Active Directory Hybrid Health AD FS New Server (Sigma)
- Azure Active Directory Hybrid Health AD FS Service Delete (Sigma)
- Azure Subscription Permission Elevation Via AuditLogs (Sigma)
- Detect Custom Script or Run Command deployment by risky user (Kusto)
- Microsoft Entra ID Hybrid Health AD FS Service Delete (Kusto)
- Microsoft Entra ID Hybrid Health AD FS Suspicious Application (Kusto)
- NRT Microsoft Entra ID Hybrid Health AD FS New Server (Kusto)
Rule Body
id: 88f453ff-7b9e-45bb-8c12-4058ca5e44ee
name: Microsoft Entra ID Hybrid Health AD FS New Server
description: |
'This detection uses AzureActivity logs (Administrative category) to identify the creation or update of a server instance in an Microsoft Entra ID Hybrid Health AD FS service.
A threat actor can create a new AD Health ADFS service and create a fake server instance to spoof AD FS signing logs. There is no need to compromise an on-premises AD FS server.
This can be done programmatically via HTTP requests to Azure. More information in this blog: https://o365blog.com/post/hybridhealthagent/'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: AzureActivity
dataTypes:
- AzureActivity
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
relevantTechniques:
- T1578
tags:
- SimuLand
query: |
AzureActivity
| where CategoryValue =~ 'Administrative'
| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'
| where _ResourceId has 'AdFederationService'
| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/servicemembers/action'
| extend claimsJson = parse_json(Claims)
| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])
| project-away claimsJson
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Caller
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: CallerIpAddress
version: 2.0.3
kind: Scheduled
Stages and Predicates
Stage 1: source
AzureActivity
Stage 2: where
| where CategoryValue =~ 'Administrative'
Stage 3: where
| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'
Stage 4: where
| where _ResourceId has 'AdFederationService'
Stage 5: where
| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/servicemembers/action'
Stage 6: extend
| extend claimsJson = parse_json(Claims)
Stage 7: extend
| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])
Stage 8: project-away
| project-away claimsJson
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
CategoryValue | eq |
| field:"CategoryValue" kind:eq value:"Administrative" |
OperationNameValue | eq |
| field:"azure_ad::operation_name_value" kind:eq value:"Microsoft.ADHybridHealthService/services/servicemembers/action" |
ResourceProviderValue | eq |
| field:"ResourceProviderValue" kind:eq value:"Microsoft.ADHybridHealthService" |
_ResourceId | match |
| field:"_ResourceId" kind:match value:"AdFederationService" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountName | extend |
AppId | extend |
Name | extend |
UPNSuffix | extend |
Netskope - Anomalous User Behavior (High Volume from Unmanaged Device)
#Detects anomalous user behavior including high data volume transfers from unmanaged devices, unusual access patterns, and suspicious application usage.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Collection | |
| Exfiltration |
Rule Body
id: fa4c4f1c-3c5f-4c3a-a13f-924c30db56e9
name: Netskope - Anomalous User Behavior (High Volume from Unmanaged Device)
description: |
Detects anomalous user behavior including high data volume transfers from unmanaged devices, unusual access patterns, and suspicious application usage.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: NetskopeWebTxConnector
dataTypes:
- NetskopeWebTransactions_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Exfiltration
- Collection
relevantTechniques:
- T1567
- T1074
query: |
let highVolumeThresholdGB = 1;
NetskopeWebTransactions_CL
| where TimeGenerated > ago(1h)
| where isnotempty(CsUsername)
| summarize
TotalBytes = sum(Bytes),
UploadBytes = sum(CsBytes),
DownloadBytes = sum(ScBytes),
UniqueApps = dcount(XCsApp),
Apps = make_set(XCsApp, 20),
UniqueHosts = dcount(CsHost),
Activities = make_set(XCsAppActivity),
Countries = make_set(XCCountry),
Devices = make_set(XCDevice),
AccessMethods = make_set(XCsAccessMethod),
EventCount = count()
by CsUsername, XCDevice, XCsAccessMethod
| extend
TotalGB = round(TotalBytes / 1073741824.0, 3),
UploadGB = round(UploadBytes / 1073741824.0, 3),
DownloadGB = round(DownloadBytes / 1073741824.0, 3)
| where TotalGB > highVolumeThresholdGB
| extend IsUnmanagedDevice = XCDevice =~ 'unmanaged' or XCDevice =~ 'BYOD' or XCDevice =~ 'Personal' or XCDevice =~ 'Unknown' or XCsAccessMethod != 'Client'
| where IsUnmanagedDevice or TotalGB > 5 or UniqueApps > 20
| extend RiskIndicators = strcat_array(array_concat(
iff(IsUnmanagedDevice, dynamic(['Unmanaged Device']), dynamic([])),
iff(TotalGB > 5, dynamic(['High Data Volume']), dynamic([])),
iff(UniqueApps > 20, dynamic(['Many Apps Accessed']), dynamic([])),
iff(array_length(Countries) > 1, dynamic(['Multiple Countries']), dynamic([]))
), ', ')
| project
TimeGenerated = now(),
User = CsUsername,
Device = XCDevice,
AccessMethod = XCsAccessMethod,
TotalDataGB = TotalGB,
UploadGB,
DownloadGB,
UniqueApplications = UniqueApps,
Applications = Apps,
UniqueHosts,
Activities,
Countries,
EventCount,
IsUnmanagedDevice,
RiskIndicators
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: User
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: Device
version: 1.0.0
kind: Scheduled
Stages and Predicates
Parameters
let highVolumeThresholdGB = 1;
Stage 1: source
NetskopeWebTransactions_CL
Stage 2: where
| where TimeGenerated > ago(1h)
Stage 3: where
| where isnotempty(CsUsername)
Stage 4: summarize
| summarize
TotalBytes = sum(Bytes),
UploadBytes = sum(CsBytes),
DownloadBytes = sum(ScBytes),
UniqueApps = dcount(XCsApp),
Apps = make_set(XCsApp, 20),
UniqueHosts = dcount(CsHost),
Activities = make_set(XCsAppActivity),
Countries = make_set(XCCountry),
Devices = make_set(XCDevice),
AccessMethods = make_set(XCsAccessMethod),
EventCount = count()
by CsUsername, XCDevice, XCsAccessMethod
Stage 5: extend
| extend
TotalGB = round(TotalBytes / 1073741824.0, 3),
UploadGB = round(UploadBytes / 1073741824.0, 3),
DownloadGB = round(DownloadBytes / 1073741824.0, 3)
Stage 6: where
| where TotalGB > highVolumeThresholdGB
Stage 7: extend
| extend IsUnmanagedDevice = XCDevice =~ 'unmanaged' or XCDevice =~ 'BYOD' or XCDevice =~ 'Personal' or XCDevice =~ 'Unknown' or XCsAccessMethod != 'Client'
Stage 8: where
| where IsUnmanagedDevice or TotalGB > 5 or UniqueApps > 20
Stage 9: extend
| extend RiskIndicators = strcat_array(array_concat(
iff(IsUnmanagedDevice, dynamic(['Unmanaged Device']), dynamic([])),
iff(TotalGB > 5, dynamic(['High Data Volume']), dynamic([])),
iff(UniqueApps > 20, dynamic(['Many Apps Accessed']), dynamic([])),
iff(array_length(Countries) > 1, dynamic(['Multiple Countries']), dynamic([]))
), ', ')
Stage 10: project
| project
TimeGenerated = now(),
User = CsUsername,
Device = XCDevice,
AccessMethod = XCsAccessMethod,
TotalDataGB = TotalGB,
UploadGB,
DownloadGB,
UniqueApplications = UniqueApps,
Applications = Apps,
UniqueHosts,
Activities,
Countries,
EventCount,
IsUnmanagedDevice,
RiskIndicators
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
CsUsername | is_not_null | field:"CsUsername" kind:is_not_null | |
IsUnmanagedDevice | eq |
| field:"IsUnmanagedDevice" kind:eq value:"true" |
TotalGB | gt |
| field:"TotalGB" kind:gt |
UniqueApps | gt |
| field:"UniqueApps" kind:gt value:"20" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccessMethod | project |
Activities | project |
Applications | project |
Countries | project |
Device | project |
DownloadGB | project |
EventCount | project |
IsUnmanagedDevice | project |
RiskIndicators | project |
TimeGenerated | project |
TotalDataGB | project |
UniqueApplications | project |
UniqueHosts | project |
UploadGB | project |
User | project |
NordPass - Vault export
#This will alert you if the vault has been exported, allowing you to review and evaluate the incident to mitigate potential risks. NOTE: The organization can control whether it allows its members to export the vault, although we recommend that it always be disabled.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Exfiltration |
Rule Body
id: c7f14b43-7625-4516-b137-30b7fda65bcf
name: NordPass - Vault export
kind: Scheduled
version: 1.0.0
displayName: Vault export
description: |
This will alert you if the vault has been exported, allowing you to review and evaluate the incident to mitigate potential risks.
NOTE: The organization can control whether it allows its members to export the vault, although we recommend that it always be disabled.
severity: High
query: |
NordPassEventLogs_CL
| where event_type == "item_access"
| where action == "vault_exported"
| extend TargetEmail = user_email
requiredDataConnectors:
- connectorId: NordPass
dataTypes:
- NordPassEventLogs_CL
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
- Exfiltration
relevantTechniques:
- T1020
incidentConfiguration:
createIncident: false
entityMappings:
- entityType: Mailbox
fieldMappings:
- identifier: MailboxPrimaryAddress
columnName: TargetEmail
Stages and Predicates
Stage 1: source
NordPassEventLogs_CL
Stage 2: where
| where event_type == "item_access"
Stage 3: where
| where action == "vault_exported"
Stage 4: extend
| extend TargetEmail = user_email
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action | eq |
| field:"action" kind:eq value:"vault_exported" |
event_type | eq |
| field:"event_type" kind:eq value:"item_access" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
TargetEmail | extend |
Samsung Knox - Application Privilege Escalation or Change Events
#This is a third-party alert feed, not a detection over modeled telemetry. The vendor product raised the finding; this rule forwards it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.
When a Knox mobile app has transitioned from an acceptable uid/esuid/fsuid to a different, non-App id.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Rule Body
id: 215e89ca-cdbc-4661-b8b2-7041f6ecc7fb
name: Samsung Knox - Application Privilege Escalation or Change Events
version: 1.0.2
kind: NRT
description: When a Knox mobile app has transitioned from an acceptable uid/esuid/fsuid to a different, non-App id.
severity: High
status: Available
requiredDataConnectors:
- connectorId: SamsungDCDefinition
dataTypes:
- Samsung_Knox_Process_CL
tactics:
- PrivilegeEscalation
relevantTechniques:
- T1548
query: |
Samsung_Knox_Process_CL
| where Name == "PROCESS_PRIVILEGE_ESCALATION"
| where MitreTtp has "T1548"
suppressionEnabled: false
suppressionDuration: PT5H
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
eventGroupingSettings:
aggregationKind: SingleAlert
Stages and Predicates
Stage 1: source
Samsung_Knox_Process_CL
Stage 2: where
| where Name == "PROCESS_PRIVILEGE_ESCALATION"
Stage 3: where
| where MitreTtp has "T1548"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
MitreTtp | match |
| field:"MitreTtp" kind:match value:"T1548" |
Name | eq |
| field:"Name" kind:eq value:"PROCESS_PRIVILEGE_ESCALATION" |
Storage Deleted
#Detects when storage is deleted from Veeam Backup & Replication. This might indicate unauthorized removal of critical components.
Rule Body
id: 7cf8c19b-6cd2-4d0c-814b-45d34e68568b
name: Storage Deleted
description: Detects when storage is deleted from Veeam Backup & Replication. This
might indicate unauthorized removal of critical components.
severity: High
status: Available
requiredDataConnectors:
- connectorId: Syslog
dataTypes:
- Syslog
- connectorId: SyslogAma
dataTypes:
- Syslog
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: "Veeam_GetSecurityEvents\n| where instanceId == 41402\n| extend Name = extract(\"\
Name=\\\"([^\\\"]*)\\\"\", 1, SyslogMessage)\n| project\n Date = format_datetime(TimeGenerated,\
\ 'dd.MM.yyyy HH:mm'),\n DataSource = original_host,\n EventId = instanceId,\n\
\ [\"User Name\"] = user,\n [\"Object Name\"] = Name,\n MessageDetails\
\ = Description,\n Severity = SeverityDescription"
version: 1.0.1
kind: Scheduled
customDetails:
Date: Date
VbrHostName: DataSource
EventId: EventId
MessageDetails: MessageDetails
Severity: Severity
Stages and Predicates
Stage 1: source
Veeam_GetSecurityEvents
Stage 2: where
| where instanceId == 41402
Stage 3: extend
| extend Name = extract("Name=\"([^\"]*)\"", 1, SyslogMessage)
Stage 4: project
| project
Date = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),
DataSource = original_host,
EventId = instanceId,
["User Name"] = user,
["Object Name"] = Name,
MessageDetails = Description,
Severity = SeverityDescription
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
instanceId | eq |
| field:"instanceId" kind:eq value:"41402" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DataSource | project |
Date | project |
EventId | project |
MessageDetails | project |
Object Name | project |
Severity | project |
User Name | project |
TI Map IP entity to Network Session Events (ASIM Network Session schema)
#This rule identifies a match Network Sessions for which the source or destination IP address is a known IoC. This analytic rule uses ASIM and supports any built-in or custom source that supports the ASIM NetworkSession schema
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry Coverage
Rule Body
id: 54f4ceb4-fd83-4633-b5b0-c0de9feb8890
name: TI Map IP entity to Network Session Events (ASIM Network Session schema)
description: |
'This rule identifies a match Network Sessions for which the source or destination IP address is a known IoC. This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM NetworkSession schema'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: AWSS3
dataTypes:
- AWSVPCFlow
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceNetworkEvents
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsForwardedEvents
dataTypes:
- WindowsEvent
- connectorId: Zscaler
dataTypes:
- CommonSecurityLog
- connectorId: MicrosoftSysmonForLinux
dataTypes:
- Syslog
- connectorId: PaloAltoNetworks
dataTypes:
- CommonSecurityLog
- connectorId: AzureMonitor(VMInsights)
dataTypes:
- VMConnection
- connectorId: AzureFirewall
dataTypes:
- AzureDiagnostics
- connectorId: AzureNSG
dataTypes:
- AzureDiagnostics
- connectorId: CiscoASA
dataTypes:
- CommonSecurityLog
- connectorId: Corelight
dataTypes:
- Corelight_CL
- connectorId: AIVectraStream
dataTypes:
- VectraStream
- connectorId: CheckPoint
dataTypes:
- CommonSecurityLog
- connectorId: Fortinet
dataTypes:
- CommonSecurityLog
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelIndicators
- connectorId: CiscoMeraki
dataTypes:
- Syslog
- CiscoMerakiNativePoller
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelIndicators
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
relevantTechniques:
- T1071
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let IP_TI = materialize (
ThreatIntelIndicators
//extract key part of kv pair
| extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
| where IndicatorType in ("ipv4-addr", "ipv6-addr", "network-traffic")
| extend NetworkSourceIP = toupper(ObservableValue)
| extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
| where TimeGenerated >= ago(ioc_lookBack)
| extend TI_ipEntity = NetworkSourceIP
| where TI_ipEntity != "NO_IP"
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue
| where IsActive and (ValidUntil > now() or isempty(ValidUntil))
);
IP_TI
| project-reorder *, Tags, TrafficLightProtocolLevel, NetworkSourceIP, Type, TI_ipEntity
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique
(
_Im_NetworkSession (starttime=ago(dt_lookBack))
| where isnotempty(SrcIpAddr)
| summarize imNWS_mintime=min(TimeGenerated), imNWS_maxtime=max(TimeGenerated) by SrcIpAddr, DstIpAddr, Dvc, EventProduct, EventVendor
| lookup (IP_TI | project TI_ipEntity, IsActive) on $left.SrcIpAddr == $right.TI_ipEntity
| project-rename SrcMatch = IsActive
| lookup (IP_TI | project TI_ipEntity, IsActive) on $left.DstIpAddr == $right.TI_ipEntity
| project-rename DstMatch = IsActive
| where SrcMatch or DstMatch
| extend
IoCIP = iff(SrcMatch, SrcIpAddr, DstIpAddr),
IoCDirection = iff(SrcMatch, "Source", "Destination")
)on $left.TI_ipEntity == $right.IoCIP
| where imNWS_mintime < ValidUntil
| extend Description = tostring(parse_json(Data).description)
| extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(parse_json(Data).labels))
| project imNWS_mintime, imNWS_maxtime, Description, ActivityGroupNames, Id, Type, ValidUntil, Confidence, SrcIpAddr, DstIpAddr, IoCDirection, IoCIP, Dvc, EventVendor, EventProduct
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IoCIP
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
customDetails:
EventStartTime: imNWS_mintime
EventEndTime: imNWS_maxtime
IoCDescription: Description
ActivityGroupNames: ActivityGroupNames
IndicatorId: Id
ThreatType: Type
IoCExpirationTime: ValidUntil
IoCConfidenceScore: Confidence
IoCIPDirection: IoCDirection
alertDetailsOverride:
alertDisplayNameFormat: A network session {{IoCDirection}} address {{IoCIP}} matched an IoC.
alertDescriptionFormat: The {{IoCDirection}} address {{IoCIP}} of a network session matched a known indicator of compromise of {{Type}}. Consult the threat intelligence blead for more information on the indicator.
tags:
- Schema: ASIMNetworkSession
SchemaVersion: 0.2.4
version: 1.2.10
kind: Scheduled
Stages and Predicates
Parameters
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let IP_TI is inlined into the numbered stages below.
Stages 1 to 10 define let IP_TI as the rule's main pipeline source. Stages 11 to 16 use it.
Stage 1: source
ThreatIntelIndicators
Stage 2: extend
| extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
Stage 3: where
| where IndicatorType in ("ipv4-addr", "ipv6-addr", "network-traffic")
Stage 4: extend
| extend NetworkSourceIP = toupper(ObservableValue)
Stage 5: extend
| extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
Stage 6: where
| where TimeGenerated >= ago(ioc_lookBack)
Stage 7: extend
| extend TI_ipEntity = NetworkSourceIP
Stage 8: where
| where TI_ipEntity != "NO_IP"
Stage 9: summarize
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue
Stage 10: where
| where IsActive and (ValidUntil > now() or isempty(ValidUntil))
Stage 11: project-reorder
IP_TI
| project-reorder *, Tags, TrafficLightProtocolLevel, NetworkSourceIP, Type, TI_ipEntity
Stage 12: join
join kind=innerunique (_Im_NetworkSession) on $left.TI_ipEntity, $right.IoCIP
Stage 13: where
where imNWS_mintime < ValidUntil
Stage 14: extend
extend Description
Stage 15: extend
extend ActivityGroupNames
Stage 16: project
project ActivityGroupNames, Confidence, Description, DstIpAddr, Dvc, EventProduct, EventVendor, Id, IoCDirection, IoCIP, SrcIpAddr, Type, ValidUntil, imNWS_maxtime, imNWS_mintime
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DstMatch | eq |
| field:"DstMatch" kind:eq value:"true" |
IndicatorType | in |
| field:"IndicatorType" kind:in |
IsActive | eq |
| field:"IsActive" kind:eq value:"true" |
SrcIpAddr | is_not_null | field:"SrcIpAddr" kind:is_not_null | |
SrcMatch | eq |
| field:"SrcMatch" kind:eq value:"true" |
TI_ipEntity | ne |
| field:"TI_ipEntity" kind:ne value:"NO_IP" |
ValidUntil | is_null | field:"ValidUntil" kind:is_null |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActivityGroupNames | project |
Confidence | project |
Description | project |
DstIpAddr | project |
Dvc | project |
EventProduct | project |
EventVendor | project |
Id | project |
IoCDirection | project |
IoCIP | project |
SrcIpAddr | project |
Type | project |
ValidUntil | project |
imNWS_maxtime | project |
imNWS_mintime | project |
User joining Zoom meeting from suspicious timezone
#'The alert shows users that join a Zoom meeting from a time zone other than the one the meeting was created in. You can also whitelist known good time zones in the tz_whitelist value using the tz database name format https://en.wikipedia.org/wiki/List_of_tz_database_time_zones'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Privilege Escalation |
Rule Body
id: 58fc0170-0877-4ea8-a9ff-d805e361cfae
name: User joining Zoom meeting from suspicious timezone
description: |
'The alert shows users that join a Zoom meeting from a time zone other than the one the meeting was created in.
You can also whitelist known good time zones in the tz_whitelist value using the tz database name format https://en.wikipedia.org/wiki/List_of_tz_database_time_zones'
severity: Low
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- PrivilegeEscalation
relevantTechniques:
- T1078
query: |
let schedule_lookback = 14d;
let join_lookback = 1d;
// If you want to whitelist specific timezones include them in a list here
let tz_whitelist = dynamic([]);
let meetings = (
ZoomLogs
| where TimeGenerated >= ago(schedule_lookback)
| where Event =~ "meeting.created"
| extend MeetingId = tostring(parse_json(MeetingEvents).MeetingId)
| extend SchedTimezone = tostring(parse_json(MeetingEvents).Timezone));
ZoomLogs
| where TimeGenerated >= ago(join_lookback)
| where Event =~ "meeting.participant_joined"
| extend JoinedTimeZone = tostring(parse_json(MeetingEvents).Timezone)
| extend MeetingName = tostring(parse_json(MeetingEvents).MeetingName)
| extend MeetingId = tostring(parse_json(MeetingEvents).MeetingId)
| where JoinedTimeZone !in (tz_whitelist)
| join (meetings) on MeetingId
| where SchedTimezone != JoinedTimeZone
| project TimeGenerated, MeetingName, JoiningUser=payload_object_participant_user_name_s, JoinedTimeZone, SchedTimezone, MeetingScheduler=User1
| extend AccountName = tostring(split(JoiningUser, "@")[0]), AccountUPNSuffix = tostring(split(JoiningUser, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: JoiningUser
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
version: 1.0.4
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
support:
tier: Community
categories:
domains: [ "Security - Others" ]
Stages and Predicates
Parameters
let schedule_lookback = 14d;
let join_lookback = 1d;
let tz_whitelist = dynamic([]);
Let Binding: meetings
let meetings = (
ZoomLogs
| where TimeGenerated >= ago(schedule_lookback)
| where Event =~ "meeting.created"
| extend MeetingId = tostring(parse_json(MeetingEvents).MeetingId)
| extend SchedTimezone = tostring(parse_json(MeetingEvents).Timezone));
Stage 1: source
ZoomLogs
Stage 2: where
| where TimeGenerated >= ago(join_lookback)
Stage 3: where
| where Event =~ "meeting.participant_joined"
Stage 4: extend (3 consecutive steps)
| extend JoinedTimeZone = tostring(parse_json(MeetingEvents).Timezone)
| extend MeetingName = tostring(parse_json(MeetingEvents).MeetingName)
| extend MeetingId = tostring(parse_json(MeetingEvents).MeetingId)
Stage 5: where
| where JoinedTimeZone !in (tz_whitelist)
Stage 6: join
| join (meetings) on MeetingId
Stage 7: where
where SchedTimezone != JoinedTimeZone
Stage 8: project
project JoinedTimeZone, JoiningUser, MeetingName, MeetingScheduler, SchedTimezone, TimeGenerated
Stage 9: extend
extend AccountName, AccountUPNSuffix
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Event | eq |
| field:"Event" kind:eq |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
JoinedTimeZone | eq | [] | excludes:JoinedTimeZone field:"JoinedTimeZone" value:"[]" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
JoinedTimeZone | project |
JoiningUser | project |
MeetingName | project |
MeetingScheduler | project |
SchedTimezone | project |
TimeGenerated | project |
AccountName | extend |
AccountUPNSuffix | extend |
Valimail Enforce - High-Value User Management Event
#This query searches for high-severity user management events such as user deletion or deactivation in Valimail Enforce, which may indicate unauthorized access or insider threat.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation | |
| Impact |
Rule Body
id: e960f5b0-cd80-474a-996a-013ff3989772
name: Valimail Enforce - High-Value User Management Event
description: |
This query searches for high-severity user management events such as user deletion or deactivation
in Valimail Enforce, which may indicate unauthorized access or insider threat.
severity: High
status: Available
requiredDataConnectors:
- connectorId: ValimailEnforce
dataTypes:
- ValimailEnforceEvents_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
- PrivilegeEscalation
relevantTechniques:
- T1531
- T1078
query: |
ValimailEnforceEvents_CL
| where EventCategory == "UserManagement"
| where EventSeverity == "High"
| where IsHighValueEvent == true
| summarize
EventCount = count(),
FirstSeen = min(PerformedAt),
LastSeen = max(PerformedAt),
AffectedUsers = make_set(Subject),
Actions = make_set(EventType)
by User, EventCategory
| extend
AccountName = tostring(split(User, "@")[0]),
AccountDomain = tostring(split(User, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountDomain
alertDetailsOverride:
alertDisplayNameFormat: "High-value user management action by {{User}}"
alertDescriptionFormat: |
User '{{User}}' performed {{EventCount}} high-value user management
action(s) in Valimail Enforce. Actions: {{Actions}}
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 1d
matchingMethod: Selected
groupByEntities:
- Account
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
ValimailEnforceEvents_CL
Stage 2: where
| where EventCategory == "UserManagement"
Stage 3: where
| where EventSeverity == "High"
Stage 4: where
| where IsHighValueEvent == true
Stage 5: summarize
| summarize
EventCount = count(),
FirstSeen = min(PerformedAt),
LastSeen = max(PerformedAt),
AffectedUsers = make_set(Subject),
Actions = make_set(EventType)
by User, EventCategory
Stage 6: extend
| extend
AccountName = tostring(split(User, "@")[0]),
AccountDomain = tostring(split(User, "@")[1])
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventCategory | eq |
| field:"EventCategory" kind:eq value:"UserManagement" |
EventSeverity | eq |
| field:"EventSeverity" kind:eq value:"High" |
IsHighValueEvent | eq |
| field:"IsHighValueEvent" kind:eq value:"true" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Actions | summarize |
AffectedUsers | summarize |
EventCategory | summarize |
EventCount | summarize |
FirstSeen | summarize |
LastSeen | summarize |
User | summarize |
AccountDomain | extend |
AccountName | extend |
Veeam ONE Malware Detection Change Tracking
#This is a third-party alert feed, not a detection over modeled telemetry. The vendor product raised the finding; this rule forwards it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.
Detects changes in Veeam ONE malware detection tracking.
Rule Body
id: 2a860019-0eda-4b49-bc62-8f683aed4929
name: Veeam ONE Malware Detection Change Tracking
description: Detects changes in Veeam ONE malware detection tracking.
severity: High
status: Available
requiredDataConnectors:
- connectorId: VeeamCustomTablesDataConnector
dataTypes:
- VeeamOneTriggeredAlarms_CL
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: VeeamOneTriggeredAlarms_CL | where PredefinedAlarmId == 403
version: 1.0.1
kind: Scheduled
customDetails:
PredefinedAlarmId: PredefinedAlarmId
TriggeredAlarmId: TriggeredAlarmId
Description: Description
Name: Name
VoneHostName: VoneHostName
TriggeredTime: TriggeredTime
Status: Status
Comment: Comment
ObjectId: ObjectId
ObjectName: ObjectName
ObjectType: ObjectType
Stages and Predicates
Stage 1: source
VeeamOneTriggeredAlarms_CL
Stage 2: where
| where PredefinedAlarmId == 403
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
PredefinedAlarmId | eq |
| field:"PredefinedAlarmId" kind:eq value:"403" |
Veeam ONE VM with No Replica
#This is a third-party alert feed, not a detection over modeled telemetry. The vendor product raised the finding; this rule forwards it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.
Detects Veeam ONE VMs with no replica configuration.
Rule Body
id: 128ea2a4-1047-4f28-ad55-b1b88357d172
name: Veeam ONE VM with No Replica
description: Detects Veeam ONE VMs with no replica configuration.
severity: High
status: Available
requiredDataConnectors:
- connectorId: VeeamCustomTablesDataConnector
dataTypes:
- VeeamOneTriggeredAlarms_CL
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: VeeamOneTriggeredAlarms_CL | where PredefinedAlarmId == 331
version: 1.0.1
kind: Scheduled
customDetails:
PredefinedAlarmId: PredefinedAlarmId
TriggeredAlarmId: TriggeredAlarmId
Description: Description
Name: Name
VoneHostName: VoneHostName
TriggeredTime: TriggeredTime
Status: Status
Comment: Comment
ObjectId: ObjectId
ObjectName: ObjectName
ObjectType: ObjectType
Stages and Predicates
Stage 1: source
VeeamOneTriggeredAlarms_CL
Stage 2: where
| where PredefinedAlarmId == 331
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
PredefinedAlarmId | eq |
| field:"PredefinedAlarmId" kind:eq value:"331" |