Detection rules › Kusto

Kusto rules: 2i

ADWS Connection from Unexpected Binary

#
Author
FalconForce
Source
github.com/FalconForceTeam/FalconFriday

This query first collects the IP addresses of all machines that have the Active Directory Web Services (ADWS) service running. It then searches for network connections to these IP addresses from processes that are not expected to connect to ADWS.

Known False Positives

  • ADWS is used by a number of legitimate applications that need to interact with Active Directory. These applications should be added to the allow-listing to avoid false positives.

MITRE ATT&CK Coverage

References

Telemetry Coverage

Rule Body

let timeframe = 2*1h;
let ADWSIPs=(
    DeviceNetworkEvents
    | where ingestion_time() >= ago(timeframe)
    | where InitiatingProcessFolderPath == @"c:\windows\adws\microsoft.activedirectory.webservices.exe"
    | where LocalPort == 9389
    | distinct LocalIP
);
DeviceNetworkEvents
| where ingestion_time() >= ago(timeframe)
| where ActionType == "ConnectionSuccess"
| where RemotePort == 9389
| where RemoteIP in (ADWSIPs)
| where not(isempty(InitiatingProcessFileName))
| where not(InitiatingProcessFolderPath in~ (@"c:\windows\system32\dsac.exe", @"c:\program files\powershell\7\pwsh.exe"))
| where not(InitiatingProcessFolderPath startswith @"c:\windows\system32\windowspowershell\")
| where not(InitiatingProcessFolderPath startswith @"c:\windows\syswow64\windowspowershell\")
| where not(InitiatingProcessFolderPath startswith @"c:\program files\microsoft monitoring agent\")
// Begin environment-specific filter.
// End environment-specific filter.

Stages and Predicates

Parameters

let timeframe = 2*1h;

Let Binding: ADWSIPs used in Stages 1, 6

let ADWSIPs = (
    DeviceNetworkEvents
    | where ingestion_time() >= ago(timeframe)
    | where InitiatingProcessFolderPath == @"c:\windows\adws\microsoft.activedirectory.webservices.exe"
    | where LocalPort == 9389
    | distinct LocalIP
);

Stage 1: source

let ADWSIPs

Stage 2: source

DeviceNetworkEvents

Stage 3: where

where ...

Stage 4: where

where ActionType == "ConnectionSuccess"

Stage 5: where

where RemotePort == 9389

Stage 6: where

where RemoteIP == "ADWSIPs"

Stage 7: where

where not (isempty(InitiatingProcessFileName))

Stage 8: where

where not (InitiatingProcessFolderPath in~ (@"c:\program files\powershell\7\pwsh.exe", @"c:\windows\system32\dsac.exe"))

Stage 9: where

where not (InitiatingProcessFolderPath startswith @"c:\windows\system32\windowspowershell\")

Stage 10: where

where not (InitiatingProcessFolderPath startswith @"c:\windows\syswow64\windowspowershell\")

Stage 11: where

where not (InitiatingProcessFolderPath startswith @"c:\program files\microsoft monitoring agent\")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
InitiatingProcessFileNameis_null(no value, null check)excludes:InitiatingProcessFileName
InitiatingProcessFolderPathinc:\program files\powershell\7\pwsh.exe, c:\windows\system32\dsac.exeexcludes:InitiatingProcessFolderPath field:"InitiatingProcessFolderPath" value:"c:\program files\powershell\7\pwsh.exe" field:"InitiatingProcessFolderPath" value:"c:\windows\system32\dsac.exe"
InitiatingProcessFolderPathstarts_withc:\windows\system32\windowspowershell\excludes:InitiatingProcessFolderPath field:"InitiatingProcessFolderPath" value:"c:\windows\system32\windowspowershell\"
InitiatingProcessFolderPathstarts_withc:\windows\syswow64\windowspowershell\excludes:InitiatingProcessFolderPath field:"InitiatingProcessFolderPath" value:"c:\windows\syswow64\windowspowershell\"
InitiatingProcessFolderPathstarts_withc:\program files\microsoft monitoring agent\excludes:InitiatingProcessFolderPath field:"InitiatingProcessFolderPath" value:"c:\program files\microsoft monitoring agent\"

Alsid Active Directory attacks pathways

#
Status
available
Severity
low
Time window
2h
Group by
Severity
Source
github.com/Azure/Azure-Sentinel

'Searches for triggered Indicators of Exposures related to Active Directory attacks pathways'

MITRE ATT&CK Coverage

TacticTechniques
Credential Access

Rule Body

id: 9649e203-3cb7-47ff-89a9-42f2a5eefe31
name: Alsid Active Directory attacks pathways
description: |
    'Searches for triggered Indicators of Exposures related to Active Directory attacks pathways'
severity: Low
requiredDataConnectors:
  - connectorId: AlsidForAD
    dataTypes:
      - AlsidForADLog_CL
queryFrequency: 2h
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - CredentialAccess
relevantTechniques:
  - T1110
query: |
  let SeverityTable=datatable(Severity:string,Level:int) [
  "low", 1,
  "medium", 2,
  "high", 3,
  "critical", 4
  ];
  let codeNameList = datatable(Codename:string)["C-PRIV-ACCOUNTS-SPN", "C-SDPROP-CONSISTENCY", "C-DANG-PRIMGROUPID", "C-GPO-HARDENING", "C-DC-ACCESS-CONSISTENCY", "C-DANGEROUS-TRUST-RELATIONSHIP", "C-UNCONST-DELEG", "C-ABNORMAL-ENTRIES-IN-SCHEMA"];
  afad_parser
  | where MessageType == 0 and Codename in~ (codeNameList)
  | lookup kind=leftouter SeverityTable on Severity
  | order by Level
  | extend HostName = tostring(split(Host, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Host, '.'), 1, -1), '.'))
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
version: 1.0.1
kind: Scheduled

Stages and Predicates

Let Binding: SeverityTable used in Stage 3

let SeverityTable = datatable(Severity:string,Level:int) [
"low", 1,
"medium", 2,
"high", 3,
"critical", 4
];

Let Binding: codeNameList used in Stage 2

let codeNameList = datatable(Codename:string)["C-PRIV-ACCOUNTS-SPN", "C-SDPROP-CONSISTENCY", "C-DANG-PRIMGROUPID", "C-GPO-HARDENING", "C-DC-ACCESS-CONSISTENCY", "C-DANGEROUS-TRUST-RELATIONSHIP", "C-UNCONST-DELEG", "C-ABNORMAL-ENTRIES-IN-SCHEMA"];

Stage 1: source

afad_parser

Stage 2: where

| where MessageType == 0 and Codename in~ (codeNameList)

Stage 3: kusto:lookup

lookup kind=leftouter (SeverityTable) on Severity

Stage 4: sort

sort by Level

Stage 5: extend

extend DnsDomain, HostName

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
DnsDomainextend
HostNameextend

BloodHound Attack Path Finding - GenericWrite Privileges on Tier Zero Objects

#

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 - GenericWrite Privileges on Tier Zero Objects

Rule Body

id: 20d7a85c-6af9-4471-a403-961445c0e49e
name: BloodHound Attack Path Finding - GenericWrite Privileges on Tier Zero Objects
description: BloodHound Attack Path Finding - GenericWrite Privileges on Tier Zero
  Objects
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 == \"T0GenericWrite\""
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 == "T0GenericWrite"

Indicators

These rows show field, operator, and value matches.

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

BloodHound Attack Path Finding - Large Default Groups With Resource-Based Constrained Delegation Privileges

#

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 - Large Default Groups With Resource-Based Constrained Delegation Privileges

Rule Body

id: a50a328d-a14d-4599-a4e4-32de5b7fe0c7
name: BloodHound Attack Path Finding - Large Default Groups With Resource-Based Constrained
  Delegation Privileges
description: BloodHound Attack Path Finding - Large Default Groups With Resource-Based
  Constrained Delegation Privileges
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 == "LargeDefaultGroupsAddAllowedToAct"
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 == "LargeDefaultGroupsAddAllowedToAct"

Indicators

These rows show field, operator, and value matches.

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

Cisco Umbrella - Crypto Miner User-Agent Detected

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

'Detects suspicious user agent strings used by crypto miners in proxy logs.'

MITRE ATT&CK Coverage

TacticTechniques
Command & ControlNo specific technique

Rule Body

id: b619d1f1-7f39-4c7e-bf9e-afbb46457997
name: Cisco Umbrella - Crypto Miner User-Agent Detected
description: |
  'Detects suspicious user agent strings used by crypto miners in proxy logs.'
severity: Medium
requiredDataConnectors:
  - connectorId: CiscoUmbrellaDataConnector
    dataTypes:
      - Cisco_Umbrella_proxy_CL
queryFrequency: 15m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CommandAndControl
query: |
  let timeframe = 15m;
  Cisco_Umbrella
  | where EventType == "proxylogs"
  | where TimeGenerated > ago(timeframe)
  | where HttpUserAgentOriginal contains "XMRig" or HttpUserAgentOriginal contains "ccminer"
  | extend Message = "Crypto Miner User Agent"
  | project Message, SrcIpAddr, DstIpAddr, UrlOriginal, TimeGenerated,HttpUserAgentOriginal
entityMappings:
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: UrlOriginal
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SrcIpAddr
version: 1.1.2
kind: Scheduled

Stages and Predicates

Parameters

let timeframe = 15m;

Stage 1: source

Cisco_Umbrella

Stage 2: where

| where EventType == "proxylogs"

Stage 3: where

| where TimeGenerated > ago(timeframe)

Stage 4: where

| where HttpUserAgentOriginal contains "XMRig" or HttpUserAgentOriginal contains "ccminer"

Stage 5: extend

| extend Message = "Crypto Miner User Agent"

Stage 6: project

| project Message, SrcIpAddr, DstIpAddr, UrlOriginal, TimeGenerated,HttpUserAgentOriginal

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
DstIpAddrproject
HttpUserAgentOriginalproject
Messageproject
SrcIpAddrproject
TimeGeneratedproject
UrlOriginalproject

Cisco Umbrella - Rare User Agent Detected

#
Severity
medium
Time window
14d
Source
github.com/Azure/Azure-Sentinel

'Rule helps to detect a rare user-agents indicating web browsing activity by an unusual process other than a web browser.'

MITRE ATT&CK Coverage

TacticTechniques
Command & ControlNo specific technique

Rule Body

id: 8c8de3fa-6425-4623-9cd9-45de1dd0569a
name: Cisco Umbrella - Rare User Agent Detected
description: |
  'Rule helps to detect a rare user-agents indicating web browsing activity by an unusual process other than a web browser.'
severity: Medium
requiredDataConnectors:
  - connectorId: CiscoUmbrellaDataConnector
    dataTypes:
      - Cisco_Umbrella_proxy_CL
queryFrequency: 1d
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CommandAndControl
query: |
  let lookBack = 14d;
  let timeframe = 1d;
  let user_agents_list = Cisco_Umbrella
  | where EventType == "proxylogs"
  | where TimeGenerated > ago(lookBack) and TimeGenerated < ago(timeframe)
  | summarize count() by HttpUserAgentOriginal
  | summarize make_list(HttpUserAgentOriginal);
  Cisco_Umbrella
  | where EventType == "proxylogs"
  | where TimeGenerated > ago(timeframe)
  | where HttpUserAgentOriginal !in (user_agents_list)
  | extend Message = "Rare User Agent"
  | project Message, SrcIpAddr, DstIpAddr, UrlOriginal, TimeGenerated, HttpUserAgentOriginal
entityMappings:
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: UrlOriginal
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SrcIpAddr
version: 1.1.2
kind: Scheduled

Stages and Predicates

Parameters

let lookBack = 14d;
let timeframe = 1d;

Let Binding: user_agents_list used in Stage 4

let user_agents_list = Cisco_Umbrella
| where EventType == "proxylogs"
| where TimeGenerated > ago(lookBack) and TimeGenerated < ago(timeframe)
| summarize count() by HttpUserAgentOriginal
| summarize make_list(HttpUserAgentOriginal);

Stage 1: source

Cisco_Umbrella

Stage 2: where

| where EventType == "proxylogs"

Stage 3: where

| where TimeGenerated > ago(timeframe)

Stage 4: where

| where HttpUserAgentOriginal !in (user_agents_list)

Stage 5: extend

| extend Message = "Rare User Agent"

Stage 6: project

| project Message, SrcIpAddr, DstIpAddr, UrlOriginal, TimeGenerated, HttpUserAgentOriginal

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
HttpUserAgentOriginalequser_agents_listexcludes:HttpUserAgentOriginal field:"HttpUserAgentOriginal" value:"user_agents_list"

Output Fields

These fields are emitted when the rule matches.

FieldSource
DstIpAddrproject
HttpUserAgentOriginalproject
Messageproject
SrcIpAddrproject
TimeGeneratedproject
UrlOriginalproject

Conditional Access - A Conditional Access Device platforms condition has changed (the Device platforms condition can be spoofed)

#
Severity
low
Time window
5m
Source
github.com/Azure/Azure-Sentinel

A Conditional Access Device platforms condition has changed (the Device platforms condition can be spoofed) in Entra ID.

MITRE ATT&CK Coverage

Telemetry Coverage

PlatformRecord / event type
AzureUpdate conditional access policy

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: e3368079-a2c0-4f1c-9fb7-287e907393ef
name: Conditional Access - A Conditional Access Device platforms condition has changed (the Device platforms condition can be spoofed)
version: 1.0.1
kind: Scheduled
description: A Conditional Access Device platforms condition has changed (the Device platforms condition can be spoofed) in Entra ID.
severity: Low
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AuditLogs
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1562.007
query: |+
  // A Conditional Access Device platforms condition has changed (the Device platforms condition can be spoofed).
  AuditLogs
  | where OperationName in ("Update conditional access policy")
  | extend excludePlatformsOld = extractjson("$.conditions.platforms.excludePlatforms", tostring(TargetResources[0].modifiedProperties[0].oldValue))
  | extend excludePlatformsNew = extractjson("$.conditions.platforms.excludePlatforms", tostring(TargetResources[0].modifiedProperties[0].newValue))
  | where excludePlatformsOld != excludePlatformsNew
  | extend modifiedBy = tostring(InitiatedBy.user.userPrincipalName)
  | extend accountName = tostring(split(modifiedBy, "@")[0])
  | extend upnSuffix = tostring(split(modifiedBy, "@")[1])
  | project
      TimeGenerated,
      OperationName,
      policy = TargetResources[0].displayName,
      modifiedBy,
      accountName,
      upnSuffix,
      result = Result,
      excludePlatformsOld,
      excludePlatformsNew
  | order by TimeGenerated desc
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: accountName
      - identifier: UPNSuffix
        columnName: upnSuffix
suppressionEnabled: false
suppressionDuration: 5h
eventGroupingSettings:
  aggregationKind: AlertPerResult
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT1H
    matchingMethod: AllEntities
    groupByEntities: []
    groupByAlertDetails: []
    groupByCustomDetails: []

Stages and Predicates

Stage 1: source

AuditLogs

Stage 2: where

| where OperationName in ("Update conditional access policy")

Stage 3: extend

| extend excludePlatformsOld = extractjson("$.conditions.platforms.excludePlatforms", tostring(TargetResources[0].modifiedProperties[0].oldValue))

Stage 4: extend

| extend excludePlatformsNew = extractjson("$.conditions.platforms.excludePlatforms", tostring(TargetResources[0].modifiedProperties[0].newValue))

Stage 5: where

| where excludePlatformsOld != excludePlatformsNew

Stage 6: extend (3 consecutive steps)

| extend modifiedBy = tostring(InitiatedBy.user.userPrincipalName)
| extend accountName = tostring(split(modifiedBy, "@")[0])
| extend upnSuffix = tostring(split(modifiedBy, "@")[1])

Stage 7: project

| project
    TimeGenerated,
    OperationName,
    policy = TargetResources[0].displayName,
    modifiedBy,
    accountName,
    upnSuffix,
    result = Result,
    excludePlatformsOld,
    excludePlatformsNew

Stage 8: sort

| order by TimeGenerated desc

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
OperationNamein
  • Update conditional access policy corpus 6 (kusto 6)
field:"OperationName" kind:in value:"Update conditional access policy"

Output Fields

These fields are emitted when the rule matches.

FieldSource
OperationNameproject
TimeGeneratedproject
accountNameproject
excludePlatformsNewproject
excludePlatformsOldproject
modifiedByproject
policyproject
resultproject
upnSuffixproject

Conditional Access - A Conditional Access policy was disabled

#
Severity
low
Time window
5m
Source
github.com/Azure/Azure-Sentinel

A Conditional Access policy was disabled in Entra ID.

MITRE ATT&CK Coverage

Telemetry Coverage

PlatformRecord / event type
AzureUpdate conditional access policy

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: 40702da1-ae8a-4e46-ac1f-9327ca6ef588
name: Conditional Access - A Conditional Access policy was disabled
version: 1.0.1
kind: Scheduled
description: A Conditional Access policy was disabled in Entra ID.
severity: Low
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AuditLogs
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
relevantTechniques:
  - T1562.007
query: |+
  // A Conditional Access policy was disabled.
  AuditLogs
  | where OperationName in ("Update conditional access policy")
  | extend stateOld = extractjson("$.state", tostring(TargetResources[0].modifiedProperties[0].oldValue))
  | extend stateNew = extractjson("$.state", tostring(TargetResources[0].modifiedProperties[0].newValue))
  | where stateOld == "enabled" and stateNew == "disabled"
  | extend modifiedBy = tostring(InitiatedBy.user.userPrincipalName)
  | extend accountName = tostring(split(modifiedBy, "@")[0])
  | extend upnSuffix = tostring(split(modifiedBy, "@")[1])
  | project
      TimeGenerated,
      OperationName,
      policy = TargetResources[0].displayName,
      modifiedBy,
      accountName,
      upnSuffix,
      result = Result,
      stateOld,
      stateNew
  | order by TimeGenerated desc
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: accountName
  - identifier: UPNSuffix
    columnName: upnSuffix
suppressionEnabled: false
suppressionDuration: 5h
eventGroupingSettings:
  aggregationKind: AlertPerResult
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT1H
    matchingMethod: AllEntities
    groupByEntities: []
    groupByAlertDetails: []
    groupByCustomDetails: []

Stages and Predicates

Stage 1: source

AuditLogs

Stage 2: where

| where OperationName in ("Update conditional access policy")

Stage 3: extend

| extend stateOld = extractjson("$.state", tostring(TargetResources[0].modifiedProperties[0].oldValue))

Stage 4: extend

| extend stateNew = extractjson("$.state", tostring(TargetResources[0].modifiedProperties[0].newValue))

Stage 5: where

| where stateOld == "enabled" and stateNew == "disabled"

Stage 6: extend (3 consecutive steps)

| extend modifiedBy = tostring(InitiatedBy.user.userPrincipalName)
| extend accountName = tostring(split(modifiedBy, "@")[0])
| extend upnSuffix = tostring(split(modifiedBy, "@")[1])

Stage 7: project

| project
    TimeGenerated,
    OperationName,
    policy = TargetResources[0].displayName,
    modifiedBy,
    accountName,
    upnSuffix,
    result = Result,
    stateOld,
    stateNew

Stage 8: sort

| order by TimeGenerated desc

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
OperationNameproject
TimeGeneratedproject
accountNameproject
modifiedByproject
policyproject
resultproject
stateNewproject
stateOldproject
upnSuffixproject

Critical Finding Overdue on Internet-Facing App

#
Status
available
Severity
high
Time window
1455m
Group by
$left.ApplicationId, $right.WL_ApplicationId, ApplicationId, StraTenantId, WL_AppName, WL_Owner
Source
github.com/Azure/Azure-Sentinel

Detects Critical and High severity findings older than 7 days that remain open on internet-facing applications. Uses the InternetFacingApps watchlist to scope results to externally exposed assets requiring urgent remediation.

MITRE ATT&CK Coverage

TacticTechniques
Impact

Rule Body

id: 88c4b680-db1c-46b9-8ca4-4165c3abf63f
name: Critical Finding Overdue on Internet-Facing App
description: |
  Detects Critical and High severity findings older than 7 days that remain
  open on internet-facing applications. Uses the InternetFacingApps watchlist
  to scope results to externally exposed assets requiring urgent remediation.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: StratoSecurePush
    dataTypes:
      - StratoSecure_Findings_CL
queryFrequency: 1d
queryPeriod: 1455m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Impact
relevantTechniques:
  - T1499
query: |
  let maxAgeDays = 7;
  let InternetFacingList = _GetWatchlist("InternetFacingApps")
      | project WL_ApplicationId = column_ifexists("ApplicationId", ""),
          WL_AppName = column_ifexists("AppName", ""),
          WL_Owner = column_ifexists("Owner", "");
  StratoSecure_Findings_CL
      | where FixStatus =~ "open"
      | where Severity in ("Critical", "High")
      | extend AgeInDays = datetime_diff("day", now(), TimeGenerated)
      | where AgeInDays > maxAgeDays
      | join kind=inner InternetFacingList on $left.ApplicationId == $right.WL_ApplicationId
      | summarize TotalOverdueFindings = count(), OldestAge = max(AgeInDays),
          RuleIds = make_set(RuleId, 20), EndTime = max(TimeGenerated)
          by ApplicationId, WL_AppName, WL_Owner, StraTenantId
      | project TimeGenerated = EndTime, ApplicationId, AppName = WL_AppName, Owner = WL_Owner,
          StraTenantId, TotalOverdueFindings, OldestAge, RuleIds
entityMappings:
  - entityType: CloudApplication
    fieldMappings:
      - identifier: AppId
        columnName: ApplicationId
version: 1.0.0
kind: Scheduled

Stages and Predicates

Parameters

let maxAgeDays = 7;

Let Binding: InternetFacingList used in Stage 6

let InternetFacingList = _GetWatchlist("InternetFacingApps")
    | project WL_ApplicationId = column_ifexists("ApplicationId", ""),
        WL_AppName = column_ifexists("AppName", ""),
        WL_Owner = column_ifexists("Owner", "");

Stage 1: source

StratoSecure_Findings_CL

Stage 2: where

| where FixStatus =~ "open"

Stage 3: where

| where Severity in ("Critical", "High")

Stage 4: extend

| extend AgeInDays = datetime_diff("day", now(), TimeGenerated)

Stage 5: where

| where AgeInDays > maxAgeDays

Stage 6: join

| join kind=inner InternetFacingList on $left.ApplicationId == $right.WL_ApplicationId

Stage 7: summarize

summarize EndTime, OldestAge, RuleIds, TotalOverdueFindings by ApplicationId, WL_AppName, WL_Owner, StraTenantId

Stage 8: project

project AppName, ApplicationId, OldestAge, Owner, RuleIds, StraTenantId, TimeGenerated, TotalOverdueFindings

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AppNameproject
ApplicationIdproject
OldestAgeproject
Ownerproject
RuleIdsproject
StraTenantIdproject
TimeGeneratedproject
TotalOverdueFindingsproject

Cyble Vision Alerts Phishing Domain 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

'Cyble detected a phishing website impersonating a monitored brand. This alert provides landing page, host, screenshot, status and configured keyword for SOC triage.'

MITRE ATT&CK Coverage

Rule Body

id: eb1d45fe-1b19-4b54-b146-971f282a6fd9
name: Cyble Vision Alerts Phishing Domain Detected
description: |
  'Cyble detected a phishing website impersonating a monitored brand. This alert provides landing page, host, screenshot, status and configured keyword for SOC triage.'
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
relevantTechniques:
- T1598.003
query: |
  Alerts_phishing 
  | where Service == "phishing"
  | extend MappedSeverity = Severity
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
  alertDetailsOverride:
  alertDisplayNameFormat: Phishing Detected {{PH_PhishingKeyword}} on {{PH_DomainName}}
  alertDescriptionFormat: |
    A phishing landing page impersonating {{PH_Brand}}.
    Host {{PH_HostName}}
    Live {{PH_IsLive}}
customDetails:
  MappedSeverity: Severity
  Status: Status
  AlertID: AlertID
  Service: Service
  PH_DomainName: PH_DomainName
  PH_Top_Domain: PH_Top_Domain
  PH_PhishingKeyword: PH_PhishingKeyword
  PH_PhishingStatus: PH_PhishingStatus
  PH_HostName: PH_HostName
  PH_Title: PH_Title
  PH_ScreenshotURL: PH_ScreenshotURL
  PH_IsLive: PH_IsLive
  PH_DetectedAt: PH_DetectedAt
  PH_LastLiveOn: PH_LastLiveOn
  PH_AWSObjectName: PH_AWSObjectName
  PH_Score: PH_Score
entityMappings:
- entityType: Url
  fieldMappings:
  - identifier: Url
    columnName: PH_DomainName
- entityType: Host
  fieldMappings:
  - identifier: HostName
    columnName: PH_HostName
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

Alerts_phishing

Stage 2: where

| where Service == "phishing"

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

DNS events related to ToR proxies

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

'Identifies IP addresses performing DNS lookups associated with common ToR proxies.'

MITRE ATT&CK Coverage

Rule Body

id: a83ef0f4-dace-4767-bce3-ebd32599d2a0
name: DNS events related to ToR proxies
description: |
  'Identifies IP addresses performing DNS lookups associated with common ToR proxies.'
severity: Low
status: Available
requiredDataConnectors:
  - connectorId: DNS
    dataTypes:
      - DnsEvents
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Exfiltration
relevantTechniques:
  - T1048
query: |
  DnsEvents
  | where Name contains "."
  | where Name has_any ("tor2web.org", "tor2web.com", "torlink.co", "onion.to", "onion.ink", "onion.cab", "onion.nu", "onion.link",
  "onion.it", "onion.city", "onion.direct", "onion.top", "onion.casa", "onion.plus", "onion.rip", "onion.dog", "tor2web.fi",
  "tor2web.blutmagie.de", "onion.sh", "onion.lu", "onion.pet", "t2w.pw", "tor2web.ae.org", "tor2web.io", "tor2web.xyz", "onion.lt",
  "s1.tor-gateways.de", "s2.tor-gateways.de", "s3.tor-gateways.de", "s4.tor-gateways.de", "s5.tor-gateways.de", "hiddenservice.net")
  | extend HostName = iff(Computer has '.', substring(Computer,0,indexof(Computer,'.')),Computer)
  | extend DnsDomain = iff(Computer has '.', substring(Computer,indexof(Computer,'.')+1),"")
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Computer
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: ClientIP
version: 1.0.3
kind: Scheduled

Stages and Predicates

Stage 1: source

DnsEvents

Stage 2: where

| where Name contains "."

Stage 3: where

| where Name has_any ("tor2web.org", "tor2web.com", "torlink.co", "onion.to", "onion.ink", "onion.cab", "onion.nu", "onion.link",
"onion.it", "onion.city", "onion.direct", "onion.top", "onion.casa", "onion.plus", "onion.rip", "onion.dog", "tor2web.fi",
"tor2web.blutmagie.de", "onion.sh", "onion.lu", "onion.pet", "t2w.pw", "tor2web.ae.org", "tor2web.io", "tor2web.xyz", "onion.lt",
"s1.tor-gateways.de", "s2.tor-gateways.de", "s3.tor-gateways.de", "s4.tor-gateways.de", "s5.tor-gateways.de", "hiddenservice.net")

Stage 4: extend

| extend HostName = iff(Computer has '.', substring(Computer,0,indexof(Computer,'.')),Computer)
HostName =
ifComputer has "."substring(Computer, 0, indexof(Computer, '.'))
elseComputer

Stage 5: extend

| extend DnsDomain = iff(Computer has '.', substring(Computer,indexof(Computer,'.')+1),"")
DnsDomain =
ifComputer has "."substring(Computer, (indexof(Computer, '.') + 1))
else""

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Namecontains
  • .
field:"Name" kind:contains value:"."
Namematch
  • hiddenservice.net transforms: term
  • onion.cab transforms: term
  • onion.casa transforms: term
  • onion.city transforms: term
  • onion.direct transforms: term
  • onion.dog transforms: term
  • onion.ink transforms: term
  • onion.it transforms: term
  • onion.link transforms: term
  • onion.lt transforms: term
  • onion.lu transforms: term
  • onion.nu transforms: term
  • onion.pet transforms: term
  • onion.plus transforms: term
  • onion.rip transforms: term
  • onion.sh transforms: term
  • onion.to transforms: term
  • onion.top transforms: term
  • s1.tor-gateways.de transforms: term
  • s2.tor-gateways.de transforms: term
  • s3.tor-gateways.de transforms: term
  • s4.tor-gateways.de transforms: term
  • s5.tor-gateways.de transforms: term
  • t2w.pw transforms: term
  • tor2web.ae.org transforms: term
  • tor2web.blutmagie.de transforms: term
  • tor2web.com transforms: term
  • tor2web.fi transforms: term
  • tor2web.io transforms: term
  • tor2web.org transforms: term
  • tor2web.xyz transforms: term
  • torlink.co transforms: term
field:"Name" kind:match

Output Fields

These fields are emitted when the rule matches.

FieldSource
HostNameextend
DnsDomainextend

F&O - Non-interactive account mapped to self or sensitive privileged user

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

Identifies changes to Microsoft Entra client apps registered for Finance & Operations, specifically when a new client is mapped to a predefined list of sensitive privileged user accounts, or when a user associates a client app with their own account.

MITRE ATT&CK Coverage

Rule Body

id: 5b7cc7f9-fe54-4138-9fb0-d650807345d3
kind: Scheduled
name: F&O - Non-interactive account mapped to self or sensitive privileged user
description: Identifies changes to Microsoft Entra client apps registered for Finance
  & Operations, specifically when a new client is mapped to a predefined list of sensitive
  privileged user accounts, or when a user associates a client app with their own
  account.
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: Dynamics365Finance
    dataTypes:
      - FinanceOperationsActivity_CL
queryFrequency: 15m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CredentialAccess
  - Persistence
  - PrivilegeEscalation
relevantTechniques:
  - T1556
  - T1098
  - T1136
  - T1078
  - T0859
query: |
  // Add sensitive privilege accounts to the privileged_user_accounts variable.
  // Example: let privileged_user_accounts = dynamic(["Admin1", "Admin"]);
  let privileged_user_accounts = dynamic([]);
  FinanceOperationsActivity_CL
  | where TableName == "SysAADClientTable" and LogType in ("Insert", "Update")
  | extend ClientId = tostring(parse_json(tostring(FormattedData.["03::AADClientId"])).NewData)
  | extend User = parse_json(tostring(FormattedData.UserId))
  | extend
      MappedUser = tostring(User.NewData),
      PreviousUserId = tostring(User.OldData),
      TargetAppName = tostring(parse_json(tostring(FormattedData.Name)).NewData),
      FinOpsAppId = 32780
  | where MappedUser in (privileged_user_accounts) or LogCreatedBy == MappedUser
  | project
      LogCreatedDateTime,
      LogCreatedBy,
      LogType,
      TargetAppName,
      MappedUser,
      PreviousUserId,
      ClientId,
      FinOpsAppId
eventGroupingSettings:
  aggregationKind: AlertPerResult
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: LogCreatedBy
  - entityType: Account
    fieldMappings:
      - identifier: AadUserId
        columnName: ClientId
  - entityType: CloudApplication
    fieldMappings:
      - identifier: AppId
        columnName: FinOpsAppId
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: MappedUser
alertDetailsOverride:
  alertDisplayNameFormat: F&O - Sensitive non-interactive user mapping detected
  alertDescriptionFormat: User account {{LogCreatedBy}} mapped an Azure AD App to
    senstitive privileged user account {{MappedUser}}. The associated Azure AD client
    ID is {{ClientId}}
version: 3.2.0

Stages and Predicates

Parameters

let privileged_user_accounts = dynamic([]);

Stage 1: source

FinanceOperationsActivity_CL

Stage 2: where

| where TableName == "SysAADClientTable" and LogType in ("Insert", "Update")

Stage 3: extend (3 consecutive steps)

| extend ClientId = tostring(parse_json(tostring(FormattedData.["03::AADClientId"])).NewData)
| extend User = parse_json(tostring(FormattedData.UserId))
| extend
    MappedUser = tostring(User.NewData),
    PreviousUserId = tostring(User.OldData),
    TargetAppName = tostring(parse_json(tostring(FormattedData.Name)).NewData),
    FinOpsAppId = 32780

Stage 4: where

| where MappedUser in (privileged_user_accounts) or LogCreatedBy == MappedUser

Stage 5: project

| project
    LogCreatedDateTime,
    LogCreatedBy,
    LogType,
    TargetAppName,
    MappedUser,
    PreviousUserId,
    ClientId,
    FinOpsAppId

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
ClientIdproject
FinOpsAppIdproject
LogCreatedByproject
LogCreatedDateTimeproject
LogTypeproject
MappedUserproject
PreviousUserIdproject
TargetAppNameproject

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

The policy detects admin users in AWS or Azure.

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

id: dc728ba1-5204-4fde-ab48-eda19c8fad3a
name: IaaS admin detected
kind: Scheduled
description: The policy detects admin users in AWS or Azure.
severity: Medium
status: Available
queryFrequency: 30m
queryPeriod: 30m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - 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 "IaaS admin detected"
  | 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 - IaaS admin detected
  alertDescriptionFormat: |
    IaaS admin detected. The policy detects admin users in AWS or Azure
  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 "IaaS admin detected"

Stage 5: project

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

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Policymatch
  • IaaS admin detected transforms: term
field:"policy_name_s" kind:match value:"IaaS admin detected"

Output Fields

These fields are emitted when the rule matches.

FieldSource
Categoryproject
Descriptionproject
EventIDproject
Policyproject
Recommendationproject
Severityproject
Tacticsproject
URLproject

Mimecast Secure Email Gateway - URL Protect

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

'Detect threat when potentially malicious url found.'

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

id: 80f244cd-b0d6-404e-9aed-37f7a66eda9f
name: Mimecast Secure Email Gateway - URL Protect
description: |
  'Detect threat when potentially malicious url found.'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: MimecastSEGAPI
    dataTypes:
      - MimecastCG
enabled: true
queryFrequency: 15m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- Discovery
- Execution
relevantTechniques:
- T1566
query: |
  MimecastCG
  | where Type == "email_ttp_url"
  | extend  SenderEnvelope = ['Sender Envelope']
suppressionDuration: 5h
suppressionEnabled: false
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: P7D
    matchingMethod: AllEntities
eventGroupingSettings:
  aggregationKind: AlertPerResult
entityMappings:
- entityType: MailMessage
  fieldMappings:
  - identifier: Sender
    columnName: SenderEnvelope
  - identifier: Recipient
    columnName: Recipients
  - identifier: Subject
    columnName: Subject
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

MimecastCG

Stage 2: where

| where Type == "email_ttp_url"

Stage 3: extend

| extend  SenderEnvelope = ['Sender Envelope']

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Typeeq
  • email_ttp_url
field:"Type" kind:eq value:"email_ttp_url"

Output Fields

These fields are emitted when the rule matches.

FieldSource
SenderEnvelopeextend

Mimecast Secure Email Gateway - URL Protect

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

Detect threat when potentially malicious url found

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

id: ea19dae6-bbb3-4444-a1b8-8e9ae6064aab
name: Mimecast Secure Email Gateway - URL Protect
description: Detect threat when potentially malicious url found
severity: High
requiredDataConnectors:
  - connectorId: MimecastSIEMAPI
    dataTypes:
      - MimecastSIEM_CL
enabled: true
query: MimecastSIEM_CL| where mimecastEventId_s=="mail_ttp_url" and reason_s != "clean"
queryFrequency: 5m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
suppressionDuration: 5h
suppressionEnabled: false
tactics:
- InitialAccess
- Discovery
- Execution
relevantTechniques:
- T1566
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: 1d
    matchingMethod: AllEntities
eventGroupingSettings:
  aggregationKind: SingleAlert
customDetails:
  senderDomain: senderDomain_s
  credentialTheft: credentialTheft_s
  urlCategory: urlCategory_s
  action: action_s
  url: url_s
  MsgId_s: msgid_s
  route: route_s
  SourceIP: SourceIP
  reason: reason_s
entityMappings:
- entityType: MailMessage
  fieldMappings:
  - identifier: Sender
    columnName: sender_s
  - identifier: Recipient
    columnName: recipient_s
  - identifier: Subject
    columnName: subject_s
version: 1.0.1
kind: Scheduled

Stages and Predicates

Stage 1: source

MimecastSIEM_CL

Stage 2: where

| where mimecastEventId_s=="mail_ttp_url" and reason_s != "clean"

Indicators

These rows show field, operator, and value matches.

Rubrik Critical Anomaly

#

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

'Rubrik Critical Anomaly rule matches Severity and if Critical severity found then generate the incident for each object.'

MITRE ATT&CK Coverage

TacticTechniques
Persistence

Rule Body

id: 54c70d21-696f-4f03-9238-9d7118d079fe
name: Rubrik Critical Anomaly
version: 1.0.0
kind: Scheduled
description: |
  'Rubrik Critical Anomaly rule matches Severity and if Critical severity found then generate the incident for each object.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: RubrikSecurityCloudAzureFunctions
    dataTypes: 
      - RubrikAnomalyData
queryFrequency: 10m
queryPeriod: 10m
triggerOperator: gt
triggerThreshold: 0
tactics: 
  - Persistence
relevantTechniques:
  - T1546
query: |
       Rubrik_Anomaly_Data_CL
       | where severity_s == "critical"
eventGroupingSettings:
  aggregationKind: AlertPerResult
customDetails:
  ClusterIdentifier: custom_details_clusterId_g
  ObjectId: custom_details_objectId_g
  ObjectName: custom_details_objectName_s
  ObjectType: custom_details_objectType_s
  ClusterName: custom_details_clusterName_s
incidentConfiguration:
  createIncident: true

Stages and Predicates

Stage 1: source

Rubrik_Anomaly_Data_CL

Stage 2: where

| where severity_s == "critical"

Indicators

These rows show field, operator, and value matches.

Service Provider Deleted

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

Detects when a service provider is deleted from Veeam Backup & Replication. This might indicate unauthorized removal of critical components.

Rule Body

id: cbe9fcb2-8767-4965-887e-350710145386
name: Service Provider Deleted
description: Detects when a service provider is deleted from Veeam Backup & Replication.
  This might indicate unauthorized removal of critical components.
severity: Informational
status: Available
requiredDataConnectors:
- connectorId: Syslog
  dataTypes:
  - Syslog
- connectorId: SyslogAma
  dataTypes:
  - Syslog
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: "Veeam_GetSecurityEvents\n| where instanceId == 27600\n| project\n    Date\
  \ = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),\n    DataSource = original_host,\n\
  \    EventId = instanceId,\n    [\"User Name\"] = 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 == 27600

Stage 3: project

| project
    Date = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),
    DataSource = original_host,
    EventId = instanceId,
    ["User Name"] = 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
User Nameproject

StealthTalk - Multi new devices registration

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

Identifies a single StealthTalk user registering two or more previously-unseen devices within a 24-hour window. Sudden registration of multiple new devices is a strong indicator of account takeover (an attacker enrolling their own device after credential theft) or device-farm abuse. The rule fires when a user produces two or more distinct NewDeviceId values within the lookback window, regardless of operating system. Look at the OSList custom detail to spot cross-platform patterns (e.g. an iOS-only user suddenly enrolling an Android device).

MITRE ATT&CK Coverage

Rule Body

id: f9d4c2a8-1b6e-4a3f-9c7d-8e2b1a3c5d7e
name: StealthTalk - Multi new devices registration
description: |
  Identifies a single StealthTalk user registering two or more previously-unseen devices within
  a 24-hour window. Sudden registration of multiple new devices is a strong indicator of
  account takeover (an attacker enrolling their own device after credential theft) or
  device-farm abuse.

  The rule fires when a user produces two or more distinct NewDeviceId values within the
  lookback window, regardless of operating system. Look at the OSList custom detail to spot
  cross-platform patterns (e.g. an iOS-only user suddenly enrolling an Android device).
severity: Medium
requiredDataConnectors:
  - connectorId: StealthTalkAnomalousAuth
    dataTypes:
      - StealthTalkAnomalousAuth_CL
queryFrequency: 30m
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - Persistence
  - InitialAccess
  - DefenseEvasion
relevantTechniques:
  - T1078
  - T1098
query: |
  let LookbackPeriod = 24h;
  let MinNewDevices  = 2;
  StealthTalkAnomalousAuth_CL
  | where TimeGenerated >= ago(LookbackPeriod)
  | where EventType == "NewDeviceLogin"
  | summarize
      NewDeviceCount  = dcount(NewDeviceId),
      NewDevices      = make_set(NewDeviceId),
      NewDeviceOSList = make_set(NewDeviceOS),
      FirstSeen       = min(TimeGenerated),
      LastSeen        = max(TimeGenerated),
      AppVersions     = make_set(AppVersion)
    by UserId
  | where NewDeviceCount >= MinNewDevices
  | extend
      AlertName    = "MultiNewDevicesRegistration",
      AlertDetails = strcat(
          "User ", UserId,
          " registered ", NewDeviceCount, " new devices within 24 hours.",
          " Device IDs: ", tostring(NewDevices), ".",
          " Operating systems: ", tostring(NewDeviceOSList), "."
      )
  | project
      TimeGenerated = LastSeen,
      UserId, NewDeviceCount, NewDevices, NewDeviceOSList,
      FirstSeen, LastSeen, AppVersions, AlertName, AlertDetails
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: UserId
customDetails:
  NewDeviceCount: NewDeviceCount
  NewDevices: NewDevices
  NewDeviceOSList: NewDeviceOSList
  FirstSeen: FirstSeen
  LastSeen: LastSeen
alertDetailsOverride:
  alertDisplayNameFormat: 'StealthTalk: Multi New Devices - {{UserId}} ({{NewDeviceCount}} new devices)'
  alertDescriptionFormat: '{{AlertDetails}}'
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: 5h
    matchingMethod: Selected
    groupByEntities:
      - Account
suppressionEnabled: false
suppressionDuration: 5h
version: 1.0.0
kind: Scheduled

Stages and Predicates

Parameters

let LookbackPeriod = 24h;
let MinNewDevices = 2;

Stage 1: source

StealthTalkAnomalousAuth_CL

Stage 2: where

| where TimeGenerated >= ago(LookbackPeriod)

Stage 3: where

| where EventType == "NewDeviceLogin"

Stage 4: summarize

| summarize
    NewDeviceCount  = dcount(NewDeviceId),
    NewDevices      = make_set(NewDeviceId),
    NewDeviceOSList = make_set(NewDeviceOS),
    FirstSeen       = min(TimeGenerated),
    LastSeen        = max(TimeGenerated),
    AppVersions     = make_set(AppVersion)
  by UserId

Stage 5: where

| where NewDeviceCount >= MinNewDevices

Stage 6: extend

| extend
    AlertName    = "MultiNewDevicesRegistration",
    AlertDetails = strcat(
        "User ", UserId,
        " registered ", NewDeviceCount, " new devices within 24 hours.",
        " Device IDs: ", tostring(NewDevices), ".",
        " Operating systems: ", tostring(NewDeviceOSList), "."
    )

Stage 7: project

| project
    TimeGenerated = LastSeen,
    UserId, NewDeviceCount, NewDevices, NewDeviceOSList,
    FirstSeen, LastSeen, AppVersions, AlertName, AlertDetails

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AlertDetailsproject
AlertNameproject
AppVersionsproject
FirstSeenproject
LastSeenproject
NewDeviceCountproject
NewDeviceOSListproject
NewDevicesproject
TimeGeneratedproject
UserIdproject

SureBackup Job Failed

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

Detects failed SureBackup job operations. This might indicate malware issues, storage problems, or potential sabotage of backup infrastructure.

Rule Body

id: b7409bbb-6f0c-43c4-bb63-b20add5eb717
name: SureBackup Job Failed
description: Detects failed SureBackup job operations. This might indicate malware
  issues, storage problems, or potential sabotage of backup infrastructure.
severity: High
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_GetJobFinished\n| where instanceId == 390\n| project\n    Date = format_datetime(TimeGenerated,\
  \ 'dd.MM.yyyy HH:mm'),\n    DataSource = original_host,\n    EventId = instanceId,\n\
  \    [\"StateMessage\"] = JobTypeDescription,\n    [\"State\"] = JobResultMessage,\n\
  \    Severity = Severity,\n    MessageDetails = Description"
version: 1.0.1
kind: Scheduled
customDetails:
  Date: Date
  VbrHostName: DataSource
  EventId: EventId
  MessageDetails: MessageDetails
  Severity: Severity

Stages and Predicates

Stage 1: source

Veeam_GetJobFinished

Stage 2: where

| where instanceId == 390

Stage 3: project

| project
    Date = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),
    DataSource = original_host,
    EventId = instanceId,
    ["StateMessage"] = JobTypeDescription,
    ["State"] = JobResultMessage,
    Severity = Severity,
    MessageDetails = Description

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
Stateproject
StateMessageproject

Tenable.ad Indicators of Attack

#
Severity
low
Time window
2h
Group by
Severity
Source
github.com/Azure/Azure-Sentinel

'Searches for triggered Indicators of Attack.'

MITRE ATT&CK Coverage

TacticTechniques
Credential Access

Rule Body

id: 6405329a-8d20-48f3-aabc-e1b8a745568e
name: Tenable.ad Indicators of Attack
description: |
    'Searches for triggered Indicators of Attack.'
severity: Low
requiredDataConnectors:
  - connectorId: Tenable.ad
    dataTypes:
      - Tenable_ad_CL
queryFrequency: 2h
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CredentialAccess
relevantTechniques:
  - T1110
query: |
  // For the query to work properly, make sure you have imported the afad_parser.kql parser into the workspace
  // Retrieve the parser here: https://raw.githubusercontent.com/tenable/Azure-Sentinel/Tenable.ad-connector/Solutions/TenableAD/Parsers/afad_parser.kql
  // Then, create the Kusto Function with alias afad_parser
  let SeverityTable=datatable(Severity:string,Level:int) [
    "low", 1,
    "medium", 2,
    "high", 3,
    "critical", 4
    ];
    afad_parser
    | where MessageType == 2
    | lookup kind=leftouter SeverityTable on Severity
    | order by Level
    | extend HostName = tostring(split(Host, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Host, '.'), 1, -1), '.'))
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
version: 1.0.1
kind: Scheduled

Stages and Predicates

Let Binding: SeverityTable used in Stage 3

let SeverityTable = datatable(Severity:string,Level:int) [
  "low", 1,
  "medium", 2,
  "high", 3,
  "critical", 4
  ];

Stage 1: source

afad_parser

Stage 2: where

| where MessageType == 2

Stage 3: kusto:lookup

lookup kind=leftouter (SeverityTable) on Severity

Stage 4: sort

sort by Level

Stage 5: extend

extend DnsDomain, HostName

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
MessageTypeeq
  • 2 corpus 21 (kusto 21)
field:"MessageType" kind:eq value:"2"

Output Fields

These fields are emitted when the rule matches.

FieldSource
DnsDomainextend
HostNameextend

Threat Essentials - User Assigned Privileged Role

#
Status
available
Severity
high
Time window
1h
Group by
Initiator, OperationName, Result, RoleName, Target
Source
github.com/Azure/Azure-Sentinel

Identifies when a new privileged role is assigned to a user. Any account eligible for a role is now being given privileged access. If the assignment is unexpected or into a role that isn't the responsibility of the account holder, investigate. Ref : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-privileged-accounts#things-to-monitor-1

MITRE ATT&CK Coverage

TacticTechniques
Persistence

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: b09795c9-8dce-47ab-8f75-5a4afb78ef0c
name: Threat Essentials - User Assigned Privileged Role
description: |
  'Identifies when a new privileged role is assigned to a user.  Any account eligible for a role is now being given privileged access. If the assignment is unexpected or into a role that isn't the responsibility of the account holder, investigate.
  Ref : https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-privileged-accounts#things-to-monitor-1'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AuditLogs
queryFrequency: 2h
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Persistence
relevantTechniques:
  - T1078.004
tags:
  - AADSecOpsGuide
query: |
  AuditLogs
  | where Category =~ "RoleManagement"
  | where AADOperationType in~ ("Assign", "AssignEligibleRole")
  | where ActivityDisplayName has_any ("Add eligible member to role", "Add member to role")
  | mv-expand TargetResources
  | mv-expand TargetResources.modifiedProperties
  | extend displayName_ = tostring(TargetResources_modifiedProperties.displayName)
  | where displayName_ =~ "Role.DisplayName"
  | extend RoleName = tostring(parse_json(tostring(TargetResources_modifiedProperties.newValue)))
  | where RoleName contains "Admin"
  | extend InitiatingApp = tostring(parse_json(tostring(InitiatedBy.app)).displayName)
  | extend Initiator = iif(isnotempty(InitiatingApp), InitiatingApp, tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName))
  | extend Target = tostring(TargetResources.userPrincipalName)
  | summarize by bin(TimeGenerated, 1h), OperationName,  RoleName, Target, Initiator, Result
  | extend InitiatorName=split(Initiator, "@")[0], InitiatorUPNSuffix=split(Initiator, "@")[1]
  | extend TargetName=split(Target, "@")[0], TargetUPNSuffix=split(Target, "@")[1]
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: InitiatorName
      - identifier: UPNSuffix
        columnName: InitiatorUPNSuffix
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: TargetName
      - identifier: UPNSuffix
        columnName: TargetUPNSuffix
version: 1.0.3
kind: Scheduled

Stages and Predicates

Stage 1: source

AuditLogs

Stage 2: where

| where Category =~ "RoleManagement"

Stage 3: where

| where AADOperationType in~ ("Assign", "AssignEligibleRole")

Stage 4: where

| where ActivityDisplayName has_any ("Add eligible member to role", "Add member to role")

Stage 5: mv-expand

| mv-expand TargetResources

Stage 6: mv-expand

| mv-expand TargetResources.modifiedProperties

Stage 7: extend

| extend displayName_ = tostring(TargetResources_modifiedProperties.displayName)

Stage 8: where

| where displayName_ =~ "Role.DisplayName"

Stage 9: extend

| extend RoleName = tostring(parse_json(tostring(TargetResources_modifiedProperties.newValue)))

Stage 10: where

| where RoleName contains "Admin"

Stage 11: extend (3 consecutive steps)

| extend InitiatingApp = tostring(parse_json(tostring(InitiatedBy.app)).displayName)
| extend Initiator = iif(isnotempty(InitiatingApp), InitiatingApp, tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName))
| extend Target = tostring(TargetResources.userPrincipalName)

Stage 12: summarize

| summarize by bin(TimeGenerated, 1h), OperationName,  RoleName, Target, Initiator, Result

Stage 13: extend

| extend InitiatorName=split(Initiator, "@")[0], InitiatorUPNSuffix=split(Initiator, "@")[1]

Stage 14: extend

| extend TargetName=split(Target, "@")[0], TargetUPNSuffix=split(Target, "@")[1]

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
AADOperationTypein
  • Assign corpus 2 (kusto 2)
  • AssignEligibleRole corpus 2 (kusto 2)
field:"AADOperationType" kind:in
ActivityDisplayNamematch
  • Add eligible member to role transforms: term corpus 9 (kusto 9)
  • Add member to role transforms: term corpus 9 (kusto 9)
field:"azure_ad::activity_display_name" kind:match
Categoryeq
  • RoleManagement corpus 17 (kusto 16, sigma 1)
field:"Category" kind:eq value:"RoleManagement"
RoleNamecontains
  • Admin
field:"RoleName" kind:contains value:"Admin"
displayName_eq
  • Role.DisplayName
field:"displayName_" kind:eq value:"Role.DisplayName"

Output Fields

These fields are emitted when the rule matches.

FieldSource
Initiatorsummarize
OperationNamesummarize
Resultsummarize
RoleNamesummarize
Targetsummarize
InitiatorNameextend
InitiatorUPNSuffixextend
TargetNameextend
TargetUPNSuffixextend

TI map Email entity to EmailEvents

#
Severity
medium
Time window
14d
Group by
$left.TI_EmailAddress, $right.RecipientEmailAddress, $right.SenderFromAddress, IndicatorId, TI_EmailAddress
Source
github.com/Azure/Azure-Sentinel

Identifies a match in EmailEvents table from any Email IOC from TI

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Telemetry Coverage

Rule Body

id: 11f7c6e3-f066-4b3c-9a81-b487ec0a6873
name: TI map Email entity to EmailEvents
description: |
  'Identifies a match in EmailEvents table from any Email IOC from TI'
severity: Medium
requiredDataConnectors:
  - connectorId: Office365
    dataTypes:
      - EmailEvents
  - connectorId: ThreatIntelligence
    dataTypes:
      - ThreatIntelligenceIndicator
  - connectorId: ThreatIntelligenceTaxii
    dataTypes:
      - ThreatIntelligenceIndicator
  - connectorId: MicrosoftDefenderThreatIntelligence
    dataTypes:
      - ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1566
query: |
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  let EmailEvents_ = materialize(EmailEvents | where isnotempty(RecipientEmailAddress) and isnotempty(SenderFromAddress) and TimeGenerated >= ago(dt_lookBack) and DeliveryAction !has "Blocked" | project-rename  EmailEvents_TimeGenerated = TimeGenerated | extend SenderFromAddress = tolower(SenderFromAddress) | extend RecipientEmailAddress = tolower(RecipientEmailAddress));
  let SenderAddresses = EmailEvents_ | distinct  SenderFromAddress | summarize make_list(SenderFromAddress);
  let RecipientAddresses = EmailEvents_ | distinct  RecipientEmailAddress | summarize make_list(RecipientEmailAddress);
  let TI = materialize(ThreatIntelligenceIndicator
  | where TimeGenerated >= ago(ioc_lookBack)
  | where isnotempty(EmailSenderAddress)
  | extend TI_EmailAddress = tolower(EmailSenderAddress)
  | where TI_EmailAddress in (SenderAddresses) or TI_EmailAddress in (RecipientAddresses)
  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
  | where Active == true and ExpirationDateTime > now());
  (union
    (TI | join kind=innerunique (EmailEvents_) on $left.TI_EmailAddress == $right.SenderFromAddress),
    (TI | join kind=innerunique (EmailEvents_) on $left.TI_EmailAddress == $right.RecipientEmailAddress))
  | where EmailEvents_TimeGenerated < ExpirationDateTime
  | summarize EmailEvents_TimeGenerated = arg_max(EmailEvents_TimeGenerated, *) by IndicatorId, TI_EmailAddress
  | project EmailEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, RecipientEmailAddress, SenderFromAddress, Subject, ConfidenceLevel, Url, Type, TI_EmailAddress, TrafficLightProtocolLevel, DeliveryAction, DeliveryLocation, EmailDirection
  | extend Name = tostring(split(RecipientEmailAddress, '@', 0)[0]), UPNSuffix = tostring(split(RecipientEmailAddress, '@', 1)[0])
  | extend timestamp = EmailEvents_TimeGenerated
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: RecipientEmailAddress
      - identifier: Name
        columnName: Name
      - identifier: UPNSuffix
        columnName: UPNSuffix
version: 1.0.2
kind: Scheduled

Stages and Predicates

Parameters

let dt_lookBack = 1h;
let ioc_lookBack = 14d;

Let Binding: EmailEvents_

let EmailEvents_ = materialize(EmailEvents | where isnotempty(RecipientEmailAddress) and isnotempty(SenderFromAddress) and TimeGenerated >= ago(dt_lookBack) and DeliveryAction !has "Blocked" | project-rename  EmailEvents_TimeGenerated = TimeGenerated | extend SenderFromAddress = tolower(SenderFromAddress) | extend RecipientEmailAddress = tolower(RecipientEmailAddress));

Let Binding: SenderAddresses

let SenderAddresses = EmailEvents_ | distinct  SenderFromAddress | summarize make_list(SenderFromAddress);

Let Binding: RecipientAddresses

let RecipientAddresses = EmailEvents_ | distinct  RecipientEmailAddress | summarize make_list(RecipientEmailAddress);

Union (2 Sources)

Each leg below queries one source; the rule matches if any leg does. Sources: TI, TI

Leg 1: TI

TI | join kind=innerunique (EmailEvents_) on $left.TI_EmailAddress == $right.SenderFromAddress

Leg 2: TI

TI | join kind=innerunique (EmailEvents_) on $left.TI_EmailAddress == $right.RecipientEmailAddress

Applied to the Combined Result

| where EmailEvents_TimeGenerated < ExpirationDateTime
| summarize EmailEvents_TimeGenerated = arg_max(EmailEvents_TimeGenerated, *) by IndicatorId, TI_EmailAddress
| project EmailEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, RecipientEmailAddress, SenderFromAddress, Subject, ConfidenceLevel, Url, Type, TI_EmailAddress, TrafficLightProtocolLevel, DeliveryAction, DeliveryLocation, EmailDirection
| extend Name = tostring(split(RecipientEmailAddress, '@', 0)[0]), UPNSuffix = tostring(split(RecipientEmailAddress, '@', 1)[0])
| extend timestamp = EmailEvents_TimeGenerated

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
DeliveryActionmatchBlockedexcludes:DeliveryAction field:"DeliveryAction" value:"Blocked"

Output Fields

These fields are emitted when the rule matches.

FieldSource
ActivityGroupNamesproject
ConfidenceLevelproject
ConfidenceScoreproject
DeliveryActionproject
DeliveryLocationproject
Descriptionproject
DomainNameproject
EmailDirectionproject
EmailEvents_TimeGeneratedproject
ExpirationDateTimeproject
IndicatorIdproject
RecipientEmailAddressproject
SenderFromAddressproject
Subjectproject
TI_EmailAddressproject
ThreatTypeproject
TrafficLightProtocolLevelproject
Typeproject
Urlproject
Nameextend
UPNSuffixextend
timestampextend

Veeam ONE Computer with No Backup

#

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

Detects computers with no backup.

Rule Body

id: c0ead324-d8e8-484d-b590-9639f5ac5d93
name: Veeam ONE Computer with No Backup
description: Detects computers with no backup.
severity: High
status: Available
requiredDataConnectors:
- connectorId: VeeamCustomTablesDataConnector
  dataTypes:
  - VeeamOneTriggeredAlarms_CL
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: VeeamOneTriggeredAlarms_CL | where PredefinedAlarmId == 370
version: 1.0.1
kind: Scheduled
customDetails:
  PredefinedAlarmId: PredefinedAlarmId
  TriggeredAlarmId: TriggeredAlarmId
  Description: Description
  Name: Name
  VoneHostName: VoneHostName
  TriggeredTime: TriggeredTime
  Status: Status
  Comment: Comment
  ObjectId: ObjectId
  ObjectName: ObjectName
  ObjectType: ObjectType

Stages and Predicates

Stage 1: source

VeeamOneTriggeredAlarms_CL

Stage 2: where

| where PredefinedAlarmId == 370

Indicators

These rows show field, operator, and value matches.

Veeam ONE Immutability Change Tracking

#

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

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

Detects changes in Veeam ONE immutability tracking configuration.

Rule Body

id: 21ef1e12-75ac-43be-a77e-d2cee4c69225
name: Veeam ONE Immutability Change Tracking
description: Detects changes in Veeam ONE immutability tracking configuration.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: VeeamCustomTablesDataConnector
  dataTypes:
  - VeeamOneTriggeredAlarms_CL
queryFrequency: 3h
queryPeriod: 3h
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: VeeamOneTriggeredAlarms_CL | where PredefinedAlarmId == 377
version: 1.0.1
kind: Scheduled
customDetails:
  PredefinedAlarmId: PredefinedAlarmId
  TriggeredAlarmId: TriggeredAlarmId
  Description: Description
  Name: Name
  VoneHostName: VoneHostName
  TriggeredTime: TriggeredTime
  Status: Status
  Comment: Comment
  ObjectId: ObjectId
  ObjectName: ObjectName
  ObjectType: ObjectType

Stages and Predicates

Stage 1: source

VeeamOneTriggeredAlarms_CL

Stage 2: where

| where PredefinedAlarmId == 377

Indicators

These rows show field, operator, and value matches.

Veeam ONE VM with No Backup (Hyper-V)

#

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

Detects Veeam ONE VMs with no backup (Hyper-V).

Rule Body

id: ae880194-5766-46d3-a17b-c8c53e9ca96c
name: Veeam ONE VM with No Backup (Hyper-V)
description: Detects Veeam ONE VMs with no backup (Hyper-V).
severity: High
status: Available
requiredDataConnectors:
- connectorId: VeeamCustomTablesDataConnector
  dataTypes:
  - VeeamOneTriggeredAlarms_CL
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: VeeamOneTriggeredAlarms_CL | where PredefinedAlarmId == 315
version: 1.0.1
kind: Scheduled
customDetails:
  PredefinedAlarmId: PredefinedAlarmId
  TriggeredAlarmId: TriggeredAlarmId
  Description: Description
  Name: Name
  VoneHostName: VoneHostName
  TriggeredTime: TriggeredTime
  Status: Status
  Comment: Comment
  ObjectId: ObjectId
  ObjectName: ObjectName
  ObjectType: ObjectType

Stages and Predicates

Stage 1: source

VeeamOneTriggeredAlarms_CL

Stage 2: where

| where PredefinedAlarmId == 315

Indicators

These rows show field, operator, and value matches.

VMware Cloud Web Security - Web Access Policy Violation

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

VMware Cloud Web Security reported access events which were violating web access policy rules. Additional investigation might be required.

Rule Body

id: b84a1f62-ad30-4ae1-8b21-3d304d8aa818
name: VMware Cloud Web Security - Web Access Policy Violation
version: 1.0.0
kind: Scheduled
description: VMware Cloud Web Security reported access events which were violating web access policy rules. Additional investigation might be required.
severity: Medium
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
requiredDataConnectors:
  - connectorId: VMwareSDWAN
    dataTypes:
      - CWS
query: |
  VMware_CWS_Weblogs_CL
  | where action == "block"
suppressionEnabled: false
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: 5h
    matchingMethod: AllEntities
    groupByEntities: []
    groupByAlertDetails: []
    groupByCustomDetails: []
eventGroupingSettings:
  aggregationKind: AlertPerResult
entityMappings:
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: sourceIp
- entityType: Malware
  fieldMappings:
  - identifier: Name
    columnName: virusList
- entityType: URL
  fieldMappings:
  - identifier: Url
    columnName: url
- entityType: Account
  fieldMappings:
  - identifier: AadUserId
    columnName: userId
suppressionDuration: 5h

Stages and Predicates

Stage 1: source

VMware_CWS_Weblogs_CL

Stage 2: where

| where action == "block"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actioneq
  • block
field:"action" kind:eq value:"block"

Back to all Kusto rules