Detection rules › Kusto

Kusto rules: 25

BloodHound Attack Path Finding - SQL Admin Users on Tier Zero Computers

#

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 - SQL Admin Users on Tier Zero Computers

Rule Body

id: b3c6f684-5fb3-451d-b1d9-fec8089c2503
name: BloodHound Attack Path Finding - SQL Admin Users on Tier Zero Computers
description: BloodHound Attack Path Finding - SQL Admin Users on Tier Zero Computers
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 == "T0SQLAdmin"
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 == "T0SQLAdmin"

Indicators

These rows show field, operator, and value matches.

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

Cisco SE - Dropper activity on host

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

'Detects possible dropper activity on host.'

MITRE ATT&CK Coverage

Rule Body

id: b6df3e11-de70-4779-ac9a-276c454a9025
name: Cisco SE - Dropper activity on host
description: |
  'Detects possible dropper activity on host.'
severity: High
requiredDataConnectors:
  - connectorId: CiscoSecureEndpoint
    dataTypes:
      - CiscoSecureEndpoint
queryFrequency: 15m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - Execution
relevantTechniques:
  - T1204.002
query: |
  CiscoSecureEndpoint
  | where EventMessage has 'Potential Dropper Infection'
  | extend HostCustomEntity = DstHostname, MalwareCustomEntity = ThreatName
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: HostCustomEntity
  - entityType: Malware
    fieldMappings:
      - identifier: Name
        columnName: MalwareCustomEntity
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

CiscoSecureEndpoint

Stage 2: where

| where EventMessage has 'Potential Dropper Infection'

Stage 3: extend

| extend HostCustomEntity = DstHostname, MalwareCustomEntity = ThreatName

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
EventMessagematch
  • Potential Dropper Infection transforms: term
field:"EventMessage" kind:match value:"Potential Dropper Infection"

Output Fields

These fields are emitted when the rule matches.

FieldSource
HostCustomEntityextend
MalwareCustomEntityextend

Critical Risks

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

This query searches for all the exploited risks that RidgeBot identified

MITRE ATT&CK Coverage

Rule Body

id: 1eebfaf3-40e1-4bc2-9f42-049b7b8ceb60
name: Critical Risks
description: |
  This query searches for all the exploited risks that RidgeBot identified
severity: High
status: Available
requiredDataConnectors: 
  - connectorId: RidgeBotDataConnector
    dataTypes:
      - CommonSecurityLog
  - connectorId: CefAma
    dataTypes:
      - CommonSecurityLog
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Execution
  - InitialAccess
  - PrivilegeEscalation
relevantTechniques:
  - T1189
  - T1059
  - T1053
  - T1548
query: |
  CommonSecurityLog
  | where DeviceVendor == "RidgeSecurity"
  | where DeviceEventClassID == "4001"
  | order by TimeGenerated desc 
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: DeviceVendor
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: Computer
version: 1.0.1
kind: Scheduled

Stages and Predicates

Stage 1: source

CommonSecurityLog

Stage 2: where

| where DeviceVendor == "RidgeSecurity"

Stage 3: where

| where DeviceEventClassID == "4001"

Stage 4: sort

| order by TimeGenerated desc

Indicators

These rows show field, operator, and value matches.

Cyble Vision Alerts OSINT Mention Detected

#

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
low
Time window
30m
Source
github.com/Azure/Azure-Sentinel

'Triggers when Cyble detects an OSINT mention related to monitored keywords, entities, or brand identifiers. OSINT findings may indicate data leaks, expose content, targeting activity, impersonation, or discussions that may require investigation.'

MITRE ATT&CK Coverage

Rule Body

id: 9ff985d8-57a8-4302-a8e6-34fa96c3c505
name: Cyble Vision Alerts OSINT Mention Detected
description: |
  'Triggers when Cyble detects an OSINT mention related to monitored keywords, entities, or brand identifiers. OSINT findings may indicate data leaks, expose content, targeting activity, impersonation, or discussions that may require investigation.'
severity: Low
status: Available
requiredDataConnectors:
- connectorId: CybleVisionAlerts
  dataTypes:
  - CybleVisionAlerts_CL
