Detection rules › Kusto

Kusto rules: 2z

1Password - Vault export

#
Severity
low
Time window
1h
Source
github.com/Azure/Azure-Sentinel

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

TacticTechniques
Credential Access

Telemetry Coverage

PlatformRecord / event type
1Passwordvault-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.

FieldKindValuesSearch
actioneq
  • export corpus 2 (kusto 2)
field:"action" kind:eq value:"export"
object_typeeq
  • vault corpus 2 (kusto 2)
field:"object_type" kind:eq value:"vault"

Output Fields

These fields are emitted when the rule matches.

FieldSource
SrcIpAddrextend
TargetUsernameextend

ASR Rare and Untrusted Executables

#
Group by
FileName, SHA1
Author
Cyb3rMonk
Source
github.com/Cyb3r-Monk/Threat-Hunting-and-Detection

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

TacticTechniques
StealthNo 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.

FieldKindValuesSearch
ActionTypein
  • AsrUntrustedExecutableAudited
  • AsrUntrustedExecutableBlocked
field:"ActionType" kind:in
LocalPrevalencele
  • 5 transforms: number
field:"LocalPrevalence" kind:le value:"5"

Output Fields

These fields are emitted when the rule matches.

FieldSource
FileNamesummarize
LocalPrevalencesummarize
SHA1summarize

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.

Status
available
Severity
medium
Time window
1h
Source
github.com/Azure/Azure-Sentinel

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.

FieldKindValuesSearch
Findingeq
  • AzureT0SyncedToEntraUser
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.

Status
available
Severity
medium
Time window
1h
Source
github.com/Azure/Azure-Sentinel

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.

FieldKindValuesSearch
Findingeq
  • T0CoerceAndRelayNTLMToLDAPS
field:"Finding" kind:eq value:"T0CoerceAndRelayNTLMToLDAPS"

CiscoISE - Device PostureStatus changed to non-compliant

#
Status
available
Severity
medium
Time window
15m
Source
github.com/Azure/Azure-Sentinel

'Detects when device changes PostureStatus from "Compliant".'

MITRE ATT&CK Coverage

TacticTechniques
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 used in Stage 4

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.

Output Fields

These fields are emitted when the rule matches.

FieldSource
DstIpAddrproject
IPCustomEntityextend

Claroty - Multiple failed logins to same destinations

#
Status
available
Severity
high
Time window
5m
Group by
Site
Source
github.com/Azure/Azure-Sentinel

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

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.

FieldKindValuesSearch
EventTypematch
  • Login to SRA transforms: term
field:"EventType" kind:match value:"Login to SRA"
FailedLoginsgt
  • 10 transforms: number
field:"FailedLogins" kind:gt value:"10"
Siteis_not_null
  • (no value, null check)
field:"Site" kind:is_not_null

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
EventTypematchsucceededexcludes:EventType field:"EventType" value:"succeeded"

Output Fields

These fields are emitted when the rule matches.

FieldSource
FailedLoginsproject
SGCustomEntityproject
SampleUserproject
Siteproject
Thresholdproject
TimeGeneratedproject

Claroty - Suspicious activity

#
Status
available
Severity
high
Time window
1h
Source
github.com/Azure/Azure-Sentinel

Detects suspicious behavior that is generally indicative of malware.

MITRE ATT&CK Coverage

TacticTechniques
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.

FieldKindValuesSearch
EventOriginalTypematch
  • Suspicious Activity transforms: term
field:"EventOriginalType" kind:match value:"Suspicious Activity"
EventTypematch
  • Suspicious Activity transforms: term
field:"EventType" kind:match value:"Suspicious Activity"

Output Fields

These fields are emitted when the rule matches.

FieldSource
DstIpAddrproject
EventOriginalTypeproject
EventTypeproject
TimeGeneratedproject
IPCustomEntityextend

Corelight - C2 DGA Detected Via Repetitive Failures

#
Status
available
Severity
medium
Time window
5m
Group by
id_orig_h, query
Source
github.com/Azure/Azure-Sentinel

'Detects large amounts of DNS resolution failures.'

MITRE ATT&CK Coverage

TacticTechniques
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.

FieldKindValuesSearch
count_gt
  • 25 transforms: number
field:"count_" kind:gt value:"25"
rcodein
  • 2
  • 3
field:"rcode" kind:in

