Detection rules › Kusto
Kusto rules: 2z
1Password - Vault export
#This will alert when a successful vault export has occurred within 1Password. Ref: https://1password.com/ Ref: https://github.com/securehats/
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| 1Password | vault-export: Export Vault |
Rule Body
id: dae4c601-51c9-47f5-83d3-e6eaef929cf6
name: 1Password - Vault export
version: 1.0.0
kind: Scheduled
description: |-
This will alert when a successful vault export has occurred within 1Password.
Ref: https://1password.com/
Ref: https://github.com/securehats/
severity: Low
requiredDataConnectors:
- connectorId: 1Password
dataTypes:
- OnePasswordEventLogs_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- CredentialAccess
relevantTechniques:
- T1555
query: |-
OnePasswordEventLogs_CL
| where action == "export"
| where object_type == "vault"
| extend
TargetUsername = actor_details.email
, SrcIpAddr = session.ip
suppressionEnabled: false
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 1h
matchingMethod: AllEntities
suppressionDuration: 1h
eventGroupingSettings:
aggregationKind: SingleAlert
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: TargetUsername
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
Stages and Predicates
Stage 1: source
OnePasswordEventLogs_CL
Stage 2: where
| where action == "export"
Stage 3: where
| where object_type == "vault"
Stage 4: extend
| extend
TargetUsername = actor_details.email
, SrcIpAddr = session.ip
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action | eq |
| field:"action" kind:eq value:"export" |
object_type | eq |
| field:"object_type" kind:eq value:"vault" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
SrcIpAddr | extend |
TargetUsername | extend |
ASR Rare and Untrusted Executables
#Below query shows Untrusted executables that are seen on few devices (LocalPrevalence). It requires the below ASR rule to be configured and Cloud-delivered protection to be enabled.
Block executable files from running unless they meet a prevalence, age, or trusted list criterion
You may need to exclude software development users/machines/folders.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth | No specific technique |
References
Telemetry Coverage
Rule Body
// Author: Cyb3rMonk(https://twitter.com/Cyb3rMonk, https://mergene.medium.com)
//
// Query parameters:
DeviceEvents
| where Timestamp > ago(30d)
| where ActionType in ("AsrUntrustedExecutableAudited","AsrUntrustedExecutableBlocked")
| summarize arg_min(Timestamp,*), LocalPrevalence = dcount(DeviceId) by SHA1, FileName
| where Timestamp > ago(1d)
| where LocalPrevalence <= 5
// there might be files without signature info, perform leftouter join
| join kind=leftouter (
DeviceFileCertificateInfo
| where Timestamp > ago(30d)
| summarize arg_max(Timestamp,*) by SHA1
)
on SHA1
// Get GlobalPrevalence info, etc.
| invoke FileProfile(SHA1, 1000)
// GlobalFirstSeen can be used for filtering the results further
// If you want to list only the files that have invalid signatures uncomment the below line
// there might be files without signature info, don't exclude them
// | where IsTrusted <> 1
Stages and Predicates
Stage 1: source
DeviceEvents
Stage 2: where
| where Timestamp > ago(30d)
Stage 3: where
| where ActionType in ("AsrUntrustedExecutableAudited","AsrUntrustedExecutableBlocked")
Stage 4: summarize
| summarize arg_min(Timestamp,*), LocalPrevalence = dcount(DeviceId) by SHA1, FileName
Stage 5: where
| where Timestamp > ago(1d)
Stage 6: where
| where LocalPrevalence <= 5
Stage 7: join
| join kind=leftouter (
DeviceFileCertificateInfo
| where Timestamp > ago(30d)
| summarize arg_max(Timestamp,*) by SHA1
)
on SHA1
Stage 8: invoke
invoke
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ActionType | in |
| field:"ActionType" kind:in |
LocalPrevalence | le |
| field:"LocalPrevalence" kind:le value:"5" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
FileName | summarize |
LocalPrevalence | summarize |
SHA1 | summarize |
BloodHound Attack Path Finding - Non-Tier Zero AD User Synced to Tier Zero Entra User
#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.
BloodHound Attack Path Finding - Non-Tier Zero AD User Synced to Tier Zero Entra User
Rule Body
id: 8844495b-1d05-4080-9fc2-28621f744a4b
name: BloodHound Attack Path Finding - Non-Tier Zero AD User Synced to Tier Zero Entra
User
description: BloodHound Attack Path Finding - Non-Tier Zero AD User Synced to Tier
Zero Entra User
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: BloodHoundEnterprise
dataTypes:
- BHEAttackPathsData_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: "BHEAttackPathsData_CL \n| where Finding == \"AzureT0SyncedToEntraUser\""
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: domain_name
customDetails:
Description: ShortDescription
Remediation: ShortRemediation
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
BHEAttackPathsData_CL
Stage 2: where
| where Finding == "AzureT0SyncedToEntraUser"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Finding | eq |
| field:"Finding" kind:eq value:"AzureT0SyncedToEntraUser" |
BloodHound Attack Path Finding - Tier Zero Computer Vulnerable to Coercion-Based NTLM Relay to LDAPS Attack
#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.
BloodHound Attack Path Finding - Tier Zero Computer Vulnerable to Coercion-Based NTLM Relay to LDAPS Attack
Rule Body
id: 37a04fa0-b13c-43d9-a6a0-f34229ebf8f4
name: BloodHound Attack Path Finding - Tier Zero Computer Vulnerable to Coercion-Based
NTLM Relay to LDAPS Attack
description: BloodHound Attack Path Finding - Tier Zero Computer Vulnerable to Coercion-Based
NTLM Relay to LDAPS Attack
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: BloodHoundEnterprise
dataTypes:
- BHEAttackPathsData_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: BHEAttackPathsData_CL | where Finding == "T0CoerceAndRelayNTLMToLDAPS"
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: domain_name
customDetails:
Description: ShortDescription
Remediation: ShortRemediation
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
BHEAttackPathsData_CL
Stage 2: where
| where Finding == "T0CoerceAndRelayNTLMToLDAPS"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Finding | eq |
| field:"Finding" kind:eq value:"T0CoerceAndRelayNTLMToLDAPS" |
CiscoISE - Device PostureStatus changed to non-compliant
#'Detects when device changes PostureStatus from "Compliant".'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation |
Rule Body
id: 548a2eda-d3eb-46cc-8d4b-1601551629e4
name: CiscoISE - Device PostureStatus changed to non-compliant
description: |
'Detects when device changes PostureStatus from "Compliant".'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: SyslogAma
datatypes:
- Syslog
queryFrequency: 15m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
tactics:
- PrivilegeEscalation
- Persistence
relevantTechniques:
- T1098
query: |
let lbtime_48h = 48h;
let lbtime_24h = 24h;
let lbtime_now = now();
let compliantIPs = CiscoISEEvent
| where TimeGenerated between (ago(lbtime_48h) .. ago(lbtime_24h))
| where PostureStatus == 'Compliant'
| summarize makelist(DstIpAddr)
;
CiscoISEEvent
| where TimeGenerated between (ago(lbtime_24h) .. lbtime_now)
| where PostureStatus != 'Compliant'
| where DstIpAddr in (compliantIPs)
| project DstIpAddr
| extend IPCustomEntity = DstIpAddr
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPCustomEntity
version: 1.0.3
kind: Scheduled
Stages and Predicates
Parameters
let lbtime_48h = 48h;
let lbtime_24h = 24h;
let lbtime_now = now();
Let Binding: compliantIPs
let compliantIPs = CiscoISEEvent
| where TimeGenerated between (ago(lbtime_48h) .. ago(lbtime_24h))
| where PostureStatus == 'Compliant'
| summarize makelist(DstIpAddr);
Stage 1: source
CiscoISEEvent
Stage 2: where
| where TimeGenerated between (ago(lbtime_24h) .. lbtime_now)
Stage 3: where
| where PostureStatus != 'Compliant'
Stage 4: where
| where DstIpAddr in (compliantIPs)
Stage 5: project
| project DstIpAddr
Stage 6: extend
| extend IPCustomEntity = DstIpAddr
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DstIpAddr | in |
| field:"dest_ip" kind:in value:"compliantIPs" |
PostureStatus | ne |
| field:"PostureStatus" kind:ne value:"Compliant" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DstIpAddr | project |
IPCustomEntity | extend |
Claroty - Multiple failed logins to same destinations
#Detects multiple failed login attempts to the same Claroty SRA destination site within a 5-minute window. The rule counts failed logins per site and alerts when the number of failures exceeds the threshold value of 10.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule Body
id: 1c2310ef-19bf-4caf-b2b0-a4c983932fa5
name: Claroty - Multiple failed logins to same destinations
description: 'Detects multiple failed login attempts to the same Claroty SRA destination site within a 5-minute window. The
rule counts failed logins per site and alerts when the number of failures exceeds the threshold value of 10.'
severity: High
status: Available
requiredDataConnectors:
- connectorId: CefAma
dataTypes:
- CommonSecurityLog
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
relevantTechniques:
- T1190
- T1133
query: |
let threshold = 10;
ClarotyEvent
| where EventType has 'Login to SRA'
| where EventType !has 'succeeded'
| extend Site = column_ifexists("site_name","")
| where isnotempty(Site)
| extend SrcUsername = extract(@'User\s(.*?)\sfailed', 1, EventMessage)
| summarize FailedLogins = count(), SampleUser = any(SrcUsername) by Site, bin(TimeGenerated, 5m)
| where FailedLogins > threshold
| extend SGCustomEntity = Site
| project TimeGenerated, Site, FailedLogins, Threshold = threshold, SampleUser, SGCustomEntity
entityMappings:
- entityType: SecurityGroup
fieldMappings:
- identifier: DistinguishedName
columnName: SGCustomEntity
version: 1.0.4
kind: Scheduled
Stages and Predicates
Parameters
let threshold = 10;
Stage 1: source
ClarotyEvent
Stage 2: where
| where EventType has 'Login to SRA'
Stage 3: where
| where EventType !has 'succeeded'
Stage 4: extend
| extend Site = column_ifexists("site_name","")
Stage 5: where
| where isnotempty(Site)
Stage 6: extend
| extend SrcUsername = extract(@'User\s(.*?)\sfailed', 1, EventMessage)
Stage 7: summarize
| summarize FailedLogins = count(), SampleUser = any(SrcUsername) by Site, bin(TimeGenerated, 5m)
Stage 8: where
| where FailedLogins > threshold
Stage 9: extend
| extend SGCustomEntity = Site
Stage 10: project
| project TimeGenerated, Site, FailedLogins, Threshold = threshold, SampleUser, SGCustomEntity
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventType | match |
| field:"EventType" kind:match value:"Login to SRA" |
FailedLogins | gt |
| field:"FailedLogins" kind:gt value:"10" |
Site | is_not_null | field:"Site" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
EventType | match | succeeded | excludes:EventType field:"EventType" value:"succeeded" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
FailedLogins | project |
SGCustomEntity | project |
SampleUser | project |
Site | project |
Threshold | project |
TimeGenerated | project |
Claroty - Suspicious activity
#Detects suspicious behavior that is generally indicative of malware.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Discovery |
Rule Body
id: 99ad9f3c-304c-44c5-a61f-3a17f8b58218
name: Claroty - Suspicious activity
description: 'Detects suspicious behavior that is generally indicative of malware.'
severity: High
status: Available
requiredDataConnectors:
- connectorId: CefAma
dataTypes:
- CommonSecurityLog
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Discovery
relevantTechniques:
- T1018
query: |
ClarotyEvent
| where EventOriginalType has 'Suspicious Activity' or EventType has 'Suspicious Activity'
| project TimeGenerated, DstIpAddr, EventOriginalType, EventType
| extend IPCustomEntity = DstIpAddr
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPCustomEntity
alertDetailsOverride:
alertDisplayNameFormat: Claroty suspicious activity on {{IPCustomEntity}}
alertDescriptionFormat: 'Claroty reported suspicious activity for {{IPCustomEntity}}. Event type: {{EventType}}. Original
type: {{EventOriginalType}}.'
customDetails:
DestinationIP: DstIpAddr
EventOriginalType: EventOriginalType
EventType: EventType
version: 1.0.4
kind: Scheduled
Stages and Predicates
Stage 1: source
ClarotyEvent
Stage 2: where
| where EventOriginalType has 'Suspicious Activity' or EventType has 'Suspicious Activity'
Stage 3: project
| project TimeGenerated, DstIpAddr, EventOriginalType, EventType
Stage 4: extend
| extend IPCustomEntity = DstIpAddr
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventOriginalType | match |
| field:"EventOriginalType" kind:match value:"Suspicious Activity" |
EventType | match |
| field:"EventType" kind:match value:"Suspicious Activity" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DstIpAddr | project |
EventOriginalType | project |
EventType | project |
TimeGenerated | project |
IPCustomEntity | extend |
Corelight - C2 DGA Detected Via Repetitive Failures
#'Detects large amounts of DNS resolution failures.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Rule Body
id: 8eaa2268-74ee-492c-b869-450eff707fef
name: Corelight - C2 DGA Detected Via Repetitive Failures
description: |
'Detects large amounts of DNS resolution failures.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Corelight
dataTypes:
- corelight_dns
- corelight_dns_red
- corelight_dns_agg
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
relevantTechniques:
- T1568
query: |
let threshold = 25;
union isfuzzy=true corelight_dns, corelight_dns_agg
// rcodes: SERVFAIL=2, NXDOMAIN=3
| where rcode in (2, 3)
| summarize count() by query, id_orig_h, bin(TimeGenerated, 5m)
| where count_ > threshold
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: id_orig_h
version: 2.2.0
kind: Scheduled
Stages and Predicates
Parameters
let threshold = 25;
Union isfuzzy=true (2 Sources)
Each leg below queries one source; the rule matches if any leg does. Sources: corelight_dns, corelight_dns_agg
Leg 1: corelight_dns
Leg 2: corelight_dns_agg
Applied to the Combined Result
| where rcode in (2, 3) | summarize count() by query, id_orig_h, bin(TimeGenerated, 5m) | where count_ > threshold
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
count_ | gt |
| field:"count_" kind:gt value:"25" |
rcode | in |
| field:"rcode" kind:in |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
id_orig_h | summarize |
query | summarize |
CTE - Enrollment Token Generated
#An enrollment token was generated for onboarding a new device.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
Rule Body
id: 0be1ebaf-36f8-49a6-a3b6-56491ccfda7f
name: CTE - Enrollment Token Generated
description: |
An enrollment token was generated for onboarding a new device.
severity: Informational
requiredDataConnectors:
- connectorId: cybereinforce_cte
dataTypes:
- CybereinforceCTE_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Persistence
relevantTechniques:
- T1098
query: |
CybereinforceCTE_CL
| where EventType == "token.generated"
| extend AccountName = tostring(split(Actor, "@")[0]), UPNSuffix = tostring(split(Actor, "@")[1])
| project TimeGenerated, TenantId, Actor, AccountName, UPNSuffix, Severity, Category, Source
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: UPNSuffix
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
CybereinforceCTE_CL
Stage 2: where
| where EventType == "token.generated"
Stage 3: extend
| extend AccountName = tostring(split(Actor, "@")[0]), UPNSuffix = tostring(split(Actor, "@")[1])
Stage 4: project
| project TimeGenerated, TenantId, Actor, AccountName, UPNSuffix, Severity, Category, Source
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventType | eq |
| field:"EventType" kind:eq value:"token.generated" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountName | project |
Actor | project |
Category | project |
Severity | project |
Source | project |
TenantId | project |
TimeGenerated | project |
UPNSuffix | project |
Hunt for critical credentials on non Credential Guard enabled devices
#This query searches for devices that does not have Credential Guard enabled but contains critical credentials. The output shows for how many users each non Credential Guard device has credentials, together with the list of users being exposed.
Telemetry Coverage
Rule Body
let no_credguard_devices = (
ExposureGraphNodes
// Get devices with credential guard misconfiguration
| where array_length(NodeProperties.rawData.hasGuardMisconfigurations) > 0
// Get interesting data
| extend DeviceName = tostring(parse_json(NodeProperties)["rawData"]["deviceName"]),
DeviceId = tostring(EntityIds.id)
| extend DeviceName = iff(isempty(DeviceName), NodeName, DeviceName)
// Search for distinct devices
| distinct NodeId, DeviceName
);
let critical_users = toscalar(
// Search for critical users
ExposureGraphNodes
| where NodeLabel == "user"
| extend CriticalityLevel = todynamic(NodeProperties).rawData.criticalityLevel.criticalityLevel
| extend RuleNames = todynamic(NodeProperties).rawData.criticalityLevel.ruleNames
| where CriticalityLevel == 0
| distinct NodeName, NodeId, tostring(CriticalityLevel), tostring(RuleNames)
| summarize make_set(NodeName)
);
// Make graph for max of 3 edges, where we start from a device and end with an user
ExposureGraphEdges
| make-graph SourceNodeId --> TargetNodeId with ExposureGraphNodes on NodeId
| graph-match (SourceNode)-[anyEdge*1..3]->(TargetNode)
where SourceNode.NodeLabel in ("device", "microsoft.compute/virtualmachines") and TargetNode.NodeLabel == "user" and TargetNode.NodeName in ( critical_users )
project SourceNodeName = SourceNode.NodeName,
SourceNodeId = SourceNode.NodeId,
Edges = anyEdge.EdgeLabel,
TargetNodeId = TargetNode.NodeId,
TargetNodeName = TargetNode.NodeName,
TargetNodeLabel = TargetNode.NodeLabel,
TargetCriticalityLevel = TargetNode.NodeProperties.rawData.criticalityLevel.criticalityLevel,
TargetRuleNames = TargetNode.NodeProperties.rawData.criticalityLevel.ruleNames
| distinct SourceNodeId, SourceNodeName, TargetNodeId, TargetNodeName, tostring(TargetCriticalityLevel), tostring(TargetRuleNames)
// Only return devices that does not have a TPM fully enabled
| join kind=inner no_credguard_devices on $left.SourceNodeId == $right.NodeId
// Make list of users per device
| summarize UserList = make_list(TargetNodeName) by DeviceName
// Count amount of exposed users per device
| extend UserCount = array_length(UserList)
| sort by UserCount desc
Stages and Predicates
Let Binding: no_credguard_devices
let no_credguard_devices = (
ExposureGraphNodes
| where array_length(NodeProperties.rawData.hasGuardMisconfigurations) > 0
| extend DeviceName = tostring(parse_json(NodeProperties)["rawData"]["deviceName"]),
DeviceId = tostring(EntityIds.id)
| extend DeviceName = iff(isempty(DeviceName), NodeName, DeviceName)
| distinct NodeId, DeviceName
);
Let Binding: critical_users
let critical_users = toscalar(
ExposureGraphNodes
| where NodeLabel == "user"
| extend CriticalityLevel = todynamic(NodeProperties).rawData.criticalityLevel.criticalityLevel
| extend RuleNames = todynamic(NodeProperties).rawData.criticalityLevel.ruleNames
| where CriticalityLevel == 0
| distinct NodeName, NodeId, tostring(CriticalityLevel), tostring(RuleNames)
| summarize make_set(NodeName)
);
Stage 1: source
let no_credguard_devices
Stage 2: source
ExposureGraphEdges
Stage 3: macro
macro
Stage 4: macro
macro
Stage 5: distinct
distinct SourceNodeId, SourceNodeName, TargetNodeId, TargetNodeName
Stage 6: join
join kind=inner (no_credguard_devices) on $left.SourceNodeId, $right.NodeId
Stage 7: summarize
summarize UserList by DeviceName
Stage 8: extend
extend UserCount
Stage 9: sort
sort by UserCount
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DeviceName | summarize |
UserList | summarize |
UserCount | extend |
Mimecast Targeted Threat Protection - URL Protect
#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 malicious scan results and actions which are not allowed
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule Body
id: 9d5545bd-1450-4086-935c-62f15fc4a4c9
name: Mimecast Targeted Threat Protection - URL Protect
description: Detects malicious scan results and actions which are not allowed
severity: High
requiredDataConnectors:
- connectorId: MimecastTTPAPI
dataTypes:
- MimecastTTPUrl_CL
enabled: true
query: MimecastTTPUrl_CL| where scanResult_s == "malicious" and action_s != "allow";
queryFrequency: 5m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
suppressionDuration: 5h
suppressionEnabled: false
tactics:
- InitialAccess
- Discovery
relevantTechniques:
- T0865
alertRuleTemplateName:
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 1d
matchingMethod: AllEntities
eventGroupingSettings:
aggregationKind: AlertPerResult
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: sendingIp_s
- entityType: MailMessage
fieldMappings:
- identifier: Sender
columnName: fromUserEmailAddress_s
- identifier: InternetMessageId
columnName: messageId_s
- identifier: Recipient
columnName: userEmailAddress_s
- entityType: URL
fieldMappings:
- identifier: Url
columnName: url_s
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
MimecastTTPUrl_CL
Stage 2: where
| where scanResult_s == "malicious" and action_s != "allow";
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action_s | ne |
| field:"action_s" kind:ne value:"allow" |
scanResult_s | eq |
| field:"scanResult_s" kind:eq value:"malicious" |
Pathlock TDnR - G/L Account Changes
#Detects changes to General Ledger (G/L) accounts in SAP, forwarded by Pathlock Threat Detection and Response. Unauthorized modifications to G/L accounts may indicate financial data manipulation, accounting fraud, or attempts to conceal unauthorised transactions.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Rule Body
id: 2a3b4c5d-6e7f-4a0b-8c1d-2e3f4a5b6c15
name: Pathlock TDnR - G/L Account Changes
kind: Scheduled
description: >-
Detects changes to General Ledger (G/L) accounts in SAP, forwarded by Pathlock Threat Detection
and Response. Unauthorized modifications to G/L accounts may indicate financial data manipulation,
accounting fraud, or attempts to conceal unauthorised transactions.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Pathlock_TDnR
dataTypes:
- Pathlock_TDnR_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
relevantTechniques:
- T1565
query: |
Pathlock_TDnR_CL
| where DataSource == "CHANGEDOC_SACH"
| project TimeGenerated, Sysid, DataSource, Eventid, Instance, Hostname, Bname,
Tcode, Report, Area, Subid, SrcIp, DestIp, AffectedUser, LogLine,
MsgType, MsgId, MsgNo, MessageV1, MessageV2, MessageV3, MessageV4, CentralTs
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Bname
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: Hostname
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIp
eventGroupingSettings:
aggregationKind: SingleAlert
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 5h
matchingMethod: AnyAlert
groupByEntities: []
groupByAlertDetails: []
groupByCustomDetails: []
suppressionDuration: 5h
suppressionEnabled: false
version: 1.0.0
Stages and Predicates
Stage 1: source
Pathlock_TDnR_CL
Stage 2: where
| where DataSource == "CHANGEDOC_SACH"
Stage 3: project
| project TimeGenerated, Sysid, DataSource, Eventid, Instance, Hostname, Bname,
Tcode, Report, Area, Subid, SrcIp, DestIp, AffectedUser, LogLine,
MsgType, MsgId, MsgNo, MessageV1, MessageV2, MessageV3, MessageV4, CentralTs
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DataSource | eq |
| field:"DataSource" kind:eq value:"CHANGEDOC_SACH" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AffectedUser | project |
Area | project |
Bname | project |
CentralTs | project |
DataSource | project |
DestIp | project |
Eventid | project |
Hostname | project |
Instance | project |
LogLine | project |
MessageV1 | project |
MessageV2 | project |
MessageV3 | project |
MessageV4 | project |
MsgId | project |
MsgNo | project |
MsgType | project |
Report | project |
SrcIp | project |
Subid | project |
Sysid | project |
Tcode | project |
TimeGenerated | project |
Pathlock TDnR - SAP System Job Monitoring Events
#Detects monitoring events from SAP system jobs (SJOBREPO), forwarded by Pathlock Threat Detection and Response. Anomalies in system job execution may indicate unauthorized task scheduling, manipulation of critical background processes, or use of system jobs as a persistence mechanism.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution |
Rule Body
id: 2a3b4c5d-6e7f-4a0b-8c1d-2e3f4a5b6c66
name: Pathlock TDnR - SAP System Job Monitoring Events
kind: Scheduled
description: >-
Detects monitoring events from SAP system jobs (SJOBREPO), forwarded by Pathlock Threat Detection
and Response. Anomalies in system job execution may indicate unauthorized task scheduling,
manipulation of critical background processes, or use of system jobs as a persistence mechanism.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Pathlock_TDnR
dataTypes:
- Pathlock_TDnR_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Execution
relevantTechniques:
- T1053
query: |
Pathlock_TDnR_CL
| where DataSource == "SYSTEM_JOBS"
| project TimeGenerated, Sysid, DataSource, Eventid, Instance, Hostname, Bname,
Tcode, Report, Area, Subid, SrcIp, DestIp, AffectedUser, LogLine,
MsgType, MsgId, MsgNo, MessageV1, MessageV2, MessageV3, MessageV4, CentralTs
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Bname
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: Hostname
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIp
eventGroupingSettings:
aggregationKind: SingleAlert
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 5h
matchingMethod: AnyAlert
groupByEntities: []
groupByAlertDetails: []
groupByCustomDetails: []
suppressionDuration: 5h
suppressionEnabled: false
version: 1.0.0
Stages and Predicates
Stage 1: source
Pathlock_TDnR_CL
Stage 2: where
| where DataSource == "SYSTEM_JOBS"
Stage 3: project
| project TimeGenerated, Sysid, DataSource, Eventid, Instance, Hostname, Bname,
Tcode, Report, Area, Subid, SrcIp, DestIp, AffectedUser, LogLine,
MsgType, MsgId, MsgNo, MessageV1, MessageV2, MessageV3, MessageV4, CentralTs
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DataSource | eq |
| field:"DataSource" kind:eq value:"SYSTEM_JOBS" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AffectedUser | project |
Area | project |
Bname | project |
CentralTs | project |
DataSource | project |
DestIp | project |
Eventid | project |
Hostname | project |
Instance | project |
LogLine | project |
MessageV1 | project |
MessageV2 | project |
MessageV3 | project |
MessageV4 | project |
MsgId | project |
MsgNo | project |
MsgType | project |
Report | project |
SrcIp | project |
Subid | project |
Sysid | project |
Tcode | project |
TimeGenerated | project |
Pathlock TDnR - Switchable Authorization Design Changes
#Detects changes to Switchable Authorizations (SACF) design-time configuration in SAP, forwarded by Pathlock Threat Detection and Response. Modifications to switchable authorization design may disable security-relevant authorization checks, allowing bypasses of access controls without removing actual authorizations.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation | |
| Defense Impairment |
Rule Body
id: 2a3b4c5d-6e7f-4a0b-8c1d-2e3f4a5b6c47
name: Pathlock TDnR - Switchable Authorization Design Changes
kind: Scheduled
description: >-
Detects changes to Switchable Authorizations (SACF) design-time configuration in SAP,
forwarded by Pathlock Threat Detection and Response. Modifications to switchable authorization
design may disable security-relevant authorization checks, allowing bypasses of access controls
without removing actual authorizations.
severity: High
status: Available
requiredDataConnectors:
- connectorId: Pathlock_TDnR
dataTypes:
- Pathlock_TDnR_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
- PrivilegeEscalation
relevantTechniques:
- T1562
- T1548
query: |
Pathlock_TDnR_CL
| where DataSource == "SACF_CHANGES_DESIGN"
| project TimeGenerated, Sysid, DataSource, Eventid, Instance, Hostname, Bname,
Tcode, Report, Area, Subid, SrcIp, DestIp, AffectedUser, LogLine,
MsgType, MsgId, MsgNo, MessageV1, MessageV2, MessageV3, MessageV4, CentralTs
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Bname
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: Hostname
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIp
eventGroupingSettings:
aggregationKind: SingleAlert
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 5h
matchingMethod: AnyAlert
groupByEntities: []
groupByAlertDetails: []
groupByCustomDetails: []
suppressionDuration: 5h
suppressionEnabled: false
version: 1.0.0
Stages and Predicates
Stage 1: source
Pathlock_TDnR_CL
Stage 2: where
| where DataSource == "SACF_CHANGES_DESIGN"
Stage 3: project
| project TimeGenerated, Sysid, DataSource, Eventid, Instance, Hostname, Bname,
Tcode, Report, Area, Subid, SrcIp, DestIp, AffectedUser, LogLine,
MsgType, MsgId, MsgNo, MessageV1, MessageV2, MessageV3, MessageV4, CentralTs
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DataSource | eq |
| field:"DataSource" kind:eq value:"SACF_CHANGES_DESIGN" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AffectedUser | project |
Area | project |
Bname | project |
CentralTs | project |
DataSource | project |
DestIp | project |
Eventid | project |
Hostname | project |
Instance | project |
LogLine | project |
MessageV1 | project |
MessageV2 | project |
MessageV3 | project |
MessageV4 | project |
MsgId | project |
MsgNo | project |
MsgType | project |
Report | project |
SrcIp | project |
Subid | project |
Sysid | project |
Tcode | project |
TimeGenerated | project |
PowerShell Encoded Command Execution (Living off the Land)
#Detects PowerShell or pwsh.exe launched with encoded command flags (-EncodedCommand, -enc, -ec, -enco). Attackers encode commands in Base64 to obfuscate malicious payloads and bypass script-based controls. Risk is elevated when a download cradle pattern is also detected. Tune AllowlistedParents for known-safe management tools such as SCCM.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Stealth |
Telemetry Coverage
Rule Body
id: 7b2f4d1a-9c3e-4f72-8b1d-3e6a9f2c4b8d
name: PowerShell Encoded Command Execution (Living off the Land)
description: |
Detects PowerShell or pwsh.exe launched with encoded command flags
(-EncodedCommand, -enc, -ec, -enco). Attackers encode commands in Base64
to obfuscate malicious payloads and bypass script-based controls.
Risk is elevated when a download cradle pattern is also detected.
Tune AllowlistedParents for known-safe management tools such as SCCM.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceProcessEvents
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Execution
- DefenseEvasion
relevantTechniques:
- T1059.001
- T1027
query: |
let Lookback = 1h;
let EncodedFlagRegex = @'(?i)(^|\s)-(encodedcommand|enc|ec|enco)\b';
let AllowlistedParents = dynamic([
"SqlServer.exe", "ManagementStudio.exe", "devenv.exe",
"ccmexec.exe", "SMSAgent.exe"
]);
let DownloadCradlePatterns = dynamic([
"Net.WebClient", "WebRequest", "DownloadString", "DownloadFile",
"IEX", "Invoke-Expression", "Invoke-RestMethod", "Start-BitsTransfer"
]);
let MDE_Results =
DeviceProcessEvents
| where Timestamp >= ago(Lookback)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| where ProcessCommandLine matches regex EncodedFlagRegex
| where not(InitiatingProcessFileName has_any (AllowlistedParents))
| extend
HasDownloadCradle = ProcessCommandLine has_any (DownloadCradlePatterns),
AccountName = InitiatingProcessAccountName,
AccountDomain = InitiatingProcessAccountDomain,
HostName = DeviceName,
EventTime = Timestamp
| project EventTime, HostName, AccountName, AccountDomain,
ProcessCommandLine, InitiatingProcessFileName, HasDownloadCradle;
let SecEvent_Results =
SecurityEvent
| where TimeGenerated >= ago(Lookback)
| where EventID == 4688
| where NewProcessName endswith "\\powershell.exe"
or NewProcessName endswith "\\pwsh.exe"
| where CommandLine matches regex EncodedFlagRegex
| where not(ParentProcessName has_any (AllowlistedParents))
| extend
HasDownloadCradle = CommandLine has_any (DownloadCradlePatterns),
AccountName = SubjectUserName,
AccountDomain = SubjectDomainName,
HostName = Computer,
EventTime = TimeGenerated,
ProcessCommandLine = CommandLine,
InitiatingProcessFileName = ParentProcessName
| project EventTime, HostName, AccountName, AccountDomain,
ProcessCommandLine, InitiatingProcessFileName, HasDownloadCradle;
union MDE_Results, SecEvent_Results
| extend RiskScore = iif(HasDownloadCradle, 2, 1)
| sort by RiskScore desc, EventTime desc
entityMappings:
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: HostName
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountDomain
- entityType: Process
fieldMappings:
- identifier: CommandLine
columnName: ProcessCommandLine
version: 1.0.4
kind: Scheduled
Stages and Predicates
Parameters
let Lookback = 1h;
Let Binding: EncodedFlagRegex
let EncodedFlagRegex = @'(?i)(^|\s)-(encodedcommand|enc|ec|enco)\b';
Let Binding: AllowlistedParents
let AllowlistedParents = dynamic([
"SqlServer.exe", "ManagementStudio.exe", "devenv.exe",
"ccmexec.exe", "SMSAgent.exe"
]);
Let Binding: DownloadCradlePatterns
let DownloadCradlePatterns = dynamic([
"Net.WebClient", "WebRequest", "DownloadString", "DownloadFile",
"IEX", "Invoke-Expression", "Invoke-RestMethod", "Start-BitsTransfer"
]);
Union (2 Sources)
Each leg below queries one source; the rule matches if any leg does. Sources: MDE_Results, SecEvent_Results
Leg 1: MDE_Results
Leg 2: SecEvent_Results
Applied to the Combined Result
| extend RiskScore = iif(HasDownloadCradle, 2, 1) | sort by RiskScore desc, EventTime desc
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
CommandLine | regex_match |
| field:"CommandLine" kind:regex_match value:"(?i)(^|\s)-(encodedcommand|enc|ec|enco)\b" |
EventID | eq |
| field:"EventID" kind:eq value:"4688" |
FileName | in |
| field:"FileName" kind:in |
NewProcessName | ends_with |
| field:"NewProcessName" kind:ends_with |
ProcessCommandLine | regex_match |
| field:"ProcessCommandLine" kind:regex_match value:"(?i)(^|\s)-(encodedcommand|enc|ec|enco)\b" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
InitiatingProcessFileName | match | SqlServer.exe, ManagementStudio.exe, devenv.exe, ccmexec.exe, SMSAgent.exe | excludes:InitiatingProcessFileName |
ParentProcessName | match | SqlServer.exe, ManagementStudio.exe, devenv.exe, ccmexec.exe, SMSAgent.exe | excludes:ParentProcessName |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountDomain | project |
AccountName | project |
EventTime | project |
HasDownloadCradle | project |
HostName | project |
InitiatingProcessFileName | project |
ProcessCommandLine | project |
RiskScore | extend |
Probable AdFind Recon Tool Usage
#This query identifies the host and account that executed AdFind, by hash and filename, in addition to the flags commonly utilized by various threat actors during the reconnaissance phase.
MITRE ATT&CK Coverage
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft Defender for Endpoint | DeviceProcessEvents action any: Process activity |
Rule Body
id: c63ae777-d5e0-4113-8c9a-c2c9d3d09fcd
name: Probable AdFind Recon Tool Usage
description: |
'This query identifies the host and account that executed AdFind, by hash and filename, in addition to the flags commonly utilized by various threat actors during the reconnaissance phase.'
severity: High
status: Available
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceProcessEvents
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Discovery
relevantTechniques:
- T1016
- T1018
- T1069.002
- T1087.002
- T1482
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"]);
DeviceProcessEvents
//looks for execution from a shell
| where InitiatingProcessFileName in~ (parentProcesses)
// main filter
| where FileName =~ "AdFind.exe" or SHA256 == "c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3"
// AdFind common Flags to check for from various threat actor TTPs
or ProcessCommandLine has_any (args)
| extend HostName = split(DeviceName, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(DeviceName, '.'), 1, -1), '.'), FileHashAlgorithm = "SHA256"
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountDomain
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: DnsDomain
- entityType: Process
fieldMappings:
- identifier: ProcessId
columnName: InitiatingProcessFileName
- identifier: CommandLine
columnName: ProcessCommandLine
- entityType: FileHash
fieldMappings:
- identifier: Algorithm
columnName: FileHashAlgorithm
- identifier: Value
columnName: SHA256
version: 1.0.3
kind: Scheduled
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
DeviceProcessEvents
Stage 2: where
| where InitiatingProcessFileName in~ (parentProcesses)
Stage 3: where
| where FileName =~ "AdFind.exe" or SHA256 == "c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3"
or ProcessCommandLine has_any (args)
Stage 4: extend
| extend HostName = split(DeviceName, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(DeviceName, '.'), 1, -1), '.'), FileHashAlgorithm = "SHA256"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
FileName | eq |
| field:"process_basename" kind:eq value:"AdFind.exe" |
InitiatingProcessFileName | in |
| field:"parent_process_basename" kind:in |
ProcessCommandLine | match |
| field:"CommandLine" kind:match |
SHA256 | eq |
| field:"sha256" kind:eq value:"c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DnsDomain | extend |
FileHashAlgorithm | extend |
HostName | extend |
PROD (TM019.1) - TRUST - A new AD Trust has been established
#A new Trust has been established with the Forest or Domains. The other forest should have a Tier Model deployed.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Security-Auditing | Event ID 5137: A directory service object was created. |
Rule Body
id: 891315d2-e080-4ac8-af5a-50bae17f2d4d
name: 'PROD (TM019.1) - TRUST - A new AD Trust has been established'
description: |
A new Trust has been established with the Forest or Domains. The other forest should have a Tier Model deployed.
severity: High
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvent
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- PrivilegeEscalation
relevantTechniques:
- T1484.002
query: |
SecurityEvent
| where EventID == 5137 and EventData has '"ObjectClass">trustedDomain' and EventData has 'CN=System'
| extend ObjectName = extract("(?i)CN=([^,]+),(?i)CN=System", 1, EventData)
| extend ActivityType = extract("([a-zA-Z]+)\\.$", 1, Activity)
| extend Domain = extract("([^.]+\\.[^.]+)$", 1, Computer)
| project TimeGenerated
, ObjectName
, ActivityType
, Account
, Domain
, Computer
, Channel
, EventID
, EventData
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: ObjectName
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: Computer
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Account
customDetails:
ObjectName: ObjectName
ActivityType: ActivityType
Account: Account
Domain: Domain
Computer: Computer
Channel: Channel
EventID: EventID
EventData: EventData
eventGroupingSettings:
aggregationKind: AlertPerResult
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
alertDetailsOverride:
alertDisplayNameFormat: '(TM019.1) A new Trust has been established, ensure the other Forest and Domains have the Tier Model deployed'
alertDescriptionFormat: 'Ensure the Tier Model has been deployed in the other Forest and Domain. Ensure Trust has been configured and secured properly.'
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
SecurityEvent
Stage 2: where
| where EventID == 5137 and EventData has '"ObjectClass">trustedDomain' and EventData has 'CN=System'
Stage 3: extend (3 consecutive steps)
| extend ObjectName = extract("(?i)CN=([^,]+),(?i)CN=System", 1, EventData)
| extend ActivityType = extract("([a-zA-Z]+)\\.$", 1, Activity)
| extend Domain = extract("([^.]+\\.[^.]+)$", 1, Computer)
Stage 4: project
| project TimeGenerated
, ObjectName
, ActivityType
, Account
, Domain
, Computer
, Channel
, EventID
, EventData
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventData | match |
| field:"EventData" kind:match |
EventID | eq |
| field:"EventID" kind:eq value:"5137" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Account | project |
ActivityType | project |
Channel | project |
Computer | project |
Domain | project |
EventData | project |
EventID | project |
ObjectName | project |
TimeGenerated | project |
Rare and potentially high-risk Office operations
#Identifies Office operations that are typically rare and can provide capabilities useful to attackers.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Collection |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- Detecting Impossible travel with mailbox permission tampering & Privilege Escalation attempt (Kusto)
- High risk Office operation conducted by IP Address that recently attempted to log into a disabled account (Kusto)
- Inbox Rules Creation Or Update Activity in O365 (Sigma)
- M365 Exchange Inbox Phishing Evasion Rule Created (Elastic)
- Mail Forwarding/Redirecting Activity In O365 (Sigma)
- Malicious BEC Inbox Rule (Kusto)
- O365 Mailbox Email Forwarding Enabled (Splunk)
- O365 New Email Forwarding Rule Created (Splunk)
Rule Body
id: 957cb240-f45d-4491-9ba5-93430a3c08be
name: Rare and potentially high-risk Office operations
description: |
'Identifies Office operations that are typically rare and can provide capabilities useful to attackers.'
severity: Low
status: Available
requiredDataConnectors:
- connectorId: Office365
dataTypes:
- OfficeActivity
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Persistence
- Collection
relevantTechniques:
- T1098
- T1114
query: |
OfficeActivity
| where Operation in~ ( "Add-MailboxPermission", "Add-MailboxFolderPermission", "Set-Mailbox", "New-ManagementRoleAssignment", "New-InboxRule", "Set-InboxRule", "Set-TransportRule")
and not(UserId has_any ('NT AUTHORITY\\SYSTEM (Microsoft.Exchange.ServiceHost)', 'NT AUTHORITY\\SYSTEM (Microsoft.Exchange.AdminApi.NetCore)', 'NT AUTHORITY\\SYSTEM (w3wp)', 'devilfish-applicationaccount') and Operation in~ ( "Add-MailboxPermission", "Set-Mailbox"))
| extend ClientIPOnly = tostring(extract_all(@'\[?(::ffff:)?(?P<IPAddress>(\d+\.\d+\.\d+\.\d+)|[^\]]+)\]?', dynamic(["IPAddress"]), ClientIP)[0])
| extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: UserId
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: ClientIP
- entityType: CloudApplication
fieldMappings:
- identifier: AppId
columnName: AppId
version: 2.0.5
kind: Scheduled
Stages and Predicates
Stage 1: source
OfficeActivity
Stage 2: where
| where Operation in~ ( "Add-MailboxPermission", "Add-MailboxFolderPermission", "Set-Mailbox", "New-ManagementRoleAssignment", "New-InboxRule", "Set-InboxRule", "Set-TransportRule")
and not(UserId has_any ('NT AUTHORITY\\SYSTEM (Microsoft.Exchange.ServiceHost)', 'NT AUTHORITY\\SYSTEM (Microsoft.Exchange.AdminApi.NetCore)', 'NT AUTHORITY\\SYSTEM (w3wp)', 'devilfish-applicationaccount') and Operation in~ ( "Add-MailboxPermission", "Set-Mailbox"))
Stage 3: extend
| extend ClientIPOnly = tostring(extract_all(@'\[?(::ffff:)?(?P<IPAddress>(\d+\.\d+\.\d+\.\d+)|[^\]]+)\]?', dynamic(["IPAddress"]), ClientIP)[0])
Stage 4: extend
| extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1])
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Operation | in |
| field:"Operation" kind:in |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
Operation | in | Add-MailboxPermission, Set-Mailbox | excludes:Operation field:"Operation" value:"Add-MailboxPermission" field:"Operation" value:"Set-Mailbox" |
UserId | match | NT AUTHORITY\SYSTEM (Microsoft.Exchange.ServiceHost), NT AUTHORITY\SYSTEM (Microsoft.Exchange.AdminApi.NetCore), NT AUTHORITY\SYSTEM (w3wp), devilfish-applicationaccount | excludes:UserId |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ClientIPOnly | extend |
AccountName | extend |
AccountUPNSuffix | extend |
Rare client observed with high reverse DNS lookup count
#'Identifies clients with a high reverse DNS counts that could be carrying out reconnaissance or discovery activity. Alerts are generated if the IP performing such reverse DNS lookups was not seen doing so in the preceding 7-day period.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Discovery |
Rule Body
id: 15ae38a2-2e29-48f7-883f-863fb25a5a06
name: Rare client observed with high reverse DNS lookup count
description: |
'Identifies clients with a high reverse DNS counts that could be carrying out reconnaissance or discovery activity.
Alerts are generated if the IP performing such reverse DNS lookups was not seen doing so in the preceding 7-day period.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: DNS
dataTypes:
- DnsEvents
queryFrequency: 1d
queryPeriod: 8d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Discovery
relevantTechniques:
- T1046
query: |
let starttime = 8d;
let endtime = 1d;
let threshold = 10;
DnsEvents
| where TimeGenerated > ago(endtime)
| where Name has "in-addr.arpa"
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), dcount(Name), ReverseDNSLookup_List = make_set(Name,100) by ClientIP
| where dcount_Name > threshold
| project StartTimeUtc, EndTimeUtc, ClientIP , dcount_Name, ReverseDNSLookup_List
// Filter out previously seen IPs
// Returns all the records from the left side that don't have matches from the right
| join kind=leftanti (DnsEvents
| where TimeGenerated between(ago(starttime)..ago(endtime))
| where Name has "in-addr.arpa"
| summarize dcount(Name) by ClientIP, bin(TimeGenerated, 1d)
| where dcount_Name > threshold
| project ClientIP , dcount_Name
) on ClientIP
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: ClientIP
version: 1.0.2
kind: Scheduled
Stages and Predicates
Parameters
let starttime = 8d;
let endtime = 1d;
let threshold = 10;
Stage 1: source
DnsEvents
Stage 2: where
| where TimeGenerated > ago(endtime)
Stage 3: where
| where Name has "in-addr.arpa"
Stage 4: summarize
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), dcount(Name), ReverseDNSLookup_List = make_set(Name,100) by ClientIP
Stage 5: where
| where dcount_Name > threshold
Stage 6: project
| project StartTimeUtc, EndTimeUtc, ClientIP , dcount_Name, ReverseDNSLookup_List
Stage 7: join (negated)
join kind=leftanti (DnsEvents) on ClientIP
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Name | match |
| field:"Name" kind:match value:"in-addr.arpa" |
dcount_Name | gt |
| field:"dcount_Name" kind:gt value:"10" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
Name | match | in-addr.arpa | excludes:Name field:"Name" value:"in-addr.arpa" |
dcount_Name | gt | 10 | excludes:dcount_Name field:"dcount_Name" value:"10" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ClientIP | project |
EndTimeUtc | project |
ReverseDNSLookup_List | project |
StartTimeUtc | project |
dcount_Name | project |
Theom Medium Risks
#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 Microsoft Sentinel incidents for medium risk Theom alerts."
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Reconnaissance | |
| Stealth | |
| Credential Access | |
| Discovery | |
| Collection | |
| Command & Control | |
| Exfiltration | |
| Impact |
Rule Body
id: 4cb34832-f73a-49f2-8d38-c2d135c5440b
name: Theom Medium Risks
description: |
"Creates Microsoft Sentinel incidents for medium risk Theom alerts."
severity: High
status : Available
requiredDataConnectors:
- connectorId: Theom
dataTypes:
- TheomAlerts_CL
queryPeriod: 5m
queryFrequency: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
- Collection
- CommandAndControl
- CredentialAccess
- DefenseEvasion
- Discovery
- Exfiltration
- Impact
- Reconnaissance
relevantTechniques:
- T1592
- T1589
- T1070
- T1552
- T1619
- T1119
- T1560
- T1530
- T1213
- T1001
- T1041
- T1537
- T1485
- T1486
- T1565
query: |
TheomAlerts_CL
| where priority_s == "P3"
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: "Theom Alert ID: {{id_s}} "
alertDescriptionFormat: "\nSummary: {{summary_s}} \nAdditional info: {{details_s}}\nPlease investigate further on Theom UI at {{deepLink_s}}\n"
entityMappings:
- entityType: CloudApplication
fieldMappings:
- identifier: Name
columnName: customProps_AssetName_s
- entityType: URL
fieldMappings:
- identifier: Url
columnName: deepLink_s
version: 1.0.2
kind: Scheduled
Stages and Predicates
Stage 1: source
TheomAlerts_CL
Stage 2: where
| where priority_s == "P3"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
priority_s | eq |
| field:"priority_s" kind:eq value:"P3" |
TI Map URL Entity to DeviceNetworkEvents
#This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in DeviceNetworkEvents.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft Defender for Endpoint | DeviceNetworkEvents action any: Network activity |
Rule Body
id: 4f0356b2-d344-4c19-9375-31b9575d80cb
name: TI Map URL Entity to DeviceNetworkEvents
description: |
'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in DeviceNetworkEvents.'
severity: Medium
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceNetworkEvents
- 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;
let DeviceNetworkEvents_ = DeviceNetworkEvents
| where TimeGenerated >= ago(dt_lookBack)
| where ActionType !has "ConnectionFailed"
| project-rename DeviceNetworkEvents_TimeGenerated = TimeGenerated;
let DeviceNetworkEventUrls = DeviceNetworkEvents_
| distinct Url = RemoteUrl
| summarize make_list(Url);
ThreatIntelIndicators
//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)
| extend Url = tolower(Url)
| where Url in (DeviceNetworkEventUrls)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue
| where IsActive and (ValidUntil > now() or isempty(ValidUntil))
| extend Description = tostring(parse_json(Data).description)
| where Description !contains_cs "State: inactive;" and Description !contains_cs "State: falsepos;"
| project-reorder *, Tags, TrafficLightProtocolLevel, Url, Type
| join kind=innerunique (DeviceNetworkEvents_) on $left.Url == $right.RemoteUrl
| where DeviceNetworkEvents_TimeGenerated < ValidUntil
| summarize DeviceNetworkEvents_TimeGenerated = arg_max(DeviceNetworkEvents_TimeGenerated, *) by Id, Url
| extend Description = tostring(parse_json(Data).description)
| extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(parse_json(Data).labels))
| project DeviceNetworkEvents_TimeGenerated, Id, Url, Confidence, Description, Type, Tags, TrafficLightProtocolLevel, ActionType, DeviceId, DeviceName, InitiatingProcessAccountUpn, InitiatingProcessCommandLine, RemoteIP, RemotePort
| extend Name = tostring(split(InitiatingProcessAccountUpn, '@', 0)[0]), UPNSuffix = tostring(split(InitiatingProcessAccountUpn, '@', 1)[0])
| extend timestamp = DeviceNetworkEvents_TimeGenerated, UserPrincipalName = InitiatingProcessAccountUpn
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: DeviceName
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Url
- entityType: Process
fieldMappings:
- identifier: CommandLine
columnName: InitiatingProcessCommandLine
version: 1.0.5
kind: Scheduled
Stages and Predicates
Parameters
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
Let Binding: DeviceNetworkEvents_
let DeviceNetworkEvents_ = DeviceNetworkEvents
| where TimeGenerated >= ago(dt_lookBack)
| where ActionType !has "ConnectionFailed"
| project-rename DeviceNetworkEvents_TimeGenerated = TimeGenerated;
Let Binding: DeviceNetworkEventUrls
let DeviceNetworkEventUrls = DeviceNetworkEvents_
| distinct Url = RemoteUrl
| summarize make_list(Url);
Stage 1: source
let DeviceNetworkEvents_
Stage 2: source
let DeviceNetworkEventUrls
Stage 3: source
ThreatIntelIndicators
Stage 4: extend
extend IndicatorType
Stage 5: where
where IndicatorType == "url"
Stage 6: extend
extend Url
Stage 7: extend
extend TrafficLightProtocolLevel
Stage 8: where
where TimeGenerated >= ago(1209600s)
Stage 9: extend
extend Url
Stage 10: where
where Url == "DeviceNetworkEventUrls"
Stage 11: summarize
summarize LatestIndicatorTime by Id, ObservableValue
Stage 12: where
where (isempty(ValidUntil) or ValidUntil > now()) and IsActive == true
Stage 13: extend
extend Description
Stage 14: where
where not (Description contains_cs "State: falsepos;") and not (Description contains_cs "State: inactive;")
Stage 15: project-reorder
project-reorder
Stage 16: join
join kind=innerunique (DeviceNetworkEvents_) on $left.Url, $right.RemoteUrl
Stage 17: where
where DeviceNetworkEvents_TimeGenerated < ValidUntil
Stage 18: summarize
summarize DeviceNetworkEvents_TimeGenerated by Id, Url
Stage 19: extend
extend Description
Stage 20: extend
extend ActivityGroupNames
Stage 21: project
project ActionType, Confidence, Description, DeviceId, DeviceName, DeviceNetworkEvents_TimeGenerated, Id, InitiatingProcessAccountUpn, InitiatingProcessCommandLine, RemoteIP, RemotePort, Tags, TrafficLightProtocolLevel, Type, Url
Stage 22: extend
extend Name, UPNSuffix
Stage 23: extend
extend UserPrincipalName, 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" |
Url | in |
| field:"Url" kind:in value:"DeviceNetworkEventUrls" |
ValidUntil | is_null | field:"ValidUntil" kind:is_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
Description | contains | State: falsepos; | excludes:Description field:"Description" value:"State: falsepos;" |
Description | contains | State: inactive; | excludes:Description field:"Description" value:"State: inactive;" |
ActionType | match | ConnectionFailed | excludes:ActionType field:"ActionType" value:"ConnectionFailed" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActionType | project |
Confidence | project |
Description | project |
DeviceId | project |
DeviceName | project |
DeviceNetworkEvents_TimeGenerated | project |
Id | project |
InitiatingProcessAccountUpn | project |
InitiatingProcessCommandLine | project |
RemoteIP | project |
RemotePort | project |
Tags | project |
TrafficLightProtocolLevel | project |
Type | project |
Url | project |
Name | extend |
UPNSuffix | extend |
UserPrincipalName | extend |
timestamp | extend |
WMI Spawning Suspicious Child Process (Living off the Land)
#Detects WmiPrvSE.exe (the WMI Provider Host) spawning high-risk processes such as PowerShell, cmd.exe, cscript, or other LOLBins. WMI requires no external tools, generates minimal disk artifacts, and can execute code on remote systems over DCOM/RPC while bypassing many controls. Tune AllowlistedCmdPatterns for known-safe management tools such as SCCM.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Lateral Movement |
Telemetry Coverage
Rule Body
id: 3c8e5f0b-1d4a-4b69-9c2e-7f0d3a5e8b1f
name: WMI Spawning Suspicious Child Process (Living off the Land)
description: |
Detects WmiPrvSE.exe (the WMI Provider Host) spawning high-risk processes
such as PowerShell, cmd.exe, cscript, or other LOLBins.
WMI requires no external tools, generates minimal disk artifacts, and can
execute code on remote systems over DCOM/RPC while bypassing many controls.
Tune AllowlistedCmdPatterns for known-safe management tools such as SCCM.
severity: High
status: Available
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceProcessEvents
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Execution
- LateralMovement
- Persistence
relevantTechniques:
- T1047
- T1021.006
- T1059.001
- T1059.003
- T1059.005
query: |
let Lookback = 1h;
let SuspiciousChildProcesses = dynamic([
"powershell.exe", "pwsh.exe", "cmd.exe", "cscript.exe", "wscript.exe",
"mshta.exe", "certutil.exe", "bitsadmin.exe", "regsvr32.exe",
"rundll32.exe", "msiexec.exe", "installutil.exe", "cmstp.exe",
"msbuild.exe", "wmic.exe", "net.exe", "net1.exe", "nltest.exe",
"whoami.exe", "ipconfig.exe", "tasklist.exe", "schtasks.exe",
"at.exe", "sc.exe", "reg.exe"
]);
let AllowlistedCmdPatterns = dynamic([
"ccmexec", "SMSAgent", "MOMAgent", "nessus", "qualys"
]);
let NetworkIndicators = dynamic([
"http://", "https://", "ftp://", "Net.WebClient",
"DownloadString", "IEX", "Invoke-Expression", "/transfer", "-urlcache"
]);
let CredentialIndicators = dynamic([
"lsass", "mimikatz", "sekurlsa", "dump", "sam", "ntds"
]);
let MDE_Results =
DeviceProcessEvents
| where Timestamp >= ago(Lookback)
| where InitiatingProcessFileName =~ "WmiPrvSE.exe"
| where FileName in~ (SuspiciousChildProcesses)
| where not(ProcessCommandLine has_any (AllowlistedCmdPatterns))
| extend
ChildProcess = FileName,
ChildCmdLine = ProcessCommandLine,
AccountName = InitiatingProcessAccountName,
AccountDomain = InitiatingProcessAccountDomain,
HostName = DeviceName,
EventTime = Timestamp,
NetworkActivity = ProcessCommandLine has_any (NetworkIndicators),
CredentialActivity = ProcessCommandLine has_any (CredentialIndicators)
| project EventTime, HostName, AccountName, AccountDomain, ChildProcess,
ChildCmdLine, NetworkActivity, CredentialActivity;
let SecEvent_Results =
SecurityEvent
| where TimeGenerated >= ago(Lookback)
| where EventID == 4688
| where ParentProcessName endswith "\\WmiPrvSE.exe"
| extend ChildProcess = tostring(split(NewProcessName, "\\")[-1])
| where ChildProcess in~ (SuspiciousChildProcesses)
| where not(CommandLine has_any (AllowlistedCmdPatterns))
| extend
ChildCmdLine = CommandLine,
AccountName = SubjectUserName,
AccountDomain = SubjectDomainName,
HostName = Computer,
EventTime = TimeGenerated,
NetworkActivity = CommandLine has_any (NetworkIndicators),
CredentialActivity = CommandLine has_any (CredentialIndicators)
| project EventTime, HostName, AccountName, AccountDomain, ChildProcess,
ChildCmdLine, NetworkActivity, CredentialActivity;
union MDE_Results, SecEvent_Results
| extend RiskScore = iif(CredentialActivity == true, 3, iif(NetworkActivity == true, 2, 1))
| sort by RiskScore desc, EventTime desc
entityMappings:
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: HostName
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountDomain
- entityType: Process
fieldMappings:
- identifier: CommandLine
columnName: ChildCmdLine
version: 1.0.5
kind: Scheduled
Stages and Predicates
Parameters
let Lookback = 1h;
Let Binding: SuspiciousChildProcesses
let SuspiciousChildProcesses = dynamic([
"powershell.exe", "pwsh.exe", "cmd.exe", "cscript.exe", "wscript.exe",
"mshta.exe", "certutil.exe", "bitsadmin.exe", "regsvr32.exe",
"rundll32.exe", "msiexec.exe", "installutil.exe", "cmstp.exe",
"msbuild.exe", "wmic.exe", "net.exe", "net1.exe", "nltest.exe",
"whoami.exe", "ipconfig.exe", "tasklist.exe", "schtasks.exe",
"at.exe", "sc.exe", "reg.exe"
]);
Let Binding: AllowlistedCmdPatterns
let AllowlistedCmdPatterns = dynamic([
"ccmexec", "SMSAgent", "MOMAgent", "nessus", "qualys"
]);
Let Binding: NetworkIndicators
let NetworkIndicators = dynamic([
"http://", "https://", "ftp://", "Net.WebClient",
"DownloadString", "IEX", "Invoke-Expression", "/transfer", "-urlcache"
]);
Let Binding: CredentialIndicators
let CredentialIndicators = dynamic([
"lsass", "mimikatz", "sekurlsa", "dump", "sam", "ntds"
]);
Union (2 Sources)
Each leg below queries one source; the rule matches if any leg does. Sources: MDE_Results, SecEvent_Results
Leg 1: MDE_Results
Leg 2: SecEvent_Results
Applied to the Combined Result
| extend RiskScore = iif(CredentialActivity == true, 3, iif(NetworkActivity == true, 2, 1)) | sort by RiskScore desc, EventTime desc
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ChildProcess | in |
| field:"ChildProcess" kind:in |
EventID | eq |
| field:"EventID" kind:eq value:"4688" |
FileName | in |
| field:"FileName" kind:in |
InitiatingProcessFileName | eq |
| field:"InitiatingProcessFileName" kind:eq value:"WmiPrvSE.exe" |
ParentProcessName | ends_with |
| field:"ParentProcessName" kind:ends_with value:"\WmiPrvSE.exe" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
ProcessCommandLine | match | ccmexec, SMSAgent, MOMAgent, nessus, qualys | excludes:ProcessCommandLine |
CommandLine | match | ccmexec, SMSAgent, MOMAgent, nessus, qualys | excludes:CommandLine |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountDomain | project |
AccountName | project |
ChildCmdLine | project |
ChildProcess | project |
CredentialActivity | project |
EventTime | project |
HostName | project |
NetworkActivity | project |
RiskScore | extend |