Detection rules › Kusto
Kusto rules: 0z
Acronis - Login from Abnormal IP - Low Occurrence
#Suspicious login from an IP address observed up to two times in the last two weeks.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule Body
id: 84037130-a623-46c2-9144-0c0955ac4112
name: Acronis - Login from Abnormal IP - Low Occurrence
description: Suspicious login from an IP address observed up to two times in the last two weeks.
severity: Medium
query: |
CommonSecurityLog
| where DeviceVendor == "Acronis audit"
| extend initiator_ip = tostring(parse_json(DeviceCustomString1).initiator_ip)
| summarize LoginCount = count() by initiator_ip
| where LoginCount <= 2
| order by LoginCount asc
queryFrequency: 1d
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
relevantTechniques:
- T1078
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: true
lookbackDuration: P7D
matchingMethod: Selected
groupByEntities:
- IP
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: 'Acronis - Login from Abnormal IP ({{initiator_ip}}) - Low Occurrence ({{LoginCount}})'
alertDynamicProperties: []
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: initiator_ip
version: 1.0.0
kind: Scheduled
requiredDataConnectors: []
Stages and Predicates
Stage 1: source
CommonSecurityLog
Stage 2: where
| where DeviceVendor == "Acronis audit"
Stage 3: extend
| extend initiator_ip = tostring(parse_json(DeviceCustomString1).initiator_ip)
Stage 4: summarize
| summarize LoginCount = count() by initiator_ip
Stage 5: where
| where LoginCount <= 2
Stage 6: sort
| order by LoginCount asc
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DeviceVendor | eq |
| field:"DeviceVendor" kind:eq value:"Acronis audit" |
LoginCount | le |
| field:"LoginCount" kind:le value:"2" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
LoginCount | summarize |
initiator_ip | summarize |
BitSight - compromised systems detected
#'Rule helps to detect whenever there is a compromised systems found in BitSight.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution |
Rule Body
id: d68b758a-b117-4cb8-8e1d-dcab5a4a2f21
name: BitSight - compromised systems detected
description: |
'Rule helps to detect whenever there is a compromised systems found in BitSight.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: BitSight
dataTypes:
- BitSightFindingsData
queryFrequency: 1d
queryPeriod: 24h
triggerOperator: GreaterThan
triggerThreshold: 0
tactics:
- Execution
relevantTechniques:
- T1203
query: |
let timeframe = 24h;
BitSightFindingsData
| where ingestion_time() > ago(timeframe)
| where RiskCategory == "Compromised Systems"
| extend Severity = toreal(Severity)
| extend Severity = case( Severity <= 6.9 and Severity >= 4.0, "Low",
Severity <= 8.9 and Severity >= 7.0, "Medium",
Severity <= 10.0 and Severity >= 9.0, "High",
"Informational")
| project FirstSeen, CompanyName, Severity, RiskCategory, RiskVector, TemporaryId
incidentConfiguration:
createIncident: true
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: 'BitSight: Alert for {{RiskVector}} in {{CompanyName}} from BitSight'
alertDescriptionFormat: 'Alert is generated for {{CompanyName}}.\n\nRisk Vector: {{RiskVector}}\nTemporaryId: {{TemporaryId}}\nRisk Category: Compromised Systems'
alertSeverityColumnName: Severity
entityMappings:
- entityType: Malware
fieldMappings:
- identifier: Name
columnName: RiskVector
- identifier: Category
columnName: RiskCategory
version: 1.0.2
kind: Scheduled
Stages and Predicates
Parameters
let timeframe = 24h;
Stage 1: source
BitSightFindingsData
Stage 2: where
| where ingestion_time() > ago(timeframe)
Stage 3: where
| where RiskCategory == "Compromised Systems"
Stage 4: extend
| extend Severity = toreal(Severity)
Stage 5: extend
| extend Severity = case( Severity <= 6.9 and Severity >= 4.0, "Low",
Severity <= 8.9 and Severity >= 7.0, "Medium",
Severity <= 10.0 and Severity >= 9.0, "High",
"Informational")
Severity =Severity <= 6.9 and Severity >= 4.0"Low"Severity <= 8.9 and Severity >= 7.0"Medium"Severity <= 10.0 and Severity >= 9.0"High""Informational"Stage 6: project
| project FirstSeen, CompanyName, Severity, RiskCategory, RiskVector, TemporaryId
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
RiskCategory | eq |
| field:"RiskCategory" kind:eq value:"Compromised Systems" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
CompanyName | project |
FirstSeen | project |
RiskCategory | project |
RiskVector | project |
Severity | project |
TemporaryId | project |
Cisco Umbrella - Hack Tool User-Agent Detected
#'Detects suspicious user agent strings used by known hack tools'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control | No specific technique |
Rule Body
id: 8d537f3c-094f-430c-a588-8a87da36ee3a
name: Cisco Umbrella - Hack Tool User-Agent Detected
description: |
'Detects suspicious user agent strings used by known hack tools'
severity: Medium
requiredDataConnectors:
- connectorId: CiscoUmbrellaDataConnector
dataTypes:
- Cisco_Umbrella_proxy_CL
queryFrequency: 15m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
query: |
let timeframe = 15m;
let user_agents=dynamic([
'(hydra)',
' arachni/',
' BFAC ',
' brutus ',
' cgichk ',
'core-project/1.0',
' crimscanner/',
'datacha0s',
'dirbuster',
'domino hunter',
'dotdotpwn',
'FHScan Core',
'floodgate',
'get-minimal',
'gootkit auto-rooter scanner',
'grendel-scan',
' inspath ',
'internet ninja',
'jaascois',
' zmeu ',
'masscan',
' metis ',
'morfeus fucking scanner',
'n-stealth',
'nsauditor',
'pmafind',
'security scan',
'springenwerk',
'teh forest lobster',
'toata dragostea',
' vega/',
'voideye',
'webshag',
'webvulnscan',
' whcc/',
' Havij',
'absinthe',
'bsqlbf',
'mysqloit',
'pangolin',
'sql power injector',
'sqlmap',
'sqlninja',
'uil2pn',
'ruler',
'Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)'
]);
Cisco_Umbrella
| where EventType == "proxylogs"
| where TimeGenerated > ago(timeframe)
| where HttpUserAgentOriginal has_any (user_agents)
| extend Message = "Hack Tool User Agent"
| project Message, SrcIpAddr, DstIpAddr, UrlOriginal, TimeGenerated, HttpUserAgentOriginal
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: UrlOriginal
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
version: 1.1.2
kind: Scheduled
Stages and Predicates
Parameters
let timeframe = 15m;
Let Binding: user_agents
let user_agents = dynamic([
'(hydra)',
' arachni/',
' BFAC ',
' brutus ',
' cgichk ',
'core-project/1.0',
' crimscanner/',
'datacha0s',
'dirbuster',
'domino hunter',
'dotdotpwn',
'FHScan Core',
'floodgate',
'get-minimal',
'gootkit auto-rooter scanner',
'grendel-scan',
' inspath ',
'internet ninja',
'jaascois',
' zmeu ',
'masscan',
' metis ',
'morfeus fucking scanner',
'n-stealth',
'nsauditor',
'pmafind',
'security scan',
'springenwerk',
'teh forest lobster',
'toata dragostea',
' vega/',
'voideye',
'webshag',
'webvulnscan',
' whcc/',
' Havij',
'absinthe',
'bsqlbf',
'mysqloit',
'pangolin',
'sql power injector',
'sqlmap',
'sqlninja',
'uil2pn',
'ruler',
'Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)'
]);
Stage 1: source
Cisco_Umbrella
Stage 2: where
| where EventType == "proxylogs"
Stage 3: where
| where TimeGenerated > ago(timeframe)
Stage 4: where
| where HttpUserAgentOriginal has_any (user_agents)
Stage 5: extend
| extend Message = "Hack Tool User Agent"
Stage 6: project
| project Message, SrcIpAddr, DstIpAddr, UrlOriginal, TimeGenerated, HttpUserAgentOriginal
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventType | eq |
| field:"EventType" kind:eq value:"proxylogs" |
HttpUserAgentOriginal | match |
| field:"HttpUserAgentOriginal" kind:match |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DstIpAddr | project |
HttpUserAgentOriginal | project |
Message | project |
SrcIpAddr | project |
TimeGenerated | project |
UrlOriginal | project |
Cyble Vision Alerts Vulnerability
#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 SSL/TLS and application vulnerabilities from CybleVision. Extracts host, IP, port, severity, vulnerability ID and first-seen metadata using the Alerts_Vulnerability parser. Incidents grouped per service.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Reconnaissance | |
| Execution | |
| Discovery |
Rule Body
id: 0e0cdda9-4536-4cc9-91cf-736e8957ed26
name: Cyble Vision Alerts Vulnerability
description: |
'Detects SSL/TLS and application vulnerabilities from CybleVision. Extracts host, IP, port, severity, vulnerability ID and first-seen metadata using the Alerts_Vulnerability parser. Incidents grouped per service.'
severity: Low
status: Available
requiredDataConnectors:
- connectorId: CybleVisionAlerts
dataTypes:
- CybleVisionAlerts_CL
enabled: true
queryFrequency: 30m
queryPeriod: 30m
triggerOperator: GreaterThan
triggerThreshold: 0
suppressionDuration: PT5H
eventGroupingSettings:
aggregationKind: AlertPerResult
tactics:
- Reconnaissance
- Execution
- Discovery
relevantTechniques:
- T1595
- T1203
- T1046
subTechniques: []
query: |
Alerts_vulnerability
| where Service == "vulnerability"
| extend MappedSeverity = Severity
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
alertDetailsOverride:
alertDisplayNameFormat: CybleVision Vulnerability {{V_Title}}
alertDescriptionFormat: |
A vulnerability was detected for host {{V_Host}} (IP {{V_IP}}, Port {{V_Port}}).
alertDynamicProperties: []
customDetails:
MappedSeverity: Severity
Status: Status
AlertID: AlertID
Service: Service
Title: V_Title
V_Port: V_Port
V_VulnID: V_VulnID
V_Type: V_Type
V_Confidence: V_Confidence
V_FirstSeen: V_FirstSeen
V_LastSeen: V_LastSeen
entityMappings:
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: V_Host
- entityType: IP
fieldMappings:
- identifier: Address
columnName: V_IP
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
Alerts_vulnerability
Stage 2: where
| where Service == "vulnerability"
Stage 3: extend
| extend MappedSeverity = Severity
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Service | eq |
| field:"Service" kind:eq value:"vulnerability" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
MappedSeverity | extend |
Detecting UAC bypass - elevated COM interface
#This query identifies processes spawned with high integrity from dllhost.exe with a command line that contains one of three specific CLSID GUIDs.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft Defender for Endpoint | DeviceProcessEvents action any: Process activity |
Rule Body
id: 2d5efc71-2e91-4ca2-8506-857eecb453ec
name: Detecting UAC bypass - elevated COM interface
description: |
This query identifies processes spawned with high integrity from dllhost.exe with a command line that contains one of three specific CLSID GUIDs.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceProcessEvents
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
relevantTechniques:
- T1490
query: |
DeviceProcessEvents
| where InitiatingProcessFileName =~ "dllhost.exe"
| where ProcessIntegrityLevel == "High"
| where InitiatingProcessCommandLine has_any ("E9495B87-D950-4AB5-87A5-FF6D70BF3E90", "3E5FC7F9-9A51-4367-9063-A120244FBEC7", "D2E7041B-2927-42fb-8E9F-7CE93B6DC937")
entityMappings:
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: DeviceName
- entityType: Account
fieldMappings:
- identifier: Sid
columnName: AccountSid
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountDomain
- entityType: Process
fieldMappings:
- identifier: CommandLine
columnName: ProcessCommandLine
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
DeviceProcessEvents
Stage 2: where
| where InitiatingProcessFileName =~ "dllhost.exe"
Stage 3: where
| where ProcessIntegrityLevel == "High"
Stage 4: where
| where InitiatingProcessCommandLine has_any ("E9495B87-D950-4AB5-87A5-FF6D70BF3E90", "3E5FC7F9-9A51-4367-9063-A120244FBEC7", "D2E7041B-2927-42fb-8E9F-7CE93B6DC937")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
InitiatingProcessCommandLine | match |
| field:"ParentCommandLine" kind:match |
InitiatingProcessFileName | eq |
| field:"parent_process_basename" kind:eq value:"dllhost.exe" |
ProcessIntegrityLevel | eq |
| field:"IntegrityLevel" kind:eq value:"High" |
Detecting UAC bypass - modify Windows Store settings
#This query identifies modification a specific registry key and then launching wsreset.exe that resets the Windows Store settings.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft Defender for Endpoint | DeviceProcessEvents action any: Process activity |
Rule Body
id: 8b8fbf9c-35d4-474b-8151-a40173521293
name: Detecting UAC bypass - modify Windows Store settings
description: |
This query identifies modification a specific registry key and then launching wsreset.exe that resets the Windows Store settings.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceProcessEvents
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
relevantTechniques:
- T1490
query: |
DeviceProcessEvents
| where InitiatingProcessFileName =~ "wsreset.exe"
| where ProcessIntegrityLevel == "High"
entityMappings:
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: DeviceName
- entityType: Account
fieldMappings:
- identifier: Sid
columnName: AccountSid
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountDomain
- entityType: Process
fieldMappings:
- identifier: CommandLine
columnName: ProcessCommandLine
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
DeviceProcessEvents
Stage 2: where
| where InitiatingProcessFileName =~ "wsreset.exe"
Stage 3: where
| where ProcessIntegrityLevel == "High"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
InitiatingProcessFileName | eq |
| field:"parent_process_basename" kind:eq value:"wsreset.exe" |
ProcessIntegrityLevel | eq |
| field:"IntegrityLevel" kind:eq value:"High" |
Excessive NXDOMAIN DNS Queries
#'This creates an incident in the event a client generates excessive amounts of DNS queries for non-existent domains.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Rule Body
id: b8266f81-2715-41a6-9062-42486cbc9c73
name: Excessive NXDOMAIN DNS Queries
description: |
'This creates an incident in the event a client generates excessive amounts of DNS queries for non-existent domains.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: SyslogAma
datatypes:
- Syslog
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
relevantTechniques:
- T1568
- T1008
query: |
let threshold = 200;
Infoblox_dnsclient
| where isnotempty(DnsResponseCode)
| where DnsResponseCode =~ "NXDOMAIN"
| summarize count() by SrcIpAddr, bin(TimeGenerated,15m)
| where count_ > threshold
| join kind=inner (Infoblox_dnsclient
| where isnotempty(DnsResponseCode)
| where DnsResponseCode =~ "NXDOMAIN"
) on SrcIpAddr
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
version: 1.0.5
kind: Scheduled
Stages and Predicates
Parameters
let threshold = 200;
Stage 1: source
Infoblox_dnsclient
Stage 2: where
| where isnotempty(DnsResponseCode)
Stage 3: where
| where DnsResponseCode =~ "NXDOMAIN"
Stage 4: summarize
| summarize count() by SrcIpAddr, bin(TimeGenerated,15m)
Stage 5: where
| where count_ > threshold
Stage 6: join
| join kind=inner (Infoblox_dnsclient
| where isnotempty(DnsResponseCode)
| where DnsResponseCode =~ "NXDOMAIN"
) on SrcIpAddr
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DnsResponseCode | eq |
| field:"DnsResponseCode" kind:eq value:"NXDOMAIN" |
DnsResponseCode | is_not_null | field:"DnsResponseCode" kind:is_not_null | |
count_ | gt |
| field:"count_" kind:gt value:"200" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
SrcIpAddr | summarize |
Gain Code Execution on ADFS Server via SMB + Remote Service or Scheduled Task
#This query detects instances where an attacker has gained the ability to execute code on an ADFS Server through SMB and Remote Service or Scheduled Task.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Lateral Movement |
Telemetry Coverage
Rule Body
id: 12dcea64-bec2-41c9-9df2-9f28461b1295
name: Gain Code Execution on ADFS Server via SMB + Remote Service or Scheduled Task
description: |
'This query detects instances where an attacker has gained the ability to execute code on an ADFS Server through SMB and Remote Service or Scheduled Task.'
severity: Medium
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvent
queryFrequency: 1d
queryPeriod: 7d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- LateralMovement
relevantTechniques:
- T1210
tags:
- Solorigate
- NOBELIUM
query: |
let timeframe = 1d;
// Adjust for a longer timeframe for identifying ADFS Servers
let lookback = 6d;
// Identify ADFS Servers
let ADFS_Servers = (
SecurityEvent
| where TimeGenerated > ago(timeframe+lookback)
| where EventID == 4688 and SubjectLogonId != "0x3e4"
| where NewProcessName has "Microsoft.IdentityServer.ServiceHost.exe"
| distinct Computer
);
SecurityEvent
| where TimeGenerated > ago(timeframe)
| where Computer in~ (ADFS_Servers)
| where Account !endswith "$"
// Check for scheduled task events
| where EventID in (4697, 4698, 4699, 4700, 4701, 4702)
| extend EventDataParsed = parse_xml(EventData)
| extend SubjectLogonId = tostring(EventDataParsed.EventData.Data[3]["#text"])
// Check specifically for access to IPC$ share and PIPE\svcctl and PIPE\atsvc for Service Control Services and Schedule Control Services
| union (
SecurityEvent
| where TimeGenerated > ago(timeframe)
| where Computer in~ (ADFS_Servers)
| where Account !endswith "$"
| where EventID == 5145
| where RelativeTargetName =~ "svcctl" or RelativeTargetName =~ "atsvc"
)
// Check for lateral movement
| join kind=inner
(SecurityEvent
| where TimeGenerated > ago(timeframe)
| where Account !endswith "$"
| where EventID == 4624 and LogonType == 3
) on $left.SubjectLogonId == $right.TargetLogonId
| project TimeGenerated, Account, Computer, EventID, RelativeTargetName
| extend timestamp = TimeGenerated
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountName = tostring(split(Account, @'\')[1]), AccountNTDomain = tostring(split(Account, @'\')[0])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Account
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountNTDomain
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: HostNameDomain
version: 1.2.1
kind: Scheduled
Stages and Predicates
Parameters
let timeframe = 1d;
let lookback = 6d;
Let Binding: ADFS_Servers
let ADFS_Servers = (
SecurityEvent
| where TimeGenerated > ago(timeframe+lookback)
| where EventID == 4688 and SubjectLogonId != "0x3e4"
| where NewProcessName has "Microsoft.IdentityServer.ServiceHost.exe"
| distinct Computer
);
Stage 1: source
let ADFS_Servers
Stage 2: source
SecurityEvent
Stage 3: where
| where TimeGenerated > ago(timeframe)
Stage 4: where
| where Computer in~ (ADFS_Servers)
Stage 5: where
| where Account !endswith "$"
Stage 6: where
| where EventID in (4697, 4698, 4699, 4700, 4701, 4702)
Stage 7: extend
| extend EventDataParsed = parse_xml(EventData)
Stage 8: extend
| extend SubjectLogonId = tostring(EventDataParsed.EventData.Data[3]["#text"])
Stage 9: union
union of 1 branches
Stage 10: source
SecurityEvent
Stage 11: where
| where TimeGenerated > ago(timeframe)
Stage 12: where
| where Computer in~ (ADFS_Servers)
Stage 13: where
| where Account !endswith "$"
Stage 14: where
| where EventID == 5145
Stage 15: where
| where RelativeTargetName =~ "svcctl" or RelativeTargetName =~ "atsvc"
Stage 16: join
| join kind=inner
(SecurityEvent
| where TimeGenerated > ago(timeframe)
| where Account !endswith "$"
| where EventID == 4624 and LogonType == 3
) on $left.SubjectLogonId == $right.TargetLogonId
Stage 17: project
project Account, Computer, EventID, RelativeTargetName, TimeGenerated
Stage 18: extend (4 consecutive steps)
extend AccountNTDomain, AccountName, DomainIndex, HostName, HostNameDomain, timestamp
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Computer | in |
| field:"Computer" kind:in value:"ADFS_Servers" |
EventID | eq |
| field:"EventID" kind:eq |
EventID | in |
| field:"EventID" kind:in |
LogonType | eq |
| field:"LogonType" kind:eq value:"3" |
RelativeTargetName | eq |
| field:"RelativeTargetName" kind:eq |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
Account | ends_with | $ | excludes:Account field:"Account" value:"$" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Account | project |
Computer | project |
EventID | project |
RelativeTargetName | project |
TimeGenerated | project |
timestamp | extend |
DomainIndex | extend |
HostName | extend |
HostNameDomain | extend |
AccountNTDomain | extend |
AccountName | extend |
GitHub - Oauth application - a client secret was removed
#Detect activities when a client secret was removed. This query runs every day and its severity is Medium.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GitHub | Audit log action oauth_application.remove_client_secret: OAuth application secret key deleted |
Rule Body
id: 0b85a077-8ba5-4cb5-90f7-1e882afe10c5
name: GitHub - Oauth application - a client secret was removed
description: |
'Detect activities when a client secret was removed. This query runs every day and its severity is Medium.'
severity: Medium
status: Available
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 7d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
relevantTechniques:
- T1078
query: |
GitHubAuditData
| where Action == "oauth_application.remove_client_secret"
| extend AccountName = tostring(split(Actor, "@")[0]), AccountUPNSuffix = tostring(split(Actor, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Actor
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
version: 1.0.1
kind: Scheduled
Stages and Predicates
Stage 1: source
GitHubAuditData
Stage 2: where
| where Action == "oauth_application.remove_client_secret"
Stage 3: extend
| extend AccountName = tostring(split(Actor, "@")[0]), AccountUPNSuffix = tostring(split(Actor, "@")[1])
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Action | eq |
| field:"Action" kind:eq value:"oauth_application.remove_client_secret" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountName | extend |
AccountUPNSuffix | extend |
GitHub Two Factor Auth Disable
#Two-factor authentication is a process where a user is prompted during the sign-in process for an additional form of identification, such as to enter a code on their cellphone or to provide a fingerprint scan. Two factor authentication reduces the risk of account takeover. Attacker will want to disable such security tools in order to go undetected.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GitHub | Audit log action org.disable_two_factor_requirement: 2FA requirement disabled for organization |
Rules Detecting the Same Action
These rules filter on the same operation.
- GitHub Enterprise Disable 2FA Requirement (Splunk)
- Github High Risk Configuration Disabled (Sigma)
- GitHub Org Authentication Method Changed (Panther)
- GitHub Organizations Disable 2FA Requirement (Splunk)
- GitHub Two-Factor Authentication Requirement Disabled (YARA-L)
- NRT GitHub Two Factor Auth Disable (Kusto)
Rule Body
id: 3ff0fffb-d963-40c0-b235-3404f915add7
name: GitHub Two Factor Auth Disable
description: |
'Two-factor authentication is a process where a user is prompted during the sign-in process for an additional form of identification, such as to enter a code on their cellphone or to provide a fingerprint scan. Two factor authentication reduces the risk of account takeover. Attacker will want to disable such security tools in order to go undetected. '
severity: Medium
status: Available
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
relevantTechniques:
- T1562
query: |
GitHubAuditData
| where Action == "org.disable_two_factor_requirement"
| project TimeGenerated, Action, Actor, Country, Repository
| extend Name = iif(Actor contains "@", split(Actor, "@")[0], Actor)
| extend UPNSuffix = iif(Actor contains "@", split(Actor, "@")[1], "")
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Actor
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
version: 1.0.2
kind: Scheduled
Stages and Predicates
Stage 1: source
GitHubAuditData
Stage 2: where
| where Action == "org.disable_two_factor_requirement"
Stage 3: project
| project TimeGenerated, Action, Actor, Country, Repository
Stage 4: extend
| extend Name = iif(Actor contains "@", split(Actor, "@")[0], Actor)
Stage 5: extend
| extend UPNSuffix = iif(Actor contains "@", split(Actor, "@")[1], "")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Action | eq |
| field:"Action" kind:eq value:"org.disable_two_factor_requirement" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Action | project |
Actor | project |
Country | project |
Repository | project |
TimeGenerated | project |
Name | extend |
UPNSuffix | extend |
Lookout - Device Compliance and Security Status Changes (v2)
#'Monitors device compliance status changes and security posture degradation using Lookout Mobile Risk API v2 enhanced device fields. Detects devices becoming non-compliant, security status changes, and potential device compromise indicators with detailed device context and MDM integration data.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Defense Evasion | |
| Discovery |
Rule Body
id: 9c5b6d8f-3a02-4e9b-af4c-2d7e9b1f5a8c
name: Lookout - Device Compliance and Security Status Changes (v2)
description: |
'Monitors device compliance status changes and security posture degradation using Lookout Mobile Risk API v2 enhanced device fields. Detects devices becoming non-compliant, security status changes, and potential device compromise indicators with detailed device context and MDM integration data.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: LookoutAPI
dataTypes:
- LookoutEvents
queryFrequency: 10m
queryPeriod: 30m
triggerOperator: gt
triggerThreshold: 0
tactics:
- Discovery
- DefenseEvasion
- Persistence
relevantTechniques:
- T1418
- T1629
- T1655
query: |
LookoutEvents
| where EventType == "DEVICE"
| where DeviceComplianceStatus in ("Non-Compliant", "Partial")
or DeviceSecurityStatus in ("THREATS_HIGH", "THREATS_MEDIUM")
or ChangeType == "UPDATE"
| extend
DeviceRiskScore = case(
DeviceSecurityStatus == "THREATS_HIGH", 9,
DeviceSecurityStatus == "THREATS_MEDIUM", 6,
DeviceSecurityStatus == "THREATS_LOW", 3,
DeviceComplianceStatus == "Non-Compliant", 7,
DeviceComplianceStatus == "Partial", 4,
1
),
ComplianceReason = case(
isempty(DeviceCheckinTime), "No Recent Check-in",
DeviceActivationStatus != "ACTIVE", "Inactive Device",
isempty(ClientLookoutSDKVersion), "Missing Security Client",
"Configuration Issue"
),
PlatformRisk = case(
DevicePlatform == "ANDROID" and DeviceOSVersion matches regex @"^[1-9]\..*", "Outdated Android",
DevicePlatform == "IOS" and DeviceOSVersion matches regex @"^1[0-4]\..*", "Outdated iOS",
DevicePlatform == "UNKNOWN", "Unknown Platform",
"Current"
)
| extend MDMIntegrationStatus = case(
isnotempty(MDMConnectorId) and isnotempty(MDMExternalId), "Fully Integrated",
isnotempty(MDMConnectorId), "Partial Integration",
"Not Integrated"
)
| extend SecurityPosture = case(
DeviceRiskScore >= 8, "Critical",
DeviceRiskScore >= 6, "High",
DeviceRiskScore >= 4, "Medium",
"Low"
)
| project
TimeGenerated,
EventId,
DeviceGuid,
DevicePlatform,
DeviceOSVersion,
DeviceManufacturer,
DeviceModel,
DeviceEmailAddress,
DeviceActivationStatus,
DeviceSecurityStatus,
DeviceComplianceStatus,
DeviceRiskScore,
SecurityPosture,
ComplianceReason,
PlatformRisk,
DeviceCheckinTime,
DeviceActivatedAt,
DeviceDeactivatedAt,
DeviceGroupGuid,
ClientLookoutSDKVersion,
ClientOTAVersion,
ClientPackageName,
ClientPackageVersion,
MDMConnectorId,
MDMConnectorUuid,
MDMExternalId,
MDMIntegrationStatus,
ActorType,
ActorGuid,
ChangeType
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: DeviceEmailAddress
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: DeviceGuid
- identifier: OSFamily
columnName: DevicePlatform
- identifier: OSVersion
columnName: DeviceOSVersion
customDetails:
DevicePlatform: DevicePlatform
DeviceSecStatus: DeviceSecurityStatus
DevCompliance: DeviceComplianceStatus
DeviceRiskScore: DeviceRiskScore
SecurityPosture: SecurityPosture
ComplianceReason: ComplianceReason
PlatformRisk: PlatformRisk
MDMIntegration: MDMIntegrationStatus
ClientSDKVersion: ClientLookoutSDKVersion
DeviceManufacturer: DeviceManufacturer
DeviceModel: DeviceModel
alertDetailsOverride:
alertDisplayNameFormat: "Device Compliance Issue: {{SecurityPosture}} Risk on {{DevicePlatform}} Device"
alertDescriptionFormat: "{{SecurityPosture}} posture with {{DeviceComplianceStatus}} compliance"
alertTacticsColumnName: SecurityPosture
alertSeverityColumnName: SecurityPosture
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: P1D
matchingMethod: Selected
groupByEntities:
- Account
- Host
groupByAlertDetails:
- DeviceGuid
groupByCustomDetails:
- SecurityPosture
- DevicePlatform
eventGroupingSettings:
aggregationKind: AlertPerResult
suppressionEnabled: false
suppressionDuration: PT30M
version: 2.0.3
kind: Scheduled
Stages and Predicates
Stage 1: source
LookoutEvents
Stage 2: where
| where EventType == "DEVICE"
Stage 3: where
| where DeviceComplianceStatus in ("Non-Compliant", "Partial")
or DeviceSecurityStatus in ("THREATS_HIGH", "THREATS_MEDIUM")
or ChangeType == "UPDATE"
Stage 4: extend (3 consecutive steps)
| extend
DeviceRiskScore = case(
DeviceSecurityStatus == "THREATS_HIGH", 9,
DeviceSecurityStatus == "THREATS_MEDIUM", 6,
DeviceSecurityStatus == "THREATS_LOW", 3,
DeviceComplianceStatus == "Non-Compliant", 7,
DeviceComplianceStatus == "Partial", 4,
1
),
ComplianceReason = case(
isempty(DeviceCheckinTime), "No Recent Check-in",
DeviceActivationStatus != "ACTIVE", "Inactive Device",
isempty(ClientLookoutSDKVersion), "Missing Security Client",
"Configuration Issue"
),
PlatformRisk = case(
DevicePlatform == "ANDROID" and DeviceOSVersion matches regex @"^[1-9]\..*", "Outdated Android",
DevicePlatform == "IOS" and DeviceOSVersion matches regex @"^1[0-4]\..*", "Outdated iOS",
DevicePlatform == "UNKNOWN", "Unknown Platform",
"Current"
)
| extend MDMIntegrationStatus = case(
isnotempty(MDMConnectorId) and isnotempty(MDMExternalId), "Fully Integrated",
isnotempty(MDMConnectorId), "Partial Integration",
"Not Integrated"
)
| extend SecurityPosture = case(
DeviceRiskScore >= 8, "Critical",
DeviceRiskScore >= 6, "High",
DeviceRiskScore >= 4, "Medium",
"Low"
)
ComplianceReason =isempty(DeviceCheckinTime)"No Recent Check-in"DeviceActivationStatus != "ACTIVE""Inactive Device"isempty(ClientLookoutSDKVersion)"Missing Security Client""Configuration Issue"DeviceRiskScore =DeviceSecurityStatus == "THREATS_HIGH"9DeviceSecurityStatus == "THREATS_MEDIUM"6DeviceSecurityStatus == "THREATS_LOW"3DeviceComplianceStatus == "Non-Compliant"7DeviceComplianceStatus == "Partial"41PlatformRisk =DevicePlatform == "ANDROID" and DeviceOSVersion matches regex @"^[1-9]\..*""Outdated Android"DevicePlatform == "IOS" and DeviceOSVersion matches regex @"^1[0-4]\..*""Outdated iOS"DevicePlatform == "UNKNOWN""Unknown Platform""Current"Stage 5: project
| project
TimeGenerated,
EventId,
DeviceGuid,
DevicePlatform,
DeviceOSVersion,
DeviceManufacturer,
DeviceModel,
DeviceEmailAddress,
DeviceActivationStatus,
DeviceSecurityStatus,
DeviceComplianceStatus,
DeviceRiskScore,
SecurityPosture,
ComplianceReason,
PlatformRisk,
DeviceCheckinTime,
DeviceActivatedAt,
DeviceDeactivatedAt,
DeviceGroupGuid,
ClientLookoutSDKVersion,
ClientOTAVersion,
ClientPackageName,
ClientPackageVersion,
MDMConnectorId,
MDMConnectorUuid,
MDMExternalId,
MDMIntegrationStatus,
ActorType,
ActorGuid,
ChangeType
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ChangeType | eq |
| field:"ChangeType" kind:eq value:"UPDATE" |
DeviceComplianceStatus | in |
| field:"DeviceComplianceStatus" kind:in |
DeviceSecurityStatus | in |
| field:"DeviceSecurityStatus" kind:in |
EventType | eq |
| field:"EventType" kind:eq value:"DEVICE" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActorGuid | project |
ActorType | project |
ChangeType | project |
ClientLookoutSDKVersion | project |
ClientOTAVersion | project |
ClientPackageName | project |
ClientPackageVersion | project |
ComplianceReason | project |
DeviceActivatedAt | project |
DeviceActivationStatus | project |
DeviceCheckinTime | project |
DeviceComplianceStatus | project |
DeviceDeactivatedAt | project |
DeviceEmailAddress | project |
DeviceGroupGuid | project |
DeviceGuid | project |
DeviceManufacturer | project |
DeviceModel | project |
DeviceOSVersion | project |
DevicePlatform | project |
DeviceRiskScore | project |
DeviceSecurityStatus | project |
EventId | project |
MDMConnectorId | project |
MDMConnectorUuid | project |
MDMExternalId | project |
MDMIntegrationStatus | project |
PlatformRisk | project |
SecurityPosture | project |
TimeGenerated | project |
Mimecast Targeted Threat Protection - URL Protect
#'Detects malicious scan results and actions which are not allowed.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule Body
id: 952faed4-c6a6-4873-aeb9-b348e9ce5aba
name: Mimecast Targeted Threat Protection - URL Protect
description: |
'Detects malicious scan results and actions which are not allowed.'
severity: High
status: Available
requiredDataConnectors:
- connectorId: MimecastTTPAPI
dataTypes:
- MimecastTTPUrl
queryFrequency: 30m
queryPeriod: 30m
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- Discovery
relevantTechniques:
- T0865
query: |
MimecastTTPUrl
| where ['Scan Result'] == "malicious" and Action != "allow"
| extend From_User_EmailAddress = ['From User Email Address'],MessageID = ['Message ID'] , User_EmailAddress = ['User Email Address'], SendingIP = ['Sending IP']
suppressionDuration: 5h
suppressionEnabled: false
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: P7D
matchingMethod: AllEntities
eventGroupingSettings:
aggregationKind: AlertPerResult
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SendingIP
- entityType: MailMessage
fieldMappings:
- identifier: Sender
columnName: From_User_EmailAddress
- identifier: InternetMessageId
columnName: MessageID
- identifier: Recipient
columnName: User_EmailAddress
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Url
version: 1.0.1
kind: Scheduled
Stages and Predicates
Stage 1: source
MimecastTTPUrl
Stage 2: where
| where ['Scan Result'] == "malicious" and Action != "allow"
Stage 3: extend
| extend From_User_EmailAddress = ['From User Email Address'],MessageID = ['Message ID'] , User_EmailAddress = ['User Email Address'], SendingIP = ['Sending IP']
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Action | ne |
| field:"Action" kind:ne value:"allow" |
Scan Result | eq |
| field:"Scan Result" kind:eq value:"malicious" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
From_User_EmailAddress | extend |
MessageID | extend |
SendingIP | extend |
User_EmailAddress | extend |
Oracle - Oracle WebLogic Exploit CVE-2021-2109
#'Detects exploitation of Oracle WebLogic vulnerability CVE-2021-2109'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule Body
id: 67950168-5740-11ec-bf63-0242ac130002
name: Oracle - Oracle WebLogic Exploit CVE-2021-2109
description: |
'Detects exploitation of Oracle WebLogic vulnerability CVE-2021-2109'
severity: High
status: Available
requiredDataConnectors:
- connectorId: CustomLogsAma
dataTypes:
- OracleWebLogicServer_CL
queryFrequency: 10m
queryPeriod: 10m
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
relevantTechniques:
- T1190
query: |
OracleWebLogicServerEvent
| where HttpRequestMethod =~ "GET"
| where UrlOriginal has_all ("ldap://", "com.bea.console.handles.JndiBindingHandle", "AdminServer")
| extend UrlCustomEntity = UrlOriginal
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: UrlCustomEntity
version: 1.0.3
kind: Scheduled
Stages and Predicates
Stage 1: source
OracleWebLogicServerEvent
Stage 2: where
| where HttpRequestMethod =~ "GET"
Stage 3: where
| where UrlOriginal has_all ("ldap://", "com.bea.console.handles.JndiBindingHandle", "AdminServer")
Stage 4: extend
| extend UrlCustomEntity = UrlOriginal
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
HttpRequestMethod | eq |
| field:"HttpRequestMethod" kind:eq value:"GET" |
UrlOriginal | match |
| field:"UrlOriginal" kind:match |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
UrlCustomEntity | extend |
Probable AdFind Recon Tool Usage (Normalized Process Events)
#Identifies the host and account that executed AdFind by hash and filename in addition to common and unique flags that are used by many threat actors in discovery. To use this analytics rule, make sure you have deployed the ASIM normalization parsers
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Discovery |
Telemetry Coverage
Rule Body
id: 45076281-35ae-45e0-b443-c32aa0baf965
name: Probable AdFind Recon Tool Usage (Normalized Process Events)
description: |
'Identifies the host and account that executed AdFind by hash and filename in addition to common and unique flags that are used by many threat actors in discovery.
To use this analytics rule, make sure you have deployed the [ASIM normalization parsers](https://aka.ms/ASimProcessEvent)'
severity: High
requiredDataConnectors: []
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Discovery
relevantTechniques:
- T1018
tags:
- Id: c63ae777-d5e0-4113-8c9a-c2c9d3d09fcd
version: 1.0.0
- Schema: ASIMProcessEvent
SchemaVersion: 0.1.0
query: |
let args = dynamic(["objectcategory","domainlist","dcmodes","adinfo","trustdmp","computers_pwdnotreqd","Domain Admins", "objectcategory=person", "objectcategory=computer", "objectcategory=*","dclist"]);
let parentProcesses = dynamic(["pwsh.exe","powershell.exe","cmd.exe"]);
imProcessCreate
//looks for execution from a shell
| where ActingProcessName has_any (parentProcesses)
| extend ActingProcessFileName = tostring(split(ActingProcessName, '\\')[-1])
| where ActingProcessFileName in~ (parentProcesses)
// main filter
| where Process hassuffix "AdFind.exe" or TargetProcessSHA256 == "c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3"
// AdFind common Flags to check for from various threat actor TTPs
or CommandLine has_any (args)
| extend AlgorithmType = "SHA256"
| extend AccountName = tostring(split(User, @'\')[1]), AccountNTDomain = tostring(split(User, @'\')[0])
| extend HostName = tostring(split(Dvc, ".")[0]), DomainIndex = toint(indexof(Dvc, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Dvc, DomainIndex + 1), Dvc)
| project-away DomainIndex
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: User
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountNTDomain
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Dvc
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: HostNameDomain
- entityType: Process
fieldMappings:
- identifier: ProcessId
columnName: ActingProcessName
- identifier: CommandLine
columnName: CommandLine
- entityType: FileHash
fieldMappings:
- identifier: Algorithm
columnName: AlgorithmType
- identifier: Value
columnName: TargetProcessSHA256
version: 1.1.6
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Yuval Naor
support:
tier: Community
categories:
domains: [ "Security - Threat Intelligence" ]
Stages and Predicates
Parameters
let parentProcesses = dynamic(["pwsh.exe","powershell.exe","cmd.exe"]);
Let Binding: args
let args = dynamic(["objectcategory","domainlist","dcmodes","adinfo","trustdmp","computers_pwdnotreqd","Domain Admins", "objectcategory=person", "objectcategory=computer", "objectcategory=*","dclist"]);
Stage 1: source
imProcessCreate
Stage 2: where
| where ActingProcessName has_any (parentProcesses)
Stage 3: extend
| extend ActingProcessFileName = tostring(split(ActingProcessName, '\\')[-1])
Stage 4: where
| where ActingProcessFileName in~ (parentProcesses)
Stage 5: where
| where Process hassuffix "AdFind.exe" or TargetProcessSHA256 == "c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3"
or CommandLine has_any (args)
Stage 6: extend (4 consecutive steps)
| extend AlgorithmType = "SHA256"
| extend AccountName = tostring(split(User, @'\')[1]), AccountNTDomain = tostring(split(User, @'\')[0])
| extend HostName = tostring(split(Dvc, ".")[0]), DomainIndex = toint(indexof(Dvc, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Dvc, DomainIndex + 1), Dvc)
Stage 7: project-away
| project-away DomainIndex
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ActingProcessFileName | in |
| field:"ActingProcessFileName" kind:in |
ActingProcessName | match |
| field:"ParentImage" kind:match |
CommandLine | match |
| field:"CommandLine" kind:match |
Process | ends_with |
| field:"Process" kind:ends_with value:"AdFind.exe" |
TargetProcessSHA256 | eq |
| field:"sha256" kind:eq value:"c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActingProcessFileName | extend |
AlgorithmType | extend |
AccountNTDomain | extend |
AccountName | extend |
HostName | extend |
HostNameDomain | extend |
Service Principal Assigned Privileged Role
#Detects a privileged role being added to a Service Principal. Ensure that any assignment to a Service Principal is valid and appropriate - Service Principals should not be assigned to very highly privileged roles such as Global Admin. Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-privileged-accounts#changes-to-privileged-accounts
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Azure | any: Entra ID audit event (any operation) |
Rule Body
id: 84cccc86-5c11-4b3a-aca6-7c8f738ed0f7
name: Service Principal Assigned Privileged Role
description: |
'Detects a privileged role being added to a Service Principal.
Ensure that any assignment to a Service Principal is valid and appropriate - Service Principals should not be assigned to very highly privileged roles such as Global Admin.
Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-privileged-accounts#changes-to-privileged-accounts'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- PrivilegeEscalation
relevantTechniques:
- T1078.004
tags:
- AADSecOpsGuide
query: |
AuditLogs
| where OperationName has_all ("member to role", "add")
| where Result =~ "Success"
| extend type_ = tostring(TargetResources[0].type)
| where type_ =~ "ServicePrincipal"
| where isnotempty(TargetResources)
| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIPAddress = tostring(InitiatedBy.user.ipAddress)
| extend InitiatedBy = tostring(iff(isnotempty(InitiatingUserPrincipalName),InitiatingUserPrincipalName, InitiatingAppName))
| extend ServicePrincipalName = tostring(TargetResources[0].displayName)
| extend ServicePrincipalId = tostring(TargetResources[0].id)
| mv-expand TargetResources[0].modifiedProperties
| extend TargetResources_0_modifiedProperties = columnifexists("TargetResources_0_modifiedProperties", '')
| where isnotempty(TargetResources_0_modifiedProperties)
| extend displayName = tostring(TargetResources_0_modifiedProperties.displayName), newValue = tostring(parse_json(tostring(TargetResources_0_modifiedProperties.newValue)))
| where displayName == "Role.DisplayName" and newValue contains "admin"
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
| extend TargetRole = newValue
| project-reorder TimeGenerated, ServicePrincipalName, ServicePrincipalId, InitiatedBy, TargetRole, InitiatingIPAddress
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: InitiatingAppName
- identifier: AadUserId
columnName: InitiatingAppServicePrincipalId
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: InitiatingUserPrincipalName
- identifier: Name
columnName: InitiatingAccountName
- identifier: UPNSuffix
columnName: InitiatingAccountUPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: InitiatingAadUserId
- entityType: Account
fieldMappings:
- identifier: Name
columnName: ServicePrincipalName
- identifier: AadUserId
columnName: ServicePrincipalId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: InitiatingIPAddress
version: 1.1.1
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
support:
tier: Community
categories:
domains: [ "Security - Others", "Identity" ]
Stages and Predicates
Stage 1: source
AuditLogs
Stage 2: where
| where OperationName has_all ("member to role", "add")
Stage 3: where
| where Result =~ "Success"
Stage 4: extend
| extend type_ = tostring(TargetResources[0].type)
Stage 5: where
| where type_ =~ "ServicePrincipal"
Stage 6: where
| where isnotempty(TargetResources)
Stage 7: extend (8 consecutive steps)
| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIPAddress = tostring(InitiatedBy.user.ipAddress)
| extend InitiatedBy = tostring(iff(isnotempty(InitiatingUserPrincipalName),InitiatingUserPrincipalName, InitiatingAppName))
| extend ServicePrincipalName = tostring(TargetResources[0].displayName)
| extend ServicePrincipalId = tostring(TargetResources[0].id)
Stage 8: mv-expand
| mv-expand TargetResources[0].modifiedProperties
Stage 9: extend
| extend TargetResources_0_modifiedProperties = columnifexists("TargetResources_0_modifiedProperties", '')
Stage 10: where
| where isnotempty(TargetResources_0_modifiedProperties)
Stage 11: extend
| extend displayName = tostring(TargetResources_0_modifiedProperties.displayName), newValue = tostring(parse_json(tostring(TargetResources_0_modifiedProperties.newValue)))
Stage 12: where
| where displayName == "Role.DisplayName" and newValue contains "admin"
Stage 13: extend
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
Stage 14: extend
| extend TargetRole = newValue
Stage 15: project-reorder
| project-reorder TimeGenerated, ServicePrincipalName, ServicePrincipalId, InitiatedBy, TargetRole, InitiatingIPAddress
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
OperationName | match |
| field:"OperationName" kind:match |
Result | eq |
| field:"Result" kind:eq value:"Success" |
TargetResources | is_not_null | field:"azure_ad::target_resources" kind:is_not_null | |
TargetResources_0_modifiedProperties | is_not_null | field:"TargetResources_0_modifiedProperties" kind:is_not_null | |
displayName | eq |
| field:"displayName" kind:eq value:"Role.DisplayName" |
newValue | contains |
| field:"newValue" kind:contains value:"admin" |
type_ | eq |
| field:"type_" kind:eq value:"ServicePrincipal" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
type_ | extend |
InitiatingAppName | extend |
InitiatingAppServicePrincipalId | extend |
InitiatingUserPrincipalName | extend |
InitiatingAadUserId | extend |
InitiatingIPAddress | extend |
InitiatedBy | extend |
ServicePrincipalName | extend |
ServicePrincipalId | extend |
TargetResources_0_modifiedProperties | extend |
displayName | extend |
newValue | extend |
InitiatingAccountName | extend |
InitiatingAccountUPNSuffix | extend |
TargetRole | extend |
TI Map URL Entity to Syslog Data
#'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in Syslog data.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Rule Body
id: 4de24a28-dcd0-4a0d-bf14-96d8483dc05a
name: TI Map URL Entity to Syslog Data
description: |
'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in Syslog data.'
severity: Medium
requiredDataConnectors:
- connectorId: Syslog
dataTypes:
- Syslog
- connectorId: ThreatIntelligence
dataTypes:
- ThreatIntelIndicators
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelIndicators
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelIndicators
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
relevantTechniques:
- T1071
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelIndicators
// Picking up only IOC's that contain the entities we want
//extract key part of kv pair
| extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
| where IndicatorType == "url"
| extend Url = ObservableValue
| extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue
| where IsActive and (ValidUntil > now() or isempty(ValidUntil))
| project-reorder *, Tags, TrafficLightProtocolLevel, Url, Type
// 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 (
Syslog
| where TimeGenerated >= ago(dt_lookBack)
// Extract URL from the Syslog message but only take messages that include URLs
| extend Url = extract("(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)", 1,SyslogMessage)
| extend Syslog_TimeGenerated = TimeGenerated
) on Url
| where Syslog_TimeGenerated < ValidUntil
| summarize Syslog_TimeGenerated = arg_max(Syslog_TimeGenerated , *) by Id, Url
| extend Description = tostring(parse_json(Data).description)
| extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(parse_json(Data).labels))
| project timestamp = Syslog_TimeGenerated, Description, ActivityGroupNames, Id, Type, ValidUntil, Confidence, SyslogMessage, Computer, ProcessName, Url, HostIP
entityMappings:
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: Computer
- entityType: IP
fieldMappings:
- identifier: Address
columnName: HostIP
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Url
version: 1.2.8
kind: Scheduled
Stages and Predicates
Parameters
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
Stage 1: source
ThreatIntelIndicators
Stage 2: extend
| extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
Stage 3: where
| where IndicatorType == "url"
Stage 4: extend
| extend Url = ObservableValue
Stage 5: extend
| extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
Stage 6: where
| where TimeGenerated >= ago(ioc_lookBack)
Stage 7: summarize
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue
Stage 8: where
| where IsActive and (ValidUntil > now() or isempty(ValidUntil))
Stage 9: project-reorder
| project-reorder *, Tags, TrafficLightProtocolLevel, Url, Type
Stage 10: join
| join kind=innerunique (
Syslog
| where TimeGenerated >= ago(dt_lookBack)
| extend Url = extract("(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)", 1,SyslogMessage)
| extend Syslog_TimeGenerated = TimeGenerated
) on Url
Stage 11: where
where Syslog_TimeGenerated < ValidUntil
Stage 12: summarize
summarize Syslog_TimeGenerated by Id, Url
Stage 13: extend
extend Description
Stage 14: extend
extend ActivityGroupNames
Stage 15: project
project ActivityGroupNames, Computer, Confidence, Description, HostIP, Id, ProcessName, SyslogMessage, Type, Url, ValidUntil, timestamp
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
IndicatorType | eq |
| field:"IndicatorType" kind:eq value:"url" |
IsActive | eq |
| field:"IsActive" kind:eq value:"true" |
ValidUntil | is_null | field:"ValidUntil" kind:is_null |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActivityGroupNames | project |
Computer | project |
Confidence | project |
Description | project |
HostIP | project |
Id | project |
ProcessName | project |
SyslogMessage | project |
Type | project |
Url | project |
ValidUntil | project |
timestamp | project |
Veeam ONE Backup Copy RPO
#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 Backup Copy RPO violation alerts.
Rule Body
id: 7fb6d1b6-48e4-442b-ba4d-1b5fb5fa379b
name: Veeam ONE Backup Copy RPO
description: Detects Veeam ONE Backup Copy RPO violation alerts.
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 == 365
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 == 365
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
PredefinedAlarmId | eq |
| field:"PredefinedAlarmId" kind:eq value:"365" |
VMware SD-WAN Edge - Network Anomaly Detection - Potential Fragmentation Attack
#The VMware SD-WAN Edge appliance received packets potentially part of an IP Fragmentation attack or indicating an MTU mismatch. An IP fragmentation attack is a cyberattack that exploits how IP packets are fragmented and reassembled. IP fragmentation is a process by which large IP packets are broken down into smaller packets to transmit them over networks with smaller Maximum Transmission Unit (MTU) sizes. Attackers can exploit IP fragmentation in various ways, for example, Denial-of-service attacks, address spoofing, or even information disclosure. This analytics rule analyzes Syslog streams; these alerts are not reported by default if Search API is used.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment | |
| Impact |
Rule Body
id: ce207901-ed7b-49ae-ada7-033e1fbb1240
name: VMware SD-WAN Edge - Network Anomaly Detection - Potential Fragmentation Attack
version: 1.0.0
kind: Scheduled
description: |-
The VMware SD-WAN Edge appliance received packets potentially part of an IP Fragmentation attack or indicating an MTU mismatch.
An IP fragmentation attack is a cyberattack that exploits how IP packets are fragmented and reassembled. IP fragmentation is a process by which large IP packets are broken down into smaller packets to transmit them over networks with smaller Maximum Transmission Unit (MTU) sizes.
Attackers can exploit IP fragmentation in various ways, for example, Denial-of-service attacks, address spoofing, or even information disclosure.
This analytics rule analyzes Syslog streams; these alerts are not reported by default if Search API is used.
severity: Low
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
requiredDataConnectors:
- connectorId: VMwareSDWAN
dataTypes:
- SDWAN
tactics:
- Impact
- DefenseEvasion
relevantTechniques:
- T1498
- T1599
query: |+
Syslog
| where SyslogMessage contains "VCF Drop"
| where SyslogMessage contains "packet too big"
| project-rename EdgeName=HostName
| project-away Computer, HostIP, SourceSystem, Type
| extend OverlaySegmentName = extract("SEGMENT_NAME=(.+) COUNT=", 1, SyslogMessage)
| extend IpProtocol = extract("PROTO=(.+) SRC=", 1, SyslogMessage)
| extend SrcIpAddress = extract("SRC=(.+) DST=", 1, SyslogMessage)
| extend DstIpAddress = extract("DST=(.+) REASON=", 1, SyslogMessage)
| extend EdgeFwAction = extract("ACTION=(.+) SEGMENT=", 1, SyslogMessage)
| extend SyslogTag = extract("^(.+): ACTION=", 1, SyslogMessage)
| extend pcktCount = extract("COUNT=([0-9]+)$", 1, SyslogMessage)
| project
TimeGenerated,
EdgeFwAction,
EdgeName,
SrcIpAddress,
IpProtocol,
DstIpAddress,
pcktCount,
SyslogTag
suppressionEnabled: false
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 1h
matchingMethod: AllEntities
groupByEntities: []
groupByAlertDetails: []
groupByCustomDetails: []
eventGroupingSettings:
aggregationKind: SingleAlert
customDetails:
Edge_Name: EdgeName
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddress
suppressionDuration: 5h
Stages and Predicates
Stage 1: source
Syslog
Stage 2: where
| where SyslogMessage contains "VCF Drop"
Stage 3: where
| where SyslogMessage contains "packet too big"
Stage 4: project-rename
| project-rename EdgeName=HostName
Stage 5: project-away
| project-away Computer, HostIP, SourceSystem, Type
Stage 6: extend (7 consecutive steps)
| extend OverlaySegmentName = extract("SEGMENT_NAME=(.+) COUNT=", 1, SyslogMessage)
| extend IpProtocol = extract("PROTO=(.+) SRC=", 1, SyslogMessage)
| extend SrcIpAddress = extract("SRC=(.+) DST=", 1, SyslogMessage)
| extend DstIpAddress = extract("DST=(.+) REASON=", 1, SyslogMessage)
| extend EdgeFwAction = extract("ACTION=(.+) SEGMENT=", 1, SyslogMessage)
| extend SyslogTag = extract("^(.+): ACTION=", 1, SyslogMessage)
| extend pcktCount = extract("COUNT=([0-9]+)$", 1, SyslogMessage)
Stage 7: project
| project
TimeGenerated,
EdgeFwAction,
EdgeName,
SrcIpAddress,
IpProtocol,
DstIpAddress,
pcktCount,
SyslogTag
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
SyslogMessage | contains |
| field:"SyslogMessage" kind:contains |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DstIpAddress | project |
EdgeFwAction | project |
EdgeName | project |
IpProtocol | project |
SrcIpAddress | project |
SyslogTag | project |
TimeGenerated | project |
pcktCount | project |
Website blocked by ESET
#'Create alert on websites blocked by ESET.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Command & Control | |
| Exfiltration |
Rule Body
id: 7b84fc5b-9ffb-4e9b-945b-5d480e330b3f
name: Website blocked by ESET
description: |
'Create alert on websites blocked by ESET.'
severity: Low
requiredDataConnectors:
- connectorId: ESETPROTECT
dataTypes:
- ESETPROTECT
- connectorId: SyslogAma
datatypes:
- Syslog
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
- Exfiltration
- CommandAndControl
- InitialAccess
relevantTechniques:
- T1041
- T1071
- T1189
- T1566
query: |
ESETPROTECT
| where EventType == 'FilteredWebsites_Event'
| extend SrcUserName, FilePath, DvcHostname, DvcIpAddr
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: SrcUserName
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: DvcHostname
- entityType: IP
fieldMappings:
- identifier: Address
columnName: DvcIpAddr
- entityType: URL
fieldMappings:
- identifier: Url
columnName: FilePath
version: 1.0.2
kind: Scheduled
Stages and Predicates
Stage 1: source
ESETPROTECT
Stage 2: where
| where EventType == 'FilteredWebsites_Event'
Stage 3: extend
| extend SrcUserName, FilePath, DvcHostname, DvcIpAddr
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventType | eq |
| field:"EventType" kind:eq value:"FilteredWebsites_Event" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DvcHostname | extend |
DvcIpAddr | extend |
FilePath | extend |
SrcUserName | extend |
XbowLowFindings
#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.
Creates an incident for each Low severity finding reported by XBOW that is currently in an open state. These findings represent minor security issues or best-practice violations that should be addressed as part of regular security maintenance. Each alert is deduplicated per finding so re-ingestion of the same finding does not produce duplicate incidents.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Discovery | No specific technique |
Rule Body
id: d2e4f1a8-7c9b-4356-8e0d-5a2b7c8e9f01
name: XbowLowFindings
description: |
Creates an incident for each Low severity finding reported by XBOW that is currently
in an open state. These findings represent minor security issues or best-practice
violations that should be addressed as part of regular security maintenance. Each
alert is deduplicated per finding so re-ingestion of the same finding does not
produce duplicate incidents.
severity: Low
status: Available
requiredDataConnectors:
- connectorId: XbowSecurityConnector
dataTypes:
- XbowFindings_CL
- XbowAssets_CL
queryFrequency: 1h
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Discovery
relevantTechniques: []
query: |
XbowFindings_CL
| where TimeGenerated > ago(2h)
| where tolower(Severity) == 'low'
| where isempty(State) or tolower(State) == 'open'
| summarize arg_max(TimeGenerated, *) by FindingId
| join kind=leftouter (
XbowAssets_CL
| summarize arg_max(TimeGenerated, *) by AssetId
| project AssetId, StartUrl
) on AssetId
| project
TimeGenerated,
FindingId,
FindingName,
Severity,
State,
Summary,
Impact,
Mitigations,
Recipe,
AssetId,
AssetName,
OrganizationId,
CreatedAt,
StartUrl
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: 'XBOW Low: {{FindingName}}'
alertDescriptionFormat: 'Low severity finding on asset {{AssetName}} ({{AssetId}}). {{Summary}}'
customDetails:
FindingID: FindingId
FindingName: FindingName
Severity: Severity
State: State
AssetID: AssetId
AssetName: AssetName
OrganizationID: OrganizationId
CreatedAt: CreatedAt
Mitigations: Mitigations
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 24h
matchingMethod: Selected
groupByCustomDetails:
- FindingID
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: StartUrl
version: 1.0.1
kind: Scheduled
Stages and Predicates
Stage 1: source
XbowFindings_CL
Stage 2: where
| where TimeGenerated > ago(2h)
Stage 3: where
| where tolower(Severity) == 'low'
Stage 4: where
| where isempty(State) or tolower(State) == 'open'
Stage 5: summarize
| summarize arg_max(TimeGenerated, *) by FindingId
Stage 6: join
| join kind=leftouter (
XbowAssets_CL
| summarize arg_max(TimeGenerated, *) by AssetId
| project AssetId, StartUrl
) on AssetId
Stage 7: project
project AssetId, AssetName, CreatedAt, FindingId, FindingName, Impact, Mitigations, OrganizationId, Recipe, Severity, StartUrl, State, Summary, TimeGenerated
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Severity | eq |
| field:"Severity" kind:eq value:"low" |
State | eq |
| field:"State" kind:eq value:"open" |
State | is_null | field:"State" kind:is_null |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AssetId | project |
AssetName | project |
CreatedAt | project |
FindingId | project |
FindingName | project |
Impact | project |
Mitigations | project |
OrganizationId | project |
Recipe | project |
Severity | project |
StartUrl | project |
State | project |
Summary | project |
TimeGenerated | project |