Output Fields

These fields are emitted when the rule matches.

FieldSource
id_orig_hsummarize
querysummarize

CTE - Enrollment Token Generated

#
Severity
informational
Time window
1h
Source
github.com/Azure/Azure-Sentinel

An enrollment token was generated for onboarding a new device.

MITRE ATT&CK Coverage

TacticTechniques
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.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AccountNameproject
Actorproject
Categoryproject
Severityproject
Sourceproject
TenantIdproject
TimeGeneratedproject
UPNSuffixproject

Hunt for critical credentials on non Credential Guard enabled devices

#
Group by
$left.SourceNodeId, $right.NodeId, DeviceName
Author
Robbe Van den Daele
Source
github.com/HybridBrothers/Hunting-Queries-Detection-Rules

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 used in Stages 1, 6

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.

FieldSource
DeviceNamesummarize
UserListsummarize
UserCountextend

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.

Severity
high
Time window
15m
Source
github.com/Azure/Azure-Sentinel

Detects malicious scan results and actions which are not allowed

MITRE ATT&CK Coverage

TacticTechniques
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.

Pathlock TDnR - G/L Account Changes

#
Status
available
Severity
medium
Time window
1h
Source
github.com/Azure/Azure-Sentinel

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

TacticTechniques
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.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AffectedUserproject
Areaproject
Bnameproject
CentralTsproject
DataSourceproject
DestIpproject
Eventidproject
Hostnameproject
Instanceproject
LogLineproject
MessageV1project
MessageV2project
MessageV3project
MessageV4project
MsgIdproject
MsgNoproject
MsgTypeproject
Reportproject
SrcIpproject
Subidproject
Sysidproject
Tcodeproject
TimeGeneratedproject

Pathlock TDnR - SAP System Job Monitoring Events

#
Status
available
Severity
medium
Time window
1h
Source
github.com/Azure/Azure-Sentinel

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

TacticTechniques
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.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AffectedUserproject
Areaproject
Bnameproject
CentralTsproject
DataSourceproject
DestIpproject
Eventidproject
Hostnameproject
Instanceproject
LogLineproject
MessageV1project
MessageV2project
MessageV3project
MessageV4project
MsgIdproject
MsgNoproject
MsgTypeproject
Reportproject
SrcIpproject
Subidproject
Sysidproject
Tcodeproject
TimeGeneratedproject

Pathlock TDnR - Switchable Authorization Design Changes

#
Status
available
Severity
high
Time window
1h
Source
github.com/Azure/Azure-Sentinel

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

TacticTechniques
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.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AffectedUserproject
Areaproject
Bnameproject
CentralTsproject
DataSourceproject
DestIpproject
Eventidproject
Hostnameproject
Instanceproject
LogLineproject
MessageV1project
MessageV2project
MessageV3project
MessageV4project
MsgIdproject
MsgNoproject
MsgTypeproject
Reportproject
SrcIpproject
Subidproject
Sysidproject
Tcodeproject
TimeGeneratedproject

PowerShell Encoded Command Execution (Living off the Land)

#
Status
available
Severity
medium
Time window
1h
Source
github.com/Azure/Azure-Sentinel

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

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.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
InitiatingProcessFileNamematchSqlServer.exe, ManagementStudio.exe, devenv.exe, ccmexec.exe, SMSAgent.exeexcludes:InitiatingProcessFileName
ParentProcessNamematchSqlServer.exe, ManagementStudio.exe, devenv.exe, ccmexec.exe, SMSAgent.exeexcludes:ParentProcessName

Output Fields

These fields are emitted when the rule matches.

FieldSource
AccountDomainproject
AccountNameproject
EventTimeproject
HasDownloadCradleproject
HostNameproject
InitiatingProcessFileNameproject
ProcessCommandLineproject
RiskScoreextend

Probable AdFind Recon Tool Usage

#
Status
available
Severity
high
Time window
1h
Source
github.com/Azure/Azure-Sentinel

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

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 used in Stage 3

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.

FieldKindValuesSearch
FileNameeq
  • AdFind.exe corpus 2 (splunk 1, kusto 1)
field:"process_basename" kind:eq value:"AdFind.exe"
InitiatingProcessFileNamein
  • cmd.exe corpus 9 (splunk 7, elastic 1, kusto 1)
  • powershell.exe corpus 7 (splunk 5, elastic 1, kusto 1)
  • pwsh.exe corpus 7 (splunk 5, elastic 1, kusto 1)