enabled: true
queryfrequency: 30m
queryPeriod: 30m
triggerOperator: GreaterThan
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics:
- Reconnaissance
- ResourceDevelopment
relevantTechniques:
- T1592
- T1589
query: |
  Alerts_osint  
  | where Service == "osint" 
  | extend MappedSeverity = Severity
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
  alertDetailsOverride:
  alertDisplayNameFormat: OSINT Mention Identified for Monitored Keyword {{KeywordName}}
  alertDescriptionFormat: |
    A public OSINT mention referencing monitored keyword/entity {{KeywordName}} has been detected. Source {{OS_Source}}. Mention URL {{OS_MentionURL}}. This may indicate reputational impact, data exposure, or adversarial research targeting the organization.
customDetails:
  MappedSeverity: Severity
  Status: Status
  AlertID: AlertID
  Service: Service
  AuthorName: OS_AuthorName
  AuthorUsername: OS_AuthorUsername
  Source: OS_Source
  MentionDate: OS_MentionDate
  MentionURL: OS_MentionURL
  PostSnippet: OS_PostSnippet
entityMappings:
- entityType: DNS
  fieldMappings:
  - identifier: DomainName
    columnName: MA_Domain
- entityType: URL
  fieldMappings:
  - identifier: Url
    columnName: MA_DomainURL
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: KeywordName
- entityType: Host
  fieldMappings:
  - identifier: HostName
    columnName: Domain
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

Alerts_osint

Stage 2: where

| where Service == "osint"

Stage 3: extend

| extend MappedSeverity = Severity

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
MappedSeverityextend

Detect process drops via Azure Custom Script Extension performing lateral movement

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

This detection rule spots processes that where dropped via Azure Custom Script Extension on a machine and are now performing lateral movement. A common procedures for attackers when they compromised one machine is to move laterally to other machines via common protocols such as RDP, SSH, VNC, WMI, RPC, etc. It is not very common in an environment that Custom Script Extensions is being used for this.

MITRE ATT&CK Coverage

References

Telemetry Coverage

Rule Body

let process_drop_via_arc = (
    DeviceFileEvents
    | where TimeGenerated > ago(7d)
    // Search for file created events by Arc Custom Script Handler
    | where ActionType == "FileCreated"
    | where InitiatingProcessFileName =~ "customscripthandler.exe"
    | where isnotempty(SHA256)
    | distinct SHA256
);
DeviceNetworkEvents
| where TimeGenerated > ago(1h)
| join kind=inner process_drop_via_arc on $left.InitiatingProcessSHA256 == $right.SHA256
| where RemotePort in ("5985", "5986", "445", "3389", "22", "5900", "135")
| where ActionType in~ ("ConnectionSuccess", "ConnectionAttempt", 
"ConnectionFailed", "ConnectionRequest")

Stages and Predicates

Let Binding: process_drop_via_arc used in Stages 1, 4

let process_drop_via_arc = (
    DeviceFileEvents
    | where TimeGenerated > ago(7d)
    | where ActionType == "FileCreated"
    | where InitiatingProcessFileName =~ "customscripthandler.exe"
    | where isnotempty(SHA256)
    | distinct SHA256
);

Stage 1: source

let process_drop_via_arc

Stage 2: source

DeviceNetworkEvents

Stage 3: where

where TimeGenerated > ago(3600s)

Stage 4: join

join kind=inner (process_drop_via_arc) on $left.InitiatingProcessSHA256, $right.SHA256

Stage 5: where

where RemotePort in (135, 22, 3389, 445, 5900, 5985, 5986)

Stage 6: where

where ActionType in~ ("ConnectionAttempt", "ConnectionFailed", "ConnectionRequest", "ConnectionSuccess")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
ActionTypeeq
  • FileCreated
field:"ActionType" kind:eq value:"FileCreated"
ActionTypein
  • ConnectionAttempt
  • ConnectionFailed
  • ConnectionRequest
  • ConnectionSuccess
field:"ActionType" kind:in
InitiatingProcessFileNameeq
  • customscripthandler.exe
field:"InitiatingProcessFileName" kind:eq value:"customscripthandler.exe"
RemotePortin
  • 135
  • 22
  • 3389
  • 445
  • 5900
  • 5985
  • 5986
field:"RemotePort" kind:in
SHA256is_not_null
  • (no value, null check)
field:"SHA256" kind:is_not_null

End-user consent stopped due to risk-based consent

#
Severity
medium
Time window
1d
Author
Microsoft Security Research
Source
github.com/Azure/Azure-Sentinel

Detects a user's consent to an OAuth application being blocked due to it being too risky. These events should be investigated to understand why the user attempted to consent to the applicaiton and what other applicaitons they may have consented to. Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-applications#end-user-stopped-due-to-risk-based-consent

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: 009b9bae-23dd-43c4-bcb9-11c4ba7c784a
name: End-user consent stopped due to risk-based consent
description: |
  'Detects a user's consent to an OAuth application being blocked due to it being too risky.
    These events should be investigated to understand why the user attempted to consent to the applicaiton and what other applicaitons they may have consented to.
    Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-applications#end-user-stopped-due-to-risk-based-consent'
severity: Medium
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AuditLogs
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Persistence
  - PrivilegeEscalation
relevantTechniques:
  - T1078.004
tags:
  - AADSecOpsGuide
query: |
  AuditLogs
    | where OperationName has "Consent to application"
    | where Result =~ "failure"
    | extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
    | extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
    | extend InitiatingIPAddress = tostring(InitiatedBy.user.ipAddress)
    | extend userAgent = iif(AdditionalDetails[0].key == "User-Agent", tostring(AdditionalDetails[0].value), tostring(AdditionalDetails[1].value))
    | where isnotempty(TargetResources)
    | extend TargetAppName = tostring(TargetResources[0].displayName)
    | extend TargetAppId = tostring(TargetResources[0].id)
    | mv-expand TargetResources[0].modifiedProperties
    | extend TargetResources_0_modifiedProperties = columnifexists("TargetResources_0_modifiedProperties", '')
    | where isnotempty(TargetResources_0_modifiedProperties)
    | where TargetResources_0_modifiedProperties.displayName =~ "MethodExecutionResult."
    | extend TargetPropertyDisplayName = tostring(TargetResources_0_modifiedProperties.displayName)
    | extend FailureReason = tostring(parse_json(tostring(TargetResources_0_modifiedProperties.newValue)))
    | where FailureReason contains "Risky"
    | extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
    | project-reorder TimeGenerated, OperationName, Result, TargetAppName, TargetAppId, FailureReason, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingIPAddress, userAgent
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: InitiatingUserPrincipalName
      - identifier: Name
        columnName: InitiatingAccountName
      - identifier: UPNSuffix
        columnName: InitiatingAccountUPNSuffix
  - entityType: Account
    fieldMappings:
      - identifier: AadUserId
        columnName: InitiatingAadUserId
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: InitiatingIPAddress
  - entityType: CloudApplication
    fieldMappings:
      - identifier: AppId
        columnName: TargetAppId
      - identifier: Name
        columnName: TargetAppName
version: 1.1.1
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Microsoft Security Research
    support:
        tier: Community
    categories:
        domains: [ "Security - Others" ]

Stages and Predicates

Stage 1: source

AuditLogs

Stage 2: where

| where OperationName has "Consent to application"

Stage 3: where

| where Result =~ "failure"

Stage 4: extend (4 consecutive steps)

| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIPAddress = tostring(InitiatedBy.user.ipAddress)
| extend userAgent = iif(AdditionalDetails[0].key == "User-Agent", tostring(AdditionalDetails[0].value), tostring(AdditionalDetails[1].value))

Stage 5: where

| where isnotempty(TargetResources)

Stage 6: extend

| extend TargetAppName = tostring(TargetResources[0].displayName)

Stage 7: extend

| extend TargetAppId = tostring(TargetResources[0].id)

Stage 8: mv-expand

| mv-expand TargetResources[0].modifiedProperties

Stage 9: extend

| extend TargetResources_0_modifiedProperties = columnifexists("TargetResources_0_modifiedProperties", '')

Stage 10: where

| where isnotempty(TargetResources_0_modifiedProperties)

Stage 11: where

| where TargetResources_0_modifiedProperties.displayName =~ "MethodExecutionResult."

Stage 12: extend

| extend TargetPropertyDisplayName = tostring(TargetResources_0_modifiedProperties.displayName)

Stage 13: extend

| extend FailureReason = tostring(parse_json(tostring(TargetResources_0_modifiedProperties.newValue)))

Stage 14: where

| where FailureReason contains "Risky"

Stage 15: extend

| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])

Stage 16: project-reorder

| project-reorder TimeGenerated, OperationName, Result, TargetAppName, TargetAppId, FailureReason, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingIPAddress, userAgent

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
InitiatingUserPrincipalNameextend
InitiatingAadUserIdextend
InitiatingIPAddressextend
userAgentextend
TargetAppNameextend
TargetAppIdextend
TargetResources_0_modifiedPropertiesextend
TargetPropertyDisplayNameextend
FailureReasonextend
InitiatingAccountNameextend
InitiatingAccountUPNSuffixextend

Failover Plan Stopped

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

Detects when a failover plan stops. This might indicate disaster recovery activity or issues with primary systems.

Rule Body

id: de4cc05b-2e4e-4104-9559-101b4c41c35e
name: Failover Plan Stopped
description: Detects when a failover plan stops. This might indicate disaster recovery
  activity or issues with primary systems.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Syslog
  dataTypes:
  - Syslog
- connectorId: SyslogAma
  dataTypes:
  - Syslog
queryFrequency: 3h
queryPeriod: 3h
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: "Veeam_GetSecurityEvents\n| where instanceId == 26700\n| project\n    Date\
  \ = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),\n    DataSource = original_host,\n\
  \    EventId = instanceId,\n    UserName = user,\n MessageDetails = Description,\n\
  \   Severity = SeverityDescription"
version: 1.0.1
kind: Scheduled
customDetails:
  Date: Date
  VbrHostName: DataSource
  EventId: EventId
  MessageDetails: MessageDetails
  Severity: Severity

Stages and Predicates

Stage 1: source

Veeam_GetSecurityEvents

Stage 2: where

| where instanceId == 26700

Stage 3: project

| project
    Date = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),
    DataSource = original_host,
    EventId = instanceId,
    UserName = user,
 MessageDetails = Description,
   Severity = SeverityDescription

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
DataSourceproject
Dateproject
EventIdproject
MessageDetailsproject
Severityproject
UserNameproject

GitHub - User was invited to the repository

#
Status
available
Severity
medium
Time window
7d
Source
github.com/Azure/Azure-Sentinel

Detect activities when a user was invited to the repository. This query runs every day and its severity is Medium.

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: 0b85a077-8ba5-4cb5-90f7-1e882afe40c9
name: GitHub - User was invited to the repository
description: |
  'Detect activities when a user was invited to the repository. This query runs every day and its severity is Medium.'
severity: Medium
status: Available
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 7d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1078
query: |
    GitHubAuditData 
    | where Action == "org.invite_member"
    | project Actor, Action
    | extend Name = iif(Actor contains "@", split(Actor, "@")[0], Actor)
    | extend UPNSuffix = iif(Actor contains "@", split(Actor, "@")[1], "")
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: Actor
      - identifier: Name
        columnName: Name
      - identifier: UPNSuffix
        columnName: UPNSuffix
version: 1.0.1
kind: Scheduled

Stages and Predicates

Stage 1: source

GitHubAuditData

Stage 2: where

| where Action == "org.invite_member"

Stage 3: project

| project Actor, Action

Stage 4: extend

| extend Name = iif(Actor contains "@", split(Actor, "@")[0], Actor)

Stage 5: extend

| extend UPNSuffix = iif(Actor contains "@", split(Actor, "@")[1], "")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Actioneq
  • org.invite_member
field:"Action" kind:eq value:"org.invite_member"

Output Fields

These fields are emitted when the rule matches.

FieldSource
Actionproject
Actorproject
Nameextend
UPNSuffixextend

Jira - Global permission added

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

'Detects when global permission added.'

MITRE ATT&CK Coverage

TacticTechniques
Privilege Escalation

Rule Body

id: 5b0cec45-4a91-4f08-bb1b-392427e8f440
name: Jira - Global permission added
description: |
  'Detects when global permission added.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: JiraAuditAPI
    dataTypes:
      - JiraAudit
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - PrivilegeEscalation
relevantTechniques:
  - T1078
query: |
  JiraAudit
  | where EventMessage =~ 'Global permission added'
  | project EventCreationTime, ObjectItemName, UserName, SrcIpAddr, ChangedValues
  | extend AccountCustomEntity = UserName, IPCustomEntity = SrcIpAddr
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountCustomEntity
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPCustomEntity
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

JiraAudit

Stage 2: where

| where EventMessage =~ 'Global permission added'

Stage 3: project

| project EventCreationTime, ObjectItemName, UserName, SrcIpAddr, ChangedValues

Stage 4: extend

| extend AccountCustomEntity = UserName, IPCustomEntity = SrcIpAddr

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
ChangedValuesproject
EventCreationTimeproject
ObjectItemNameproject
SrcIpAddrproject
UserNameproject
AccountCustomEntityextend
IPCustomEntityextend

Microsoft Entra ID Hybrid Health AD FS Service Delete

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

This detection uses AzureActivity logs (Administrative category) to identify the deletion of an Microsoft Entra ID Hybrid Health AD FS service instance in a tenant. A threat actor can create a new AD Health ADFS service and create a fake server to spoof AD FS signing logs. The health AD FS service can then be deleted after it is no longer needed via HTTP requests to Azure. More information is available in this blog https://o365blog.com/post/hybridhealthagent/

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: 86a036b2-3686-42eb-b417-909fc0867771
name: Microsoft Entra ID Hybrid Health AD FS Service Delete
description: |
  'This detection uses AzureActivity logs (Administrative category) to identify the deletion of an Microsoft Entra ID Hybrid Health AD FS service instance in a tenant.
  A threat actor can create a new AD Health ADFS service and create a fake server to spoof AD FS signing logs.
  The health AD FS service can then be deleted after it is no longer needed via HTTP requests to Azure.
  More information is available in this blog https://o365blog.com/post/hybridhealthagent/'
severity: Medium
status: Available 
requiredDataConnectors:
  - connectorId: AzureActivity
    dataTypes:
      - AzureActivity
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1578.003
tags:
  - SimuLand
query: |
  AzureActivity
  | where CategoryValue =~ 'Administrative'
  | where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'
  | where _ResourceId has 'AdFederationService'
  | where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/delete'
  | extend claimsJson = parse_json(Claims)
  | extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])
  | project-away claimsJson
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: Caller
      - identifier: Name
        columnName: Name
      - identifier: UPNSuffix
        columnName: UPNSuffix
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: CallerIpAddress
version: 2.0.3
kind: Scheduled

Stages and Predicates

Stage 1: source

AzureActivity

Stage 2: where

| where CategoryValue =~ 'Administrative'

Stage 3: where

| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'

Stage 4: where

| where _ResourceId has 'AdFederationService'

Stage 5: where

| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/delete'

Stage 6: extend

| extend claimsJson = parse_json(Claims)

Stage 7: extend

| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])

Stage 8: project-away

| project-away claimsJson

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
CategoryValueeq
  • Administrative corpus 6 (kusto 4, sigma 2)
field:"CategoryValue" kind:eq value:"Administrative"
OperationNameValueeq
  • Microsoft.ADHybridHealthService/services/delete corpus 2 (sigma 1, kusto 1)
field:"azure_ad::operation_name_value" kind:eq value:"Microsoft.ADHybridHealthService/services/delete"
ResourceProviderValueeq
  • Microsoft.ADHybridHealthService corpus 6 (kusto 4, sigma 2)
field:"ResourceProviderValue" kind:eq value:"Microsoft.ADHybridHealthService"
_ResourceIdmatch
  • AdFederationService transforms: term corpus 4 (kusto 4)
field:"_ResourceId" kind:match value:"AdFederationService"

Output Fields

These fields are emitted when the rule matches.

FieldSource
AccountNameextend
AppIdextend
Nameextend
UPNSuffixextend

Microsoft Recommended Driver Block List

#

Pathlock TDnR - Authorization Role Changes

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

Detects changes to SAP authorization roles (PFCG), forwarded by Pathlock Threat Detection and Response. Unauthorized role modifications are one of the most common SAP privilege escalation vectors and may be used to grant unauthorized access to sensitive transactions or data.

MITRE ATT&CK Coverage

Rule Body

id: 2a3b4c5d-6e7f-4a0b-8c1d-2e3f4a5b6c46
name: Pathlock TDnR - Authorization Role Changes
kind: Scheduled
description: >-
  Detects changes to SAP authorization roles (PFCG), forwarded by Pathlock Threat Detection and
  Response. Unauthorized role modifications are one of the most common SAP privilege escalation
  vectors and may be used to grant unauthorized access to sensitive transactions or data.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: Pathlock_TDnR
    dataTypes:
      - Pathlock_TDnR_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - PrivilegeEscalation
  - Persistence
relevantTechniques:
  - T1548
  - T1098
query: |
  Pathlock_TDnR_CL
  | where DataSource == "ROLE_CHANGES"
  | 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 == "ROLE_CHANGES"

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

Samsung Knox - Peripheral Access Detection with Camera Events

#

This is a third-party alert feed, not a detection over modeled telemetry. The vendor product raised the finding; this rule forwards it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.

Status
available
Severity
high
Source
github.com/Azure/Azure-Sentinel

When camera access has been detected on a Knox device, even though such access is disabled through an MDM device policy.

Rule Body

id: cd526f4d-dbe9-4149-8a0a-9ec43c3abb16
name: Samsung Knox - Peripheral Access  Detection with Camera Events
version: 1.0.2
kind: NRT
description: When camera access has been detected on a Knox device, even though such access is disabled through an MDM device policy.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: SamsungDCDefinition
    dataTypes:
      - Samsung_Knox_System_CL
tactics: []
relevantTechniques: []
query: |
  Samsung_Knox_System_CL 
  | where Name == "PERIPHERAL_ACCESS_THROUGH_POLICY_DETECTED_CAMERA" 
  and MitreTtp has "KNOX.2"
suppressionEnabled: false
suppressionDuration: PT5H
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
eventGroupingSettings:
  aggregationKind: SingleAlert

Stages and Predicates

Stage 1: source

Samsung_Knox_System_CL

Stage 2: where

| where Name == "PERIPHERAL_ACCESS_THROUGH_POLICY_DETECTED_CAMERA" 
and MitreTtp has "KNOX.2"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
MitreTtpmatch
  • KNOX.2 transforms: term
field:"MitreTtp" kind:match value:"KNOX.2"
Nameeq
  • PERIPHERAL_ACCESS_THROUGH_POLICY_DETECTED_CAMERA
field:"Name" kind:eq value:"PERIPHERAL_ACCESS_THROUGH_POLICY_DETECTED_CAMERA"

Sign-ins from IPs that attempt sign-ins to disabled accounts (Uses Authentication Normalization)

#
Severity
medium
Time window
1d
Group by
SrcDvcIpAddr, Type
Source
github.com/Azure/Azure-Sentinel

Identifies IPs with failed attempts to sign in to one or more disabled accounts signed in successfully to another account. To use this analytics rule, make sure you have deployed the ASIM normalization parsers

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

id: 95002681-4ecb-4da3-9ece-26d7e5feaa33
name: Sign-ins from IPs that attempt sign-ins to disabled accounts (Uses Authentication Normalization)
description: |
  'Identifies IPs with failed attempts to sign in to one or more disabled accounts signed in successfully to another account.
  To use this analytics rule, make sure you have deployed the [ASIM normalization parsers](https://aka.ms/ASimAuthentication)'
severity: Medium
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
  - Persistence
relevantTechniques:
  - T1078
  - T1098
tags:
  - Id: 500c103a-0319-4d56-8e99-3cec8d860757
    version: 1.0.0
query: |
  imAuthentication
  | where EventResult =='Failure'
  | where EventResultDetails == 'User disabled'
  | summarize StartTime=min(EventStartTime), EndTime=max(EventEndTime), disabledAccountLoginAttempts = count()
        , disabledAccountsTargeted = dcount(TargetUsername), disabledAccountSet = make_set(TargetUsername)
        , applicationsTargeted = dcount(TargetAppName)
        , applicationSet = make_set(TargetAppName) 
        by SrcDvcIpAddr, Type
  | order by disabledAccountLoginAttempts desc
  | join kind=leftouter 
      (
      // Consider these IPs suspicious - and alert any related  successful sign-ins
      imAuthentication
      | where EventResult=='Success'
      | summarize successfulAccountSigninCount = dcount(TargetUsername), successfulAccountSigninSet = makeset(TargetUsername, 15) by SrcDvcIpAddr, Type
      // Assume IPs associated with sign-ins from 100+ distinct user accounts are safe
      | where successfulAccountSigninCount < 100
      )
      on SrcDvcIpAddr
  | where isnotempty(successfulAccountSigninCount)
  | project StartTime, EndTime, SrcDvcIpAddr, disabledAccountLoginAttempts, disabledAccountsTargeted, disabledAccountSet, applicationSet, 
  successfulAccountSigninCount, successfulAccountSigninSet, Type
  | order by disabledAccountLoginAttempts

entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SrcDvcIpAddr
version: 1.0.3
kind: Scheduled
metadata:
  source:
    kind: Community

Stages and Predicates

Stage 1: source

imAuthentication

Stage 2: where

| where EventResult =='Failure'

Stage 3: where

| where EventResultDetails == 'User disabled'

Stage 4: summarize

| summarize StartTime=min(EventStartTime), EndTime=max(EventEndTime), disabledAccountLoginAttempts = count()
      , disabledAccountsTargeted = dcount(TargetUsername), disabledAccountSet = make_set(TargetUsername)
      , applicationsTargeted = dcount(TargetAppName)
      , applicationSet = make_set(TargetAppName) 
      by SrcDvcIpAddr, Type

Stage 5: sort

| order by disabledAccountLoginAttempts desc

Stage 6: join

| join kind=leftouter 
    (
    imAuthentication
    | where EventResult=='Success'
    | summarize successfulAccountSigninCount = dcount(TargetUsername), successfulAccountSigninSet = makeset(TargetUsername, 15) by SrcDvcIpAddr, Type
    | where successfulAccountSigninCount < 100
    )
    on SrcDvcIpAddr

Stage 7: where

where isnotempty(successfulAccountSigninCount)

Stage 8: project

project EndTime, SrcDvcIpAddr, StartTime, Type, applicationSet, disabledAccountLoginAttempts, disabledAccountSet, disabledAccountsTargeted, successfulAccountSigninCount, successfulAccountSigninSet

Stage 9: sort

sort by disabledAccountLoginAttempts

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
EndTimeproject
SrcDvcIpAddrproject
StartTimeproject
Typeproject
applicationSetproject
disabledAccountLoginAttemptsproject
disabledAccountSetproject
disabledAccountsTargetedproject
successfulAccountSigninCountproject
successfulAccountSigninSetproject

Suspicious parentprocess relationship - Office child processes.

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

The attacker sends a spearphishing email to a user. The email contains a link, which points to a website that eventually presents the user a download of an MS Office document. This document contains a malicious macro. The macro spawns a new child process providing initial access. This detection looks for suspicious parent-process chains starting with a browser which spawns an Office application which spawns something else.

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Telemetry Coverage

Rule Body

id: 5ee34fa1-64ed-48c7-afa2-794b244f6c60
name: Suspicious parentprocess relationship - Office child processes. 
description: |
  The attacker sends a spearphishing email to a user. The email contains a link, which points to a website that eventually presents the user a download of an MS Office document. This document contains a malicious macro. The macro spawns a new child process providing initial access. This detection looks for suspicious parent-process chains starting with a browser which spawns an Office application which spawns something else.
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - DeviceProcessEvents
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1566.002
query: |
  let browsers = dynamic(["iexplore.exe", "chrome.exe", "firefox.exe", "msedge.exe"]); // Customize this list for your environment.
  let officeApps = dynamic(["winword.exe", "excel.exe", "powerpnt.exe"]); // Consider adding other Office applications such as Publisher, Visio and Access. 
  // This is an allow-list of the most common child processes. This is a quick and dirty solution. Consider allow-listing the full process path instead of file name.
  // Also, make this list as short as possible. Remove anything from this list if it doesn't occur in your organization. 
  let allowList = dynamic(["MSOSYNC.exe", "splwow64.exe", "csc.exe", "outlook.exe", "AcroRd32.exe", "Acrobat.exe", "explorer.exe", "DW20.exe", 
  "Microsoft.Mashup.Container.Loader.exe", "Microsoft.Mashup.Container.NetFX40.exe", "WerFault.exe", "CLVIEW.exe"]); 
  DeviceProcessEvents
  | where InitiatingProcessParentFileName in~ (browsers) and InitiatingProcessFileName in~ (officeApps) and 
  FileName !in~ (officeApps) and FileName !in~ (browsers) and FileName !in~ (allowList)
  | project-rename ProcessStart_Timestamp = Timestamp
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: DeviceName
  - entityType: Account
    fieldMappings:
      - identifier: Sid
        columnName: AccountSid 
      - identifier: Name
        columnName: AccountName
      - identifier: NTDomain
        columnName: AccountDomain
  - entityType: Process
    fieldMappings:
      - identifier: CommandLine
        columnName: ProcessCommandLine
version: 1.0.1
kind: Scheduled

Stages and Predicates

Parameters

let browsers = dynamic(["iexplore.exe", "chrome.exe", "firefox.exe", "msedge.exe"]);
let officeApps = dynamic(["winword.exe", "excel.exe", "powerpnt.exe"]);

Let Binding: allowList used in Stage 2

let allowList = dynamic(["MSOSYNC.exe", "splwow64.exe", "csc.exe", "outlook.exe", "AcroRd32.exe", "Acrobat.exe", "explorer.exe", "DW20.exe", 
"Microsoft.Mashup.Container.Loader.exe", "Microsoft.Mashup.Container.NetFX40.exe", "WerFault.exe", "CLVIEW.exe"]);

Stage 1: source

DeviceProcessEvents

Stage 2: where

| where InitiatingProcessParentFileName in~ (browsers) and InitiatingProcessFileName in~ (officeApps) and 
FileName !in~ (officeApps) and FileName !in~ (browsers) and FileName !in~ (allowList)

Stage 3: project-rename

| project-rename ProcessStart_Timestamp = Timestamp

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
InitiatingProcessFileNamein
  • excel.exe corpus 7 (splunk 5, kusto 2)
  • powerpnt.exe corpus 6 (splunk 5, kusto 1)
  • winword.exe corpus 7 (splunk 5, kusto 2)
field:"parent_process_basename" kind:in
InitiatingProcessParentFileNamein
  • chrome.exe
  • firefox.exe
  • iexplore.exe
  • msedge.exe
field:"grandparent_process_basename" kind:in

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
FileNameinAcroRd32.exe, Acrobat.exe, CLVIEW.exe, DW20.exe, MSOSYNC.exe, Microsoft.Mashup.Container.Loader.exe, Microsoft.Mashup.Container.NetFX40.exe, WerFault.exe, csc.exe, explorer.exe, outlook.exe, splwow64.exeexcludes:FileName
FileNameinchrome.exe, firefox.exe, iexplore.exe, msedge.exeexcludes:FileName
FileNameinexcel.exe, powerpnt.exe, winword.exeexcludes:FileName field:"FileName" value:"excel.exe" field:"FileName" value:"powerpnt.exe" field:"FileName" value:"winword.exe"

Output Fields

These fields are emitted when the rule matches.

FieldSource
ProcessStart_Timestampproject-rename

Unused IaaS Policy

#

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
30m
Source
github.com/Azure/Azure-Sentinel

The policy detects 'IaaS policies' that no one in the account has been using during the last X days.

MITRE ATT&CK Coverage

Rule Body

id: e0ae5f9e-865b-41f5-98bb-c04113888e85
name: Unused IaaS Policy
kind: Scheduled
description: The policy detects 'IaaS policies' that no one in the account has been using during the last X days.
severity: High
status: Available
queryFrequency: 30m
queryPeriod: 30m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
  - PrivilegeEscalation
relevantTechniques:
  - T1078
  - T1068
  - T1078
query: |-
  Authomize_v2_CL
  | where ingestion_time() >= ago(30m)
  | extend EventID = id_s, Policy = policy_name_s, Severity = severity_s,Description = description_s,Recommendation = recommendation_s,URL = url_s,Tactics = tactics_s
  | where Policy has "Unused IaaS Policy"
  | project  EventID, Policy, Severity, Description, Recommendation, URL, Category, Tactics
entityMappings:
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: URL
requiredDataConnectors:
- connectorId: Authomize
  dataTypes: [ "Authomize_v2_CL" ]
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: 5h
    matchingMethod: AnyAlert
    groupByEntities: []
    groupByAlertDetails: []
    groupByCustomDetails: []
eventGroupingSettings:
  aggregationKind: SingleAlert
alertDetailsOverride:
  alertnameFormat: Alert from Authomize - Unused IaaS Policy
  alertDescriptionFormat: |
    Unused IaaS Policy. The policy detects 'IaaS policies' that no one in the account has been using during the last X days.
  alertSeverity: Severity
  alertTactics: Tactics
  alertDynamicProperties:
  - alertProperty: AlertLink
    value: URL
customDetails:
  AuthomizeEventID: EventID
  EventName: Policy
  EventDescription: Description
  EventRecommendation: Recommendation
  ReferencedURL: URL
suppressionDuration: 5h
suppressionEnabled: false
version: 1.0.2

Stages and Predicates

Stage 1: source

Authomize_v2_CL

Stage 2: where

| where ingestion_time() >= ago(30m)

Stage 3: extend

| extend EventID = id_s, Policy = policy_name_s, Severity = severity_s,Description = description_s,Recommendation = recommendation_s,URL = url_s,Tactics = tactics_s

Stage 4: where

| where Policy has "Unused IaaS Policy"

Stage 5: project

| project  EventID, Policy, Severity, Description, Recommendation, URL, Category, Tactics

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Policymatch
  • Unused IaaS Policy transforms: term
field:"policy_name_s" kind:match value:"Unused IaaS Policy"

Output Fields

These fields are emitted when the rule matches.

FieldSource
Categoryproject
Descriptionproject
EventIDproject
Policyproject
Recommendationproject
Severityproject
Tacticsproject
URLproject

Back to all Kusto rules