field:"parent_process_basename" kind:in
ProcessCommandLinematch
  • Domain Admins transforms: term corpus 2 (kusto 2)
  • adinfo transforms: term corpus 2 (kusto 2)
  • computers_pwdnotreqd transforms: term corpus 2 (kusto 2)
  • dclist transforms: term corpus 2 (kusto 2)
  • dcmodes transforms: term corpus 2 (kusto 2)
  • domainlist transforms: term corpus 2 (kusto 2)
  • objectcategory transforms: term corpus 2 (kusto 2)
  • objectcategory=* transforms: term corpus 2 (kusto 2)
  • objectcategory=computer transforms: term corpus 2 (kusto 2)
  • objectcategory=person transforms: term corpus 2 (kusto 2)
  • trustdmp transforms: term corpus 2 (kusto 2)
field:"CommandLine" kind:match
SHA256eq
  • c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3 corpus 2 (kusto 2)
field:"sha256" kind:eq value:"c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3"

Output Fields

These fields are emitted when the rule matches.

FieldSource
DnsDomainextend
FileHashAlgorithmextend
HostNameextend

PROD (TM019.1) - TRUST - A new AD Trust has been established

#
Status
available
Severity
high
Time window
1h
Source
github.com/Azure/Azure-Sentinel

A new Trust has been established with the Forest or Domains. The other forest should have a Tier Model deployed.

MITRE ATT&CK Coverage

Telemetry Coverage

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.

FieldKindValuesSearch
EventDatamatch
  • "ObjectClass">trustedDomain transforms: term
  • CN=System transforms: term
field:"EventData" kind:match
EventIDeq
  • 5137 corpus 8 (kusto 5, elastic 3)
field:"EventID" kind:eq value:"5137"

Output Fields

These fields are emitted when the rule matches.

FieldSource
Accountproject
ActivityTypeproject
Channelproject
Computerproject
Domainproject
EventDataproject
EventIDproject
ObjectNameproject
TimeGeneratedproject

Rare and potentially high-risk Office operations

#
Status
available
Severity
low
Time window
1d
Source
github.com/Azure/Azure-Sentinel

Identifies Office operations that are typically rare and can provide capabilities useful to attackers.

MITRE ATT&CK Coverage

TacticTechniques
Persistence
Collection

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

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.

FieldKindValuesSearch
Operationin
  • Add-MailboxFolderPermission corpus 2 (splunk 1, kusto 1)
  • Add-MailboxPermission
  • New-InboxRule corpus 2 (splunk 1, kusto 1)
  • New-ManagementRoleAssignment
  • Set-InboxRule corpus 2 (splunk 1, kusto 1)
  • Set-Mailbox
  • Set-TransportRule corpus 3 (kusto 3)
field:"Operation" kind:in

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
OperationinAdd-MailboxPermission, Set-Mailboxexcludes:Operation field:"Operation" value:"Add-MailboxPermission" field:"Operation" value:"Set-Mailbox"
UserIdmatchNT AUTHORITY\SYSTEM (Microsoft.Exchange.ServiceHost), NT AUTHORITY\SYSTEM (Microsoft.Exchange.AdminApi.NetCore), NT AUTHORITY\SYSTEM (w3wp), devilfish-applicationaccountexcludes:UserId

Output Fields

These fields are emitted when the rule matches.

FieldSource
ClientIPOnlyextend
AccountNameextend
AccountUPNSuffixextend

Rare client observed with high reverse DNS lookup count

#
Status
available
Severity
medium
Time window
8d
Group by
ClientIP
Source
github.com/Azure/Azure-Sentinel

'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

TacticTechniques
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.

FieldKindValuesSearch
Namematch
  • in-addr.arpa transforms: term
field:"Name" kind:match value:"in-addr.arpa"
dcount_Namegt
  • 10 transforms: number
field:"dcount_Name" kind:gt value:"10"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
Namematchin-addr.arpaexcludes:Name field:"Name" value:"in-addr.arpa"
dcount_Namegt10excludes:dcount_Name field:"dcount_Name" value:"10"

Output Fields

These fields are emitted when the rule matches.

FieldSource
ClientIPproject
EndTimeUtcproject
ReverseDNSLookup_Listproject
StartTimeUtcproject
dcount_Nameproject

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.

Status
available
Severity
high
Time window
5m
Source
github.com/Azure/Azure-Sentinel

"Creates Microsoft Sentinel incidents for medium risk Theom alerts."

MITRE ATT&CK Coverage

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.

TI Map URL Entity to DeviceNetworkEvents

#
Severity
medium
Time window
14d
Group by
$left.Url, $right.RemoteUrl, Id, ObservableValue, Url
Source
github.com/Azure/Azure-Sentinel

This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in DeviceNetworkEvents.

MITRE ATT&CK Coverage

TacticTechniques
Command & Control

Telemetry Coverage

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_ used in Stages 1, 16

let DeviceNetworkEvents_ = DeviceNetworkEvents
  | where TimeGenerated >= ago(dt_lookBack)
  | where ActionType !has "ConnectionFailed"
  | project-rename DeviceNetworkEvents_TimeGenerated = TimeGenerated;

Let Binding: DeviceNetworkEventUrls used in Stages 2, 10

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.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
DescriptioncontainsState: falsepos;excludes:Description field:"Description" value:"State: falsepos;"
DescriptioncontainsState: inactive;excludes:Description field:"Description" value:"State: inactive;"
ActionTypematchConnectionFailedexcludes:ActionType field:"ActionType" value:"ConnectionFailed"

Output Fields

These fields are emitted when the rule matches.

FieldSource
ActionTypeproject
Confidenceproject
Descriptionproject
DeviceIdproject
DeviceNameproject
DeviceNetworkEvents_TimeGeneratedproject
Idproject
InitiatingProcessAccountUpnproject
InitiatingProcessCommandLineproject
RemoteIPproject
RemotePortproject
Tagsproject
TrafficLightProtocolLevelproject
Typeproject
Urlproject
Nameextend
UPNSuffixextend
UserPrincipalNameextend
timestampextend

WMI Spawning Suspicious Child Process (Living off the Land)

#
Status
available
Severity
high
Time window
1h
Source
github.com/Azure/Azure-Sentinel

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

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.

FieldKindValuesSearch
ChildProcessin
  • at.exe
  • bitsadmin.exe
  • certutil.exe
  • cmd.exe
  • cmstp.exe
  • cscript.exe
  • installutil.exe
  • ipconfig.exe
  • msbuild.exe
  • mshta.exe
  • msiexec.exe
  • net.exe
  • net1.exe
  • nltest.exe
  • powershell.exe
  • pwsh.exe
  • reg.exe
  • regsvr32.exe
  • rundll32.exe
  • sc.exe
  • schtasks.exe
  • tasklist.exe
  • whoami.exe
  • wmic.exe
  • wscript.exe
field:"ChildProcess" kind:in
EventIDeq
  • 4688
field:"EventID" kind:eq value:"4688"
FileNamein
  • at.exe
  • bitsadmin.exe
  • certutil.exe
  • cmd.exe
  • cmstp.exe
  • cscript.exe
  • installutil.exe
  • ipconfig.exe
  • msbuild.exe
  • mshta.exe
  • msiexec.exe
  • net.exe
  • net1.exe
  • nltest.exe
  • powershell.exe
  • pwsh.exe
  • reg.exe
  • regsvr32.exe
  • rundll32.exe
  • sc.exe
  • schtasks.exe
  • tasklist.exe
  • whoami.exe
  • wmic.exe
  • wscript.exe
field:"FileName" kind:in
InitiatingProcessFileNameeq
  • WmiPrvSE.exe
field:"InitiatingProcessFileName" kind:eq value:"WmiPrvSE.exe"
ParentProcessNameends_with
  • \WmiPrvSE.exe
field:"ParentProcessName" kind:ends_with value:"\WmiPrvSE.exe"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
ProcessCommandLinematchccmexec, SMSAgent, MOMAgent, nessus, qualysexcludes:ProcessCommandLine
CommandLinematchccmexec, SMSAgent, MOMAgent, nessus, qualysexcludes:CommandLine

Output Fields

These fields are emitted when the rule matches.

FieldSource
AccountDomainproject
AccountNameproject
ChildCmdLineproject
ChildProcessproject
CredentialActivityproject
EventTimeproject
HostNameproject
NetworkActivityproject
RiskScoreextend

Back to all Kusto rules