Detection rules › Kusto

Kusto rules: 2u

Apache - Request from private IP

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

'Detects requests from private IP'

MITRE ATT&CK Coverage

Rule Body

id: a0077556-3aff-11ec-8d3d-0242ac130003
name: Apache - Request from private IP
description: |
  'Detects requests from private IP'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: CustomLogsAma
    datatypes:
      - ApacheHTTPServer_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Impact
  - InitialAccess
relevantTechniques:
  - T1498
  - T1190
  - T1133
query: |
  ApacheHTTPServer
  | where ipv4_is_private(SrcIpAddr)
  | extend IPCustomEntity = SrcIpAddr
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPCustomEntity
version: 1.0.2
kind: Scheduled

Stages and Predicates

Stage 1: source

ApacheHTTPServer

Stage 2: where

| where ipv4_is_private(SrcIpAddr)

Stage 3: extend

| extend IPCustomEntity = SrcIpAddr

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
SrcIpAddrcidr_match
  • 10.0.0.0/8
  • 127.0.0.0/8
  • 169.254.0.0/16
  • 172.16.0.0/12
  • 192.168.0.0/16
field:"src_ip" kind:cidr_match

Output Fields

These fields are emitted when the rule matches.

FieldSource
IPCustomEntityextend

ApexOne - Suspicious connections

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

'Detects suspicious connections.'

MITRE ATT&CK Coverage

TacticTechniques
Command & Control

Rule Body

id: 9e3dc038-67b7-11ec-90d6-0242ac120003
name: ApexOne - Suspicious connections
description: |
  'Detects suspicious connections.'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: CefAma
    dataTypes:
      - CommonSecurityLog
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CommandAndControl
relevantTechniques:
  - T1102
query: |
  TMApexOneEvent
  | where EventMessage has "Suspicious Connection"
  | where NetworkDirection == 1 
  | where DvcAction in ('1', '3')
  | extend IPCustomEntity = SrcIpAddr, AccountCustomEntity = DstUserName
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPCustomEntity
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountCustomEntity
version: 1.0.3
kind: Scheduled

Stages and Predicates

Stage 1: source

TMApexOneEvent

Stage 2: where

| where EventMessage has "Suspicious Connection"

Stage 3: where

| where NetworkDirection == 1

Stage 4: where

| where DvcAction in ('1', '3')

Stage 5: extend

| extend IPCustomEntity = SrcIpAddr, AccountCustomEntity = DstUserName

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AccountCustomEntityextend
IPCustomEntityextend

AWS Security Hub - Detect SQS Queue lacking encryption at rest

#
Status
available
Severity
medium
Time window
1h
Group by
AwsAccountId, AwsRegion, AwsSecurityFindingDescription, AwsSecurityFindingId, AwsSecurityFindingTitle, ComplianceSecurityControlId, QueueArn
Source
github.com/Azure/Azure-Sentinel

This query detects Amazon SQS queues without server-side encryption at rest enabled, using AWS Security Hub control SQS.1 findings. Lack of encryption for SQS queues can expose sensitive message contents if underlying storage or backups are accessed by unauthorized parties.

MITRE ATT&CK Coverage

Rule Body

id: 7b8c5e2d-6f1c-4a1f-9e2a-3c5f7a8b9c10
name: AWS Security Hub - Detect SQS Queue lacking encryption at rest
description: |
  This query detects Amazon SQS queues without server-side encryption at rest enabled, using AWS Security Hub control SQS.1 findings.
  Lack of encryption for SQS queues can expose sensitive message contents if underlying storage or backups are accessed by unauthorized parties.
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: AWSSecurityHub
    dataTypes:
      - AWSSecurityHubFindings
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Impact
relevantTechniques:
  - T1565.001
tags:
  - AWS Foundational Security Best Practices v1.0.0
  - NIST 800-53 r5
query: |
  AWSSecurityHubFindings
  | where RecordState == "ACTIVE" and ComplianceStatus == "FAILED"
  | where tostring(AwsSecurityFindingGeneratorId) == "security-control/SQS.1"
        or tostring(ComplianceSecurityControlId) == "SQS.1"
  | mv-expand Resource = Resources
  | where tostring(Resource.Type) == "AwsSqsQueue"
  | extend QueueArn = tostring(Resource.Id)
  | summarize TimeGenerated = max(TimeGenerated)
      by AwsAccountId, AwsRegion, AwsSecurityFindingTitle, AwsSecurityFindingDescription,
         AwsSecurityFindingId, ComplianceSecurityControlId, QueueArn
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AwsAccountId
      - identifier: CloudAppAccountId
        columnName: AwsAccountId
  - entityType: CloudApplication
    fieldMappings:
      - identifier: Name
        columnName: QueueArn
customDetails:
  ComplianceControlId: ComplianceSecurityControlId
  Region: AwsRegion
  FindingId: AwsSecurityFindingId
alertDetailsOverride:
  alertDisplayNameFormat: "SQS queue {{QueueArn}} not encrypted at rest"
  alertDescriptionFormat: |-
    AWS Account {{AwsAccountId}} has an SQS queue ({{QueueArn}}) without server-side encryption enabled. Enable KMS encryption to protect message data at rest.
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

AWSSecurityHubFindings

Stage 2: where

| where RecordState == "ACTIVE" and ComplianceStatus == "FAILED"

Stage 3: where

| where tostring(AwsSecurityFindingGeneratorId) == "security-control/SQS.1"
      or tostring(ComplianceSecurityControlId) == "SQS.1"

Stage 4: mv-expand

| mv-expand Resource = Resources

Stage 5: where

| where tostring(Resource.Type) == "AwsSqsQueue"

Stage 6: extend

| extend QueueArn = tostring(Resource.Id)

Stage 7: summarize

| summarize TimeGenerated = max(TimeGenerated)
    by AwsAccountId, AwsRegion, AwsSecurityFindingTitle, AwsSecurityFindingDescription,
       AwsSecurityFindingId, ComplianceSecurityControlId, QueueArn

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AwsAccountIdsummarize
AwsRegionsummarize
AwsSecurityFindingDescriptionsummarize
AwsSecurityFindingIdsummarize
AwsSecurityFindingTitlesummarize
ComplianceSecurityControlIdsummarize
QueueArnsummarize
TimeGeneratedsummarize

AWSCloudTrail - S3 bucket suspicious ransomware activity

#
Status
available
Severity
high
Time window
1h
Group by
$left.bucketName, $left.keyName, $right.bucketName, $right.keyName
Source
github.com/Azure/Azure-Sentinel

Detects a ransomware-like sequence where objects are read from an S3 bucket and then overwritten using an external KMS key. This pattern can indicate malicious encryption and potential data denial in the bucket.

MITRE ATT&CK Coverage

TacticTechniques
Impact

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: b442b9e2-5cc4-4129-a85b-a5ef38a9e5f0
name: AWSCloudTrail - S3 bucket suspicious ransomware activity
description: |
  Detects a ransomware-like sequence where objects are read from an S3 bucket and then overwritten using an
  external KMS key. This pattern can indicate malicious encryption and potential data denial in the bucket.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: AWS
    dataTypes:
      - AWSCloudTrail
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Impact
relevantTechniques:
  - T1486
query: |
  let timeframe = 1h;
  let lookback = 2h;
  // The attacker downloads the object(s) from the compromised bucket
  let GetObject = AWSCloudTrail
  | where TimeGenerated >= ago(lookback)
  | where EventName == "GetObject" and isempty(ErrorCode) and isempty(ErrorMessage)
  | extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)
  | project-rename StartTime = TimeGenerated;
  // Then, the attacker overwrites the same object(s) but encrypted with his own key
  let PutObject = AWSCloudTrail
  | where TimeGenerated >= ago(timeframe)
  | where EventName == "PutObject" and isempty(ErrorCode) and isempty(ErrorMessage)
  | extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)
  | extend kmsId = tostring(parse_json(RequestParameters).["x-amz-server-side-encryption-aws-kms-key-id"])
  | where tostring(kmsId) !has tostring(RecipientAccountId) and kmsId <> "";
  PutObject
  | join kind=inner 
  (
     GetObject
  )
  on $left.bucketName == $right.bucketName, $left.keyName == $right.keyName
  | where TimeGenerated > StartTime
  | extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)
  | extend UserName = tostring(split(UserIdentityArn, '/')[-1])
  | extend AccountName = case( UserIdentityPrincipalid == "Anonymous", "Anonymous", isempty(UserIdentityUserName), UserName, UserIdentityUserName)
  | extend AccountName = iif(AccountName contains "@", tostring(split(AccountName, '@', 0)[0]), AccountName),
    AccountUPNSuffix = iif(AccountName contains "@", tostring(split(AccountName, '@', 1)[0]), "")
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountName
      - identifier: UPNSuffix
        columnName: AccountUPNSuffix
      - identifier: CloudAppAccountId
        columnName: RecipientAccountId
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SourceIpAddress
customDetails:
  bucketName: bucketName
  keyName: keyName
  kmsId: kmsId
  RecipientAccountId: RecipientAccountId
alertDetailsOverride:
  alertDisplayNameFormat: 'AWS S3 ransomware-like overwrite activity by {{AccountName}}'
  alertDescriptionFormat: 'Detected GetObject followed by encrypted PutObject activity in bucket {{bucketName}} from {{SourceIpAddress}} for account {{RecipientAccountId}}.'
version: 1.0.2
kind: Scheduled

Stages and Predicates

Parameters

let timeframe = 1h;
let lookback = 2h;

let PutObject is inlined into the numbered stages below.

Let Binding: GetObject used in Stage 7

let GetObject = AWSCloudTrail
| where TimeGenerated >= ago(lookback)
| where EventName == "GetObject" and isempty(ErrorCode) and isempty(ErrorMessage)
| extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)
| project-rename StartTime = TimeGenerated;

Stages 1 to 6 define let PutObject as the rule's main pipeline source. Stages 7 to 9 use it.

Stage 1: source

AWSCloudTrail

Stage 2: where

| where TimeGenerated >= ago(timeframe)

Stage 3: where

| where EventName == "PutObject" and isempty(ErrorCode) and isempty(ErrorMessage)

Stage 4: extend

| extend bucketName = tostring(parse_json(RequestParameters).bucketName), keyName = tostring(parse_json(RequestParameters).key)

Stage 5: extend

| extend kmsId = tostring(parse_json(RequestParameters).["x-amz-server-side-encryption-aws-kms-key-id"])

Stage 6: where

| where tostring(kmsId) !has tostring(RecipientAccountId) and kmsId <> ""

Stage 7: join

PutObject
| join kind=inner 
(
   GetObject
)
on $left.bucketName == $right.bucketName, $left.keyName == $right.keyName

Stage 8: where

where TimeGenerated > StartTime

Stage 9: extend (4 consecutive steps)

extend AccountName, AccountUPNSuffix, UserIdentityArn, UserName

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
ErrorCodeis_null
  • (no value, null check)
field:"ErrorCode" kind:is_null
ErrorMessageis_null
  • (no value, null check)
field:"ErrorMessage" kind:is_null
EventNameeq
  • GetObject
  • PutObject
field:"EventName" kind:eq

Output Fields

These fields are emitted when the rule matches.

FieldSource
bucketNameextend
keyNameextend
kmsIdextend
UserIdentityArnextend
UserNameextend
AccountNameextend
AccountUPNSuffixextend

Azure secure score sign in risk policy

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

'This query searches for an active Azure Premium P2 license is required to use and edit this policy. You will be required to have setup the MFA Policy before activating this policy'

MITRE ATT&CK Coverage

TacticTechniques
Impact

Rule Body

id: 5231D757-A5B5-4CA7-A91B-AA3702970E02
name: Azure secure score sign in risk policy
description: |
  'This query searches for an active Azure Premium P2 license is required to use and edit this policy. 
   You will be required to have setup the MFA Policy before activating this policy'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: SenservaPro
    dataTypes:
      - SenservaPro_CL
queryFrequency: 6h
queryPeriod: 6h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Impact
relevantTechniques:
  - T1529
query: |
  SenservaPro_CL
  | where ControlName_s == 'AzureSecureScoreSignInRiskPolicy'
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: ControlName_s
      - identifier: AadTenantId
        columnName: TenantId
      - identifier: DisplayName
        columnName: TenantDisplayName_s 
  - entityType: SecurityGroup
    fieldMappings:
      - identifier: DistinguishedName
        columnName: Group_s
  - entityType: AzureResource
    fieldMappings:
      - identifier: ResourceId
        columnName: SourceSystem 
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

SenservaPro_CL

Stage 2: where

| where ControlName_s == 'AzureSecureScoreSignInRiskPolicy'

Indicators

These rows show field, operator, and value matches.

Backup Repository Deleted

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

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

Rule Body

id: 73b4d1d5-c357-4350-bb58-924684a4792a
name: Backup Repository Deleted
description: Detects when a backup repository is deleted from Veeam Backup & Replication.
  This might indicate unauthorized removal of critical components.
severity: High
status: Available
requiredDataConnectors:
- connectorId: Syslog
  dataTypes:
  - Syslog
- connectorId: SyslogAma
  dataTypes:
  - Syslog
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: "Veeam_GetSecurityEvents\n| where instanceId == 28200\n| extend Name =  extract(\"\
  Name=\\\"(?<Name>[^\\\"]*)\\\"\", 1, SyslogMessage)\n| project\n    Date = format_datetime(TimeGenerated,\
  \ 'dd.MM.yyyy HH:mm'),\n    DataSource = original_host,\n    EventId = instanceId,\n\
  \    UserName = user,\n    [\"Object Name\"] = Name,\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 == 28200

Stage 3: extend

| extend Name =  extract("Name=\"(?<Name>[^\"]*)\"", 1, SyslogMessage)

Stage 4: project

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

Bitglass - New admin user

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

'Detects new admin user.'

MITRE ATT&CK Coverage

TacticTechniques
Privilege Escalation

Rule Body

id: 8c8602e6-315d-400f-9d1e-23bbdee1dbfe
name: Bitglass - New admin user
description: |
  'Detects new admin user.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: Bitglass
    dataTypes:
      - Bitglass
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - PrivilegeEscalation
relevantTechniques:
  - T1078
query: |
  Bitglass
  | where EventType =~ 'admin'
  | where EventResultDetails has_all ('User', 'Promoted to administrator')
  | extend AccountCustomEntity = User
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountCustomEntity
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

Bitglass

Stage 2: where

| where EventType =~ 'admin'

Stage 3: where

| where EventResultDetails has_all ('User', 'Promoted to administrator')

Stage 4: extend

| extend AccountCustomEntity = User

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
EventResultDetailsmatch
  • Promoted to administrator transforms: term
  • User transforms: term
field:"EventResultDetails" kind:match
EventTypeeq
  • admin
field:"EventType" kind:eq value:"admin"

Output Fields

These fields are emitted when the rule matches.

FieldSource
AccountCustomEntityextend

Checkpoint - Pending Phishing emails

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

This query searches for phishing emails that are pending action

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

id: a97e2333-b7de-4c14-9700-e652a1dbef26
name: Checkpoint - Pending Phishing emails
apiVersion: 2021-09-01-preview
description: This query searches for phishing emails that are pending action
displayName: Checkpoint - Pending Phishing emails
severity: High
enabled: true
query: CheckpointHEC_CL | where EventCurrentState == "new" and EventCategory == "phishing"
queryFrequency: 5m
queryPeriod: 15m
requiredDataConnectors:
  - connectorId: CheckpointHECConnection
    dataTypes:
      - CheckpointHEC_CL
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1566
suppressionDuration: 5h
suppressionEnabled: false
alertRuleTemplateName:
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: 1d
    matchingMethod: AllEntities
eventGroupingSettings:
  aggregationKind: SingleAlert
alertDetailsOverride:
customDetails:
  EmailID: EmailEmailId
entityMappings:
  - entityType: MailMessage
    fieldMappings:
      - identifier: Sender
        columnName: EmailFromEmail
      - identifier: NetworkMessageId
        columnName: EmailMessageId
      - identifier: Subject
        columnName: EmailSubject
  - entityType: Mailbox
    fieldMappings:
      - identifier: MailboxPrimaryAddress
        columnName: EmailTo
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

CheckpointHEC_CL

Stage 2: where

| where EventCurrentState == "new" and EventCategory == "phishing"

Indicators

These rows show field, operator, and value matches.

Cisco Cloud Security - Windows PowerShell User-Agent Detected

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

'Rule helps to detect Powershell user-agent activity by an unusual process other than a web browser.'

MITRE ATT&CK Coverage

Rule Body

id: b12b3dab-d973-45af-b07e-e29bb34d8db9
name: Cisco Cloud Security - Windows PowerShell User-Agent Detected
description: |
  'Rule helps to detect Powershell user-agent activity by an unusual process other than a web browser.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: CiscoUmbrellaDataConnector
    dataTypes:
      - Cisco_Umbrella_proxy_CL
queryFrequency: 15m
queryPeriod: 15m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CommandAndControl
  - DefenseEvasion
  - Execution
relevantTechniques:
  - T1132
  - T1027
  - T1059.001
query: |
  Cisco_Umbrella
  | where EventType == "proxylogs"
  | where HttpUserAgentOriginal contains "WindowsPowerShell"
  | extend Message = "Windows PowerShell User Agent"
  | project TimeGenerated, Message, SrcIpAddr, DstIpAddr, UrlOriginal, HttpUserAgentOriginal
entityMappings:
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: UrlOriginal
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SrcIpAddr
version: 1.1.3
kind: Scheduled

Stages and Predicates

Stage 1: source

Cisco_Umbrella

Stage 2: where

| where EventType == "proxylogs"

Stage 3: where

| where HttpUserAgentOriginal contains "WindowsPowerShell"

Stage 4: extend

| extend Message = "Windows PowerShell User Agent"

Stage 5: project

| project TimeGenerated, Message, SrcIpAddr, DstIpAddr, UrlOriginal, 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 SEG - Suspicious link

#

Cisco SEG - Unscannable attacment

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

'Detects unscannable attachments in mails.'

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

id: c66b8ced-8c76-415b-a0f3-08c7030a857d
name: Cisco SEG - Unscannable attacment
description: |
  'Detects unscannable attachments in mails.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: CefAma
    dataTypes:
      - CommonSecurityLog
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1566
query: |
  CiscoSEGEvent
  | where NetworkDirection =~ 'Incoming'
  | where tostring(AdditionalFields) has 'ESAAMPVerdict'
  | extend amp_verdict = extract(@'ESAAMPVerdict":"(NOT_EVALUATED|CLEAN|FA_PENDING|UNKNOWN|SKIPPED|UNSCANNABLE|LOW_RISK|MALICIOUS)"', 1, tostring(AdditionalFields))
  | where amp_verdict =~ 'UNSCANNABLE'
  | extend AccountCustomEntity = DstUserName
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountCustomEntity
version: 1.0.3
kind: Scheduled

Stages and Predicates

Stage 1: source

CiscoSEGEvent

Stage 2: where

| where NetworkDirection =~ 'Incoming'

Stage 3: where

| where tostring(AdditionalFields) has 'ESAAMPVerdict'

Stage 4: extend

| extend amp_verdict = extract(@'ESAAMPVerdict":"(NOT_EVALUATED|CLEAN|FA_PENDING|UNKNOWN|SKIPPED|UNSCANNABLE|LOW_RISK|MALICIOUS)"', 1, tostring(AdditionalFields))

Stage 5: where

| where amp_verdict =~ 'UNSCANNABLE'

Stage 6: extend

| extend AccountCustomEntity = DstUserName

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
amp_verdictextend
AccountCustomEntityextend

Claroty - Login to uncommon location

#
Status
available
Severity
medium
Time window
14d
Group by
EventMessage, EventType, Site, SrcIpAddr, SrcUsername
Source
github.com/Azure/Azure-Sentinel

Detects user login to uncommon location.

MITRE ATT&CK Coverage

Rule Body

id: e7dbcbc3-b18f-4635-b27c-718195c369f1
name: Claroty - Login to uncommon location
description: 'Detects user login to uncommon location.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: CefAma
    dataTypes:
      - CommonSecurityLog
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1190
  - T1133
query: |
  let usr_sites = ClarotyEvent
  | where TimeGenerated > ago(14d)
  | where EventType has 'Login to SRA succeeded'
  | extend Site = column_ifexists("site_name","")
  | where isnotempty(Site)
  | extend SrcUsername = extract(@'User\s(.*?)\slogged', 1, EventMessage)
  | where isnotempty(SrcUsername)
  | summarize all_loc = make_set(tostring(Site)) by SrcUsername;
  ClarotyEvent
  | where TimeGenerated > ago(14d)
  | where EventType has 'Login to SRA succeeded'
  | extend Site = column_ifexists("site_name","")
  | where isnotempty(Site)
  | extend SrcUsername = extract(@'User\s(.*?)\slogged', 1, EventMessage)
  | where isnotempty(SrcUsername)
  | join kind=leftouter (usr_sites) on SrcUsername
  | where isempty(all_loc) or not(set_has_element(all_loc, tostring(Site)))
  | extend SrcIpAddr
  | summarize StartTime=min(TimeGenerated), EndTime=max(TimeGenerated), EventCount=count(), Sites=make_set(Site, 100), KnownSites=any(all_loc) by SrcUsername, SrcIpAddr, Site, EventType, EventMessage
  | extend UncommonSiteCount = array_length(Sites)
  | project StartTime, EndTime, SrcUsername, SrcIpAddr, Site, EventType, EventMessage, EventCount, UncommonSiteCount, KnownSites
entityMappings:
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: SrcIpAddr
version: 1.0.4
kind: Scheduled

Stages and Predicates

Let Binding: usr_sites used in Stage 8

let usr_sites = ClarotyEvent
| where TimeGenerated > ago(14d)
| where EventType has 'Login to SRA succeeded'
| extend Site = column_ifexists("site_name","")
| where isnotempty(Site)
| extend SrcUsername = extract(@'User\s(.*?)\slogged', 1, EventMessage)
| where isnotempty(SrcUsername)
| summarize all_loc = make_set(tostring(Site)) by SrcUsername;

Stage 1: source

ClarotyEvent

Stage 2: where

| where TimeGenerated > ago(14d)

Stage 3: where

| where EventType has 'Login to SRA succeeded'

Stage 4: extend

| extend Site = column_ifexists("site_name","")

Stage 5: where

| where isnotempty(Site)

Stage 6: extend

| extend SrcUsername = extract(@'User\s(.*?)\slogged', 1, EventMessage)

Stage 7: where

| where isnotempty(SrcUsername)

Stage 8: join

| join kind=leftouter (usr_sites) on SrcUsername

Stage 9: where

where (not (all_loc =~ "Site") or isempty(all_loc))

Stage 10: extend

extend SrcIpAddr

Stage 11: summarize

summarize EndTime, EventCount, KnownSites, Sites, StartTime by SrcUsername, SrcIpAddr, Site, EventType, EventMessage

Stage 12: extend

extend UncommonSiteCount

Stage 13: project

project EndTime, EventCount, EventMessage, EventType, KnownSites, Site, SrcIpAddr, SrcUsername, StartTime, UncommonSiteCount

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
EventTypematch
  • Login to SRA succeeded transforms: term
field:"EventType" kind:match value:"Login to SRA succeeded"
Siteis_not_null
  • (no value, null check)
field:"Site" kind:is_not_null
SrcUsernameis_not_null
  • (no value, null check)
field:"SrcUsername" kind:is_not_null
all_locis_null
  • (no value, null check)
field:"all_loc" kind:is_null

Output Fields

These fields are emitted when the rule matches.

FieldSource
EndTimeproject
EventCountproject
EventMessageproject
EventTypeproject
KnownSitesproject
Siteproject
SrcIpAddrproject
SrcUsernameproject
StartTimeproject
UncommonSiteCountproject

Cloud Gateway Pool Settings Updated

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

Detects when cloud gateway pool settings are updated in Veeam Backup & Replication. This might indicate configuration changes that require review.

Rule Body

id: 2b3b59eb-ea7c-45f6-9df8-8dbaed632317
name: Cloud Gateway Pool Settings Updated
description: Detects when cloud gateway pool settings are updated in Veeam Backup
  & Replication. This might indicate configuration changes that require review.
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 == 24142\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 == 24142

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

Cognni Incidents for Highly Sensitive Financial Information

#

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
5h
Source
github.com/Azure/Azure-Sentinel

'Display incidents in which highly sensitive financial information was placed at risk by user sharing.'

MITRE ATT&CK Coverage

TacticTechniques
Collection

Rule Body

id: 7ebb7386-6c99-4331-aab1-a185a603eb47
name: Cognni Incidents for Highly Sensitive Financial Information
description: |
  'Display incidents in which highly sensitive financial information was placed at risk by user sharing.'
severity: High
requiredDataConnectors:
  - connectorId: CognniSentinelDataConnector
    dataTypes:
      - CognniIncidents_CL
queryFrequency: 5h
queryPeriod: 5h
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - Collection
relevantTechniques:
  - T1530
query: |
  let highRisk = 3;
  let financial = 'Financial Information';
  CognniIncidents_CL 
  | where Severity == highRisk
  | where informationType_s == financial
  | where TimeGenerated >= ago(5h)
  | extend AccountCustomEntity = userId_s
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountCustomEntity
version: 1.0.0
kind: Scheduled

Stages and Predicates

Parameters

let highRisk = 3;
let financial = 'Financial Information';

Stage 1: source

CognniIncidents_CL

Stage 2: where

| where Severity == highRisk

Stage 3: where

| where informationType_s == financial

Stage 4: where

| where TimeGenerated >= ago(5h)

Stage 5: extend

| extend AccountCustomEntity = userId_s

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AccountCustomEntityextend

Detecting Impossible travel with mailbox permission tampering & Privilege Escalation attempt

#
Severity
medium
Time window
1d
Group by
$left.Account, $left.UserId, $right.Initiatedby, $right.UserId
Author
Microsoft Security Research
Source
github.com/Azure/Azure-Sentinel

This hunting query will alert on any Impossible travel activity in correlation with mailbox permission tampering followed by account being added to a PIM managed privileged group. Ensure this impossible travel incident with increase of privileges is legitimate in your environment.

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: 1399664f-9434-497c-9cde-42e4d74ae20e
name: Detecting Impossible travel with mailbox permission tampering & Privilege Escalation attempt
description: |
  'This hunting query will alert on any Impossible travel activity in correlation with mailbox permission tampering followed by account being added to a PIM managed privileged group.
  Ensure this impossible travel incident with increase of privileges is legitimate in your environment.'
severity: Medium
requiredDataConnectors:
  - connectorId: AzureSecurityCenter
    dataTypes:
      - SecurityAlert (ASC)
  - connectorId: Office365
    dataTypes:
      - OfficeActivity
  - connectorId: AzureActivity
    dataTypes:
      - AzureActivity
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AuditLogs
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
  - PrivilegeEscalation
relevantTechniques:
  - T1078
  - T1548
query: |
  SecurityAlert 
  | where AlertName == "Impossible travel activity"
  | extend Extprop = parsejson(Entities)
  | mv-expand Extprop
  | extend Extprop = parsejson(Extprop)
  | extend CmdLine = iff(Extprop['Type']=="process", Extprop['CommandLine'], '')
  | extend File = iff(Extprop['Type']=="file", Extprop['Name'], '')
  | extend Account = Extprop['Name']
  | extend Domain = Extprop['UPNSuffix']
  | extend Account = iif(isnotempty(Domain) and Extprop['Type']=="account", tolower(strcat(Account, "@", Domain)), iif(Extprop['Type']=="account", tolower(Account), ""))
  | extend IpAddress = iff(Extprop["Type"] == "ip",Extprop['Address'], '')
  | extend Process = iff(isnotempty(CmdLine), CmdLine, File)
  | project TimeGenerated,Account,IpAddress,CompromisedEntity,Description,ProviderName,ResourceId
  | join kind=inner
  (
  OfficeActivity
  | where Operation =~ "Add-MailboxPermission"
  | extend value = tostring(parse_json(Parameters)[3].Value)
  | where value contains "FullAccess"
  | where ResultStatus == "True"
  | project Parameters,TimeGenerated,value,RecordType,Operation,OrganizationId,UserType,UserKey,OfficeWorkload,ResultStatus,OfficeObjectId,UserId,ClientIP,ExternalAccess,OriginatingServer,OrganizationName,TenantId,ElevationTime,SourceSystem,OfficeId,OfficeTenantId,Type,SourceRecordId
  ) on $left.Account == $right.UserId
  | join kind=inner
  (
  AuditLogs
  | where ActivityDisplayName =~ "Add eligible member to role in PIM requested (timebound)"
  | where AADOperationType =~ "CreateRequestEligibleRole"
  | where TargetResources has_any ("-PRIV", "Administrator", "Security")
  | extend BuiltinRole = tostring(parse_json(TargetResources[0].displayName))
  | extend CustomGroup = tostring(parse_json(TargetResources[3].displayName))
  | extend TargetAccount = tostring(parse_json(TargetResources[2].displayName))
  | extend Initiatedby = Identity
  | project TimeGenerated, ActivityDisplayName, AADOperationType, Initiatedby, TargetAccount, BuiltinRole, CustomGroup, LoggedByService, Result, ResourceId, Id
  | sort by TimeGenerated desc
  ) on $left.UserId == $right.Initiatedby
  | extend AccountName = tostring(split(Initiatedby, "@")[0]), AccountUPNSuffix = tostring(split(Initiatedby, "@")[1])
  | project AADOperationType, ActivityDisplayName,AccountName, AccountUPNSuffix, Id,ResourceId,IpAddress
  
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountName
      - identifier: UPNSuffix
        columnName: AccountUPNSuffix
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IpAddress
version: 1.0.3
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Microsoft Security Research
    support:
        tier: Community
    categories:
        domains: [ "Security - Others", "Identity" ]

Stages and Predicates

Stage 1: source

SecurityAlert

Stage 2: where

| where AlertName == "Impossible travel activity"

Stage 3: extend

| extend Extprop = parsejson(Entities)

Stage 4: mv-expand

| mv-expand Extprop

Stage 5: extend (8 consecutive steps)

| extend Extprop = parsejson(Extprop)
| extend CmdLine = iff(Extprop['Type']=="process", Extprop['CommandLine'], '')
| extend File = iff(Extprop['Type']=="file", Extprop['Name'], '')
| extend Account = Extprop['Name']
| extend Domain = Extprop['UPNSuffix']
| extend Account = iif(isnotempty(Domain) and Extprop['Type']=="account", tolower(strcat(Account, "@", Domain)), iif(Extprop['Type']=="account", tolower(Account), ""))
| extend IpAddress = iff(Extprop["Type"] == "ip",Extprop['Address'], '')
| extend Process = iff(isnotempty(CmdLine), CmdLine, File)

Stage 6: project

| project TimeGenerated,Account,IpAddress,CompromisedEntity,Description,ProviderName,ResourceId

Stage 7: join

| join kind=inner
(
OfficeActivity
| where Operation =~ "Add-MailboxPermission"
| extend value = tostring(parse_json(Parameters)[3].Value)
| where value contains "FullAccess"
| where ResultStatus == "True"
| project Parameters,TimeGenerated,value,RecordType,Operation,OrganizationId,UserType,UserKey,OfficeWorkload,ResultStatus,OfficeObjectId,UserId,ClientIP,ExternalAccess,OriginatingServer,OrganizationName,TenantId,ElevationTime,SourceSystem,OfficeId,OfficeTenantId,Type,SourceRecordId
) on $left.Account == $right.UserId

Stage 8: join

| join kind=inner
(
AuditLogs
| where ActivityDisplayName =~ "Add eligible member to role in PIM requested (timebound)"
| where AADOperationType =~ "CreateRequestEligibleRole"
| where TargetResources has_any ("-PRIV", "Administrator", "Security")
| extend BuiltinRole = tostring(parse_json(TargetResources[0].displayName))
| extend CustomGroup = tostring(parse_json(TargetResources[3].displayName))
| extend TargetAccount = tostring(parse_json(TargetResources[2].displayName))
| extend Initiatedby = Identity
| project TimeGenerated, ActivityDisplayName, AADOperationType, Initiatedby, TargetAccount, BuiltinRole, CustomGroup, LoggedByService, Result, ResourceId, Id
| sort by TimeGenerated desc
) on $left.UserId == $right.Initiatedby

Stage 9: extend

extend AccountName, AccountUPNSuffix

Stage 10: project

project AADOperationType, AccountName, AccountUPNSuffix, ActivityDisplayName, Id, IpAddress, ResourceId

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AADOperationTypeproject
AccountNameproject
AccountUPNSuffixproject
ActivityDisplayNameproject
Idproject
IpAddressproject
ResourceIdproject

Google SecOps - Multi-Event Correlated Alert

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

Creates incidents in Microsoft Sentinel when Google Security Operations raises an active multi-event correlated alert (MULTI_EVENT, riskScore gte 40) at HIGH or CRITICAL severity. These alerts indicate complex attack patterns like lateral movement, staged persistence, or command-and-control identified by correlating multiple signals across a time window.

MITRE ATT&CK Coverage

Rule Body

id: d4f8a032-6d5b-4e9f-b3a0-8c2e4f7d0b6e
name: Google SecOps - Multi-Event Correlated Alert
description: |
  Creates incidents in Microsoft Sentinel when Google Security Operations raises an active multi-event correlated alert (MULTI_EVENT, riskScore gte 40) at HIGH or CRITICAL severity. These alerts indicate complex attack patterns like lateral movement, staged persistence, or command-and-control identified by correlating multiple signals across a time window.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: GSDetectionAlerts
    dataTypes:
      - DetectionAlerts_CL
queryFrequency: 10m
queryPeriod: 10m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - LateralMovement
  - Persistence
  - PrivilegeEscalation
  - CommandAndControl
relevantTechniques:
  - T1210
  - T1021
  - T1053
  - T1055
query: |
  GoogleSecOpsDetectionAlerts
  | where ruleType == "MULTI_EVENT"
  | where severity in ("HIGH", "CRITICAL")
  | where riskScore >= 40
  | where alertState == "ALERTING"
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: varPrincipalIp
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: varTargetIp
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: varSourceIp
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: varCorrelationIp
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: urlBackToProduct
customDetails:
  RuleName: ruleName
  RuleType: ruleType
  Severity: severity
  RiskScore: riskScore
  SourceIPCount: varSourceIpCount
  PrincipalIPCount: varPrincipalIpCount
  DetectionTime: detectionTime
  PrincipalIP: varPrincipalIp
  TargetIP: varTargetIp
  SourceIP: varSourceIp
  CorrelationIP: varCorrelationIp
  PrincipalHostname: varPrincipalHostname
  TargetHostname: varTargetHostname
  SourceHostname: varSourceHostname
  PrincipalUser: varPrincipalUserUserid
  SourceUser: varSourceUserUserid
  TargetUser: varTargetUserUserid
  alert_identifier: id
alertDetailsOverride:
  alertDisplayNameFormat: "Multi-Event Correlation: {{ruleName}} : {{id}}"
  alertDescriptionFormat: "Google SecOps correlated multiple events into a confirmed alert. Rule: {{ruleName}}."
eventGroupingSettings:
  aggregationKind: AlertPerResult
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: true
    lookbackDuration: P1D
    matchingMethod: Selected
    groupByCustomDetails:
      - alert_identifier
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

GoogleSecOpsDetectionAlerts

Stage 2: where

| where ruleType == "MULTI_EVENT"

Stage 3: where

| where severity in ("HIGH", "CRITICAL")

Stage 4: where

| where riskScore >= 40

Stage 5: where

| where alertState == "ALERTING"

Indicators

These rows show field, operator, and value matches.

Object Storage Deleted

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

Detects when an object storage is deleted from Veeam Backup & Replication. This might indicate unauthorized removal of critical components.

Rule Body

id: 6e4d1832-2cf9-410d-a5e2-c12b33c7d9f7
name: Object Storage Deleted
description: Detects when an object storage is deleted from Veeam Backup & Replication.
  This might indicate unauthorized removal of critical components.
severity: High
status: Available
requiredDataConnectors:
- connectorId: Syslog
  dataTypes:
  - Syslog
- connectorId: SyslogAma
  dataTypes:
  - Syslog
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: "Veeam_GetSecurityEvents\n| where instanceId == 28980\n| extend Name =  extract(\"\
  Name=\\\"(?<Name>[^\\\"]*)\\\"\", 1, SyslogMessage)\n| project\n    Date = format_datetime(TimeGenerated,\
  \ 'dd.MM.yyyy HH:mm'),\n    DataSource = original_host,\n    EventId = instanceId,\n\
  \    UserName = user,\n    [\"Data SourceName\"] = Name,\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 == 28980

Stage 3: extend

| extend Name =  extract("Name=\"(?<Name>[^\"]*)\"", 1, SyslogMessage)

Stage 4: project

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

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
Data SourceNameproject
DataSourceproject
Dateproject
EventIdproject
MessageDetailsproject
Severityproject
UserNameproject

PaloAlto - Possible attack without response

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

'Detects possible attack without response.'

MITRE ATT&CK Coverage

Rule Body

id: b6d54840-51d3-11ec-bf63-0242ac130002
name: PaloAlto - Possible attack without response
description: |
  'Detects possible attack without response.'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: CefAma
    dataTypes:
      - CommonSecurityLog
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1190
  - T1133
query: |
  PaloAltoCDLEvent
  | where EventResourceId =~ 'THREAT'
  | where DvcAction !has "block" or DvcAction !has "override" or DvcAction !has "deny"
  | extend AccountCustomEntity = DstUsername, IPCustomEntity = SrcIpAddr, UrlCustomEntity = Url
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountCustomEntity
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPCustomEntity
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: UrlCustomEntity
version: 1.0.4
kind: Scheduled

Stages and Predicates

Stage 1: source

PaloAltoCDLEvent

Stage 2: where

| where EventResourceId =~ 'THREAT'

Stage 3: where

| where DvcAction !has "block" or DvcAction !has "override" or DvcAction !has "deny"

Stage 4: extend

| extend AccountCustomEntity = DstUsername, IPCustomEntity = SrcIpAddr, UrlCustomEntity = Url

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AccountCustomEntityextend
IPCustomEntityextend
UrlCustomEntityextend

Recorded Future Sandbox - Malicious Email Attachment

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

'Creates incidents when Recorded Future Sandbox detects malicious files from Outlook email attachments'

Rule Body

id: a1b2c3d4-5678-90ab-cdef-222222222222
name: Recorded Future Sandbox - Malicious Email Attachment
description: |
  'Creates incidents when Recorded Future Sandbox detects malicious files from Outlook email attachments'
severity: High
status: Available
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: |
  RecordedFutureSandboxResults_CL
  | where TimeGenerated >= now(-1h)
  | where Source_s == "OutlookAttachment"
  | where toint(SandboxScore_s) >= 50
eventGroupingSettings:
  aggregationKind: AlertPerResult
alertDetailsOverride:
  alertDisplayNameFormat: 'Malicious Email Attachment: {{FileName_s}} from {{EmailFrom_s}}'
  alertDescriptionFormat: |
    _Recorded Future Sandbox - Malicious Email Attachment Detected_

    **Sandbox Score:** {{SandboxScore_s}}/100

    **Verdict:** {{SandboxVerdict_s}}

    **Sample ID:** {{SampleId_s}}

    A malicious file was detected in an email attachment. Review the full sandbox report and investigate the sender.
customDetails:
  RFLabel: SourceSystem
  Source: Source_s
  SandboxScore: SandboxScore_s
  SandboxVerdict: SandboxVerdict_s
  FileName: FileName_s
  SampleId: SampleId_s
  EmailFrom: EmailFrom_s
  EmailTo: EmailTo_s
entityMappings:
  - entityType: File
    fieldMappings:
      - identifier: Name
        columnName: FileName_s
  - entityType: Mailbox
    fieldMappings:
      - identifier: MailboxPrimaryAddress
        columnName: EmailFrom_s
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: 1h
    matchingMethod: Selected
    groupByCustomDetails:
      - EmailFrom
version: 1.0.0
kind: NRT

Stages and Predicates

Stage 1: source

RecordedFutureSandboxResults_CL

Stage 2: where

| where TimeGenerated >= now(-1h)

Stage 3: where

| where Source_s == "OutlookAttachment"

Stage 4: where

| where toint(SandboxScore_s) >= 50

Indicators

These rows show field, operator, and value matches.

Scale-Out Backup Repository Settings Updated

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

Detects when scale-out backup repository settings are updated in Veeam Backup & Replication. This might indicate configuration changes that require review.

Rule Body

id: 12006091-95a7-4f21-b474-f74b0480a138
name: Scale-Out Backup Repository Settings Updated
description: Detects when scale-out backup repository settings are updated in Veeam
  Backup & Replication. This might indicate configuration changes that require review.
severity: Low
status: Available
requiredDataConnectors:
- connectorId: Syslog
  dataTypes:
  - Syslog
- connectorId: SyslogAma
  dataTypes:
  - Syslog
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: "Veeam_GetSecurityEvents\n| where instanceId == 30100\n| extend Name = extract(\"\
  Name=\\\"([^\\\"]*)\\\"\", 1, SyslogMessage)\n| project\n    Date = format_datetime(TimeGenerated,\
  \ 'dd.MM.yyyy HH:mm'),\n    DataSource = original_host,\n    EventId = instanceId,\n\
  \    UserName = user,\n    [\"Object Name\"] = Name,\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 == 30100

Stage 3: extend

| extend Name = extract("Name=\"([^\"]*)\"", 1, SyslogMessage)

Stage 4: project

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

SlackAudit - Suspicious file downloaded.

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

'Detects potentialy suspicious downloads.'

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

id: 132b98a5-07e9-401a-9b6f-453e52a53979
name: SlackAudit - Suspicious file downloaded.
description: |
  'Detects potentialy suspicious downloads.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: SlackAuditAPI
    dataTypes:
      - SlackAudit_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1189
query: |
  SlackAudit
  | where DvcAction =~ 'file_downloaded'
  | extend FileName = tostring(EntityFileName)
  | extend fe = split(FileName, '.')
  | extend FileExtension = iff(array_length(fe) > 1, tostring(fe[-1]), '')
  | where FileName contains '.'
  | where FileExtension matches regex @"^[A-Za-z]{1,4}$"
  | project EntityFileName = FileName, SrcUserName
  | extend AccountCustomEntity = SrcUserName
  | extend FileCustomEntity = EntityFileName
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountCustomEntity
  - entityType: File
    fieldMappings:
      - identifier: Name
        columnName: FileCustomEntity
alertDetailsOverride:
  alertDisplayNameFormat: 'Suspicious Slack file downloaded by {{SrcUserName}}: {{EntityFileName}}'
  alertDescriptionFormat: A Slack audit file_downloaded event matched the suspicious extension heuristic for {{EntityFileName}}
    by {{SrcUserName}}.
customDetails:
  FileName: EntityFileName
  UserName: SrcUserName
version: 1.0.1
kind: Scheduled

Stages and Predicates

Stage 1: source

SlackAudit

Stage 2: where

| where DvcAction =~ 'file_downloaded'

Stage 3: extend (3 consecutive steps)

| extend FileName = tostring(EntityFileName)
| extend fe = split(FileName, '.')
| extend FileExtension = iff(array_length(fe) > 1, tostring(fe[-1]), '')

Stage 4: where

| where FileName contains '.'

Stage 5: where

| where FileExtension matches regex @"^[A-Za-z]{1,4}$"

Stage 6: project

| project EntityFileName = FileName, SrcUserName

Stage 7: extend

| extend AccountCustomEntity = SrcUserName

Stage 8: extend

| extend FileCustomEntity = EntityFileName

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
EntityFileNameproject
SrcUserNameproject
AccountCustomEntityextend
FileCustomEntityextend

TacitRed - High Confidence Compromise

#

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

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

Detects compromised credentials with high confidence scores. High confidence findings indicate verified credential compromises that require immediate attention. Ref: https://data443.com/tacitred-attack-surface-intelligence/

MITRE ATT&CK Coverage

TacticTechniques
Reconnaissance
Initial Access

Rule Body

id: b2c3d4e5-f6a7-8901-bcde-f23456789012
name: TacitRed - High Confidence Compromise
version: 1.0.1
kind: Scheduled
description: |-
  Detects compromised credentials with high confidence scores.
  High confidence findings indicate verified credential compromises that require immediate attention.
  
  Ref: https://data443.com/tacitred-attack-surface-intelligence/
severity: High
requiredDataConnectors:
  - connectorId: TacitRedThreatIntel
    dataTypes:
      - TacitRed_Findings_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: GreaterThan
triggerThreshold: 0
tactics:
  - CredentialAccess
  - InitialAccess
  - Reconnaissance
relevantTechniques:
  - T1078
  - T1589
query: |-
  TacitRed_Findings_CL
  | where TimeGenerated >= ago(1h)
  | where confidence_d >= 80
  | extend
      Email = tostring(email_s),
      Username = tostring(username_s),
      Domain = tostring(domain_s),
      FindingType = tostring(findingType_s),
      Confidence = todouble(confidence_d),
      Source = tostring(source_s),
      Severity = tostring(severity_s)
  | project
      TimeGenerated,
      Email,
      Username,
      Domain,
      FindingType,
      Confidence,
      Source,
      Severity
suppressionEnabled: false
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: 5h
    matchingMethod: Selected
    groupByEntities:
      - Account
suppressionDuration: 5h
eventGroupingSettings:
  aggregationKind: AlertPerResult
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: Username
      - identifier: UPNSuffix
        columnName: Email
  - entityType: DNS
    fieldMappings:
      - identifier: DomainName
        columnName: Domain

Stages and Predicates

Stage 1: source

TacitRed_Findings_CL

Stage 2: where

| where TimeGenerated >= ago(1h)

Stage 3: where

| where confidence_d >= 80

Stage 4: extend

| extend
    Email = tostring(email_s),
    Username = tostring(username_s),
    Domain = tostring(domain_s),
    FindingType = tostring(findingType_s),
    Confidence = todouble(confidence_d),
    Source = tostring(source_s),
    Severity = tostring(severity_s)

Stage 5: project

| project
    TimeGenerated,
    Email,
    Username,
    Domain,
    FindingType,
    Confidence,
    Source,
    Severity

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
confidence_dge
  • 80 transforms: number
field:"confidence_d" kind:ge value:"80"

Output Fields

These fields are emitted when the rule matches.

FieldSource
Confidenceproject
Domainproject
Emailproject
FindingTypeproject
Severityproject
Sourceproject
TimeGeneratedproject
Usernameproject

TI map IP entity to LastPass data

#
Status
available
Severity
medium
Time window
14d
Group by
$left.TI_ipEntity, $right.IP_Address_s, IndicatorId
Source
github.com/Azure/Azure-Sentinel

'Identifies a match in LastPass table from any IP IOC from TI'

MITRE ATT&CK Coverage

TacticTechniques
Impact

Rule Body

id: 2a723664-22c2-4d3e-bbec-5843b90166f3
name: TI map IP entity to LastPass data
description: |
  'Identifies a match in LastPass table from any IP IOC from TI'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: LastPass
    dataTypes:
      - LastPassNativePoller_CL
  - connectorId: ThreatIntelligence
    dataTypes:
      - ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics:
  - Impact
relevantTechniques:
 - T1485
query: |
    let dt_lookBack = 1h;
    let ioc_lookBack = 14d;
    ThreatIntelligenceIndicator
    | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
    | where Active == true
    // Picking up only IOC's that contain the entities we want
    | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
    // As there is potentially more than 1 indicator type for matching IP, taking Network IP first, then others if that is empty.
    // Taking the first non-empty value based on potential IOC match availability
    | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
    | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
    | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
    | join (
        LastPassNativePoller_CL | where todatetime(Time_s) >= ago(dt_lookBack)
        | where Action_s != "Reporting"
        // renaming time column so it is clear the log this came from
        | extend LastPass_TimeGenerated = todatetime(Time_s)
    )
    on $left.TI_ipEntity == $right.IP_Address_s
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
    | project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, LastPass_TimeGenerated, 
    TI_ipEntity, IP_Address_s, Username_s, Action_s, Data_s, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: Username_s
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IP_Address_s
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: Url
version: 1.0.1
kind: Scheduled

Stages and Predicates

Parameters

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

Stage 1: source

ThreatIntelligenceIndicator

Stage 2: where

| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()

Stage 3: where

| where Active == true

Stage 4: where

| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)

Stage 5: extend (3 consecutive steps)

| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
TI_ipEntity =
ifisnotempty(NetworkIP)NetworkIP
elseNetworkDestinationIP

Stage 6: join

| join (
    LastPassNativePoller_CL | where todatetime(Time_s) >= ago(dt_lookBack)
    | where Action_s != "Reporting"
    | extend LastPass_TimeGenerated = todatetime(Time_s)
)
on $left.TI_ipEntity == $right.IP_Address_s

Stage 7: summarize

summarize LatestIndicatorTime by IndicatorId

Stage 8: project

project Action_s, ActivityGroupNames, ConfidenceScore, Data_s, Description, EmailSourceIpAddress, ExpirationDateTime, IP_Address_s, IndicatorId, LastPass_TimeGenerated, LatestIndicatorTime, NetworkDestinationIP, NetworkIP, NetworkSourceIP, TI_ipEntity, ThreatType, Url, Username_s

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
Action_sproject
ActivityGroupNamesproject
ConfidenceScoreproject
Data_sproject
Descriptionproject
EmailSourceIpAddressproject
ExpirationDateTimeproject
IP_Address_sproject
IndicatorIdproject
LastPass_TimeGeneratedproject
LatestIndicatorTimeproject
NetworkDestinationIPproject
NetworkIPproject
NetworkSourceIPproject
TI_ipEntityproject
ThreatTypeproject
Urlproject
Username_sproject

User login from different countries within 3 hours (Uses Authentication Normalization)

#
Severity
high
Time window
3h
Group by
TargetUserId, TargetUserType, TargetUsername
Author
Ofer Shezaf
Source
github.com/Azure/Azure-Sentinel

This query searches for successful user logins from different countries within 3 hours. To use this analytics rule, make sure you have deployed the ASIM normalization parsers

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Telemetry Coverage

Rule Body

id: 09ec8fa2-b25f-4696-bfae-05a7b85d7b9e
name: User login from different countries within 3 hours (Uses Authentication Normalization)
description: |
  'This query searches for successful user logins from different countries within 3 hours.
   To use this analytics rule, make sure you have deployed the [ASIM normalization parsers](https://aka.ms/ASimAuthentication)'
severity: High
requiredDataConnectors: []
queryFrequency: 3h
queryPeriod: 3h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess 
relevantTechniques:
  - T1078
tags:
  - Id: 2954d424-f786-4677-9ffc-c24c44c6e7d5
    version: 1.0.0
  - Schema: ASIMAuthentication
    SchemaVersion: 0.1.0
query: |
  let timeframe = ago(3h);
  let threshold = 2;
  imAuthentication
  | where TimeGenerated > timeframe
  | where EventType == 'Logon'
      and EventResult == 'Success'
  | where isnotempty(SrcGeoCountry)
  | summarize
      StartTime        = min(TimeGenerated)
      , EndTime        = max(TimeGenerated)
      , Vendors        = make_set(EventVendor, 128)
      , Products       = make_set(EventProduct, 128)
      , NumOfCountries = dcount(SrcGeoCountry)
      , Countries      = make_set(SrcGeoCountry, 128)
      by TargetUserId, TargetUsername, TargetUserType
  | where NumOfCountries >= threshold
  | where TargetUserType !in ("Application", "Service", "System", "Other", "Machine", "ServicePrincipal")
  | extend
    Name = iif(
        TargetUsername contains "@"
            , tostring(split(TargetUsername, '@', 0)[0])
            , TargetUsername
        ),
    UPNSuffix = iif(
        TargetUsername contains "@"
        , tostring(split(TargetUsername, '@', 1)[0])
        , ""
    )
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: TargetUserName
      - identifier: Name
        columnName: Name
      - identifier: UPNSuffix
        columnName: UPNSuffix
version: 1.2.5
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Ofer Shezaf
    support:
        tier: Community
    categories:
        domains: [ "Security - Network" ]

Stages and Predicates

Parameters

let timeframe = ago(3h);
let threshold = 2;

Stage 1: source

imAuthentication

Stage 2: where

| where TimeGenerated > timeframe

Stage 3: where

| where EventType == 'Logon'
    and EventResult == 'Success'

Stage 4: where

| where isnotempty(SrcGeoCountry)

Stage 5: summarize

| summarize
    StartTime        = min(TimeGenerated)
    , EndTime        = max(TimeGenerated)
    , Vendors        = make_set(EventVendor, 128)
    , Products       = make_set(EventProduct, 128)
    , NumOfCountries = dcount(SrcGeoCountry)
    , Countries      = make_set(SrcGeoCountry, 128)
    by TargetUserId, TargetUsername, TargetUserType

Stage 6: where

| where NumOfCountries >= threshold

Stage 7: where

| where TargetUserType !in ("Application", "Service", "System", "Other", "Machine", "ServicePrincipal")

Stage 8: extend

| extend
  Name = iif(
      TargetUsername contains "@"
          , tostring(split(TargetUsername, '@', 0)[0])
          , TargetUsername
      ),
  UPNSuffix = iif(
      TargetUsername contains "@"
      , tostring(split(TargetUsername, '@', 1)[0])
      , ""
  )

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
TargetUserTypeinApplication, Machine, Other, Service, ServicePrincipal, Systemexcludes:TargetUserType

Output Fields

These fields are emitted when the rule matches.

FieldSource
Countriessummarize
EndTimesummarize
NumOfCountriessummarize
Productssummarize
StartTimesummarize
TargetUserIdsummarize
TargetUserTypesummarize
TargetUsernamesummarize
Vendorssummarize
Nameextend
UPNSuffixextend

Veeam ONE Possible Ransomware Activity (vSphere)

#

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 possible ransomware activity alerts for VMware vSphere.

Rule Body

id: 37d97c4d-a42f-495b-a523-376416b278b5
name: Veeam ONE Possible Ransomware Activity (vSphere)
description: Detects Veeam ONE possible ransomware activity alerts for VMware vSphere.
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 == 342
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 == 342

Indicators

These rows show field, operator, and value matches.

Wazuh - Large Number of Web errors from an IP

#
Severity
low
Time window
1d
Group by
HostName, SourceIP
Author
Jordan Ross
Source
github.com/Azure/Azure-Sentinel

'Identifies instances where Wazuh logged over 400 '403' Web Errors from one IP Address. To onboard Wazuh data into Sentinel please view: https://documentation.wazuh.com/current/cloud-security/azure/index.html'

MITRE ATT&CK Coverage

TacticTechniques
Credential Access

Rule Body

id: 2790795b-7dba-483e-853f-44aa0bc9c985
name: Wazuh - Large Number of Web errors from an IP
description: |
  'Identifies instances where Wazuh logged over 400 '403' Web Errors from one IP Address. To onboard Wazuh data into Sentinel please view: https://documentation.wazuh.com/current/cloud-security/azure/index.html'
severity: Low
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CredentialAccess
relevantTechniques:
  - T1110
query: |
  CommonSecurityLog
  | where DeviceProduct =~ "Wazuh"
  | where Activity has "Web server 400 error code."
  | where Message has "403"
  | extend HostName=substring(split(DeviceCustomString1,")")[0],1)
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), NumberOfErrors = dcount(SourceIP) by HostName, SourceIP
  | where NumberOfErrors > 400
  | sort by NumberOfErrors desc
  | extend timestamp = StartTime
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: HostName
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SourceIP
version: 1.0.5
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Jordan Ross
    support:
        tier: Community
    categories:
        domains: [ "Security - Others", "Networking" ]

Stages and Predicates

Stage 1: source

CommonSecurityLog

Stage 2: where

| where DeviceProduct =~ "Wazuh"

Stage 3: where

| where Activity has "Web server 400 error code."

Stage 4: where

| where Message has "403"

Stage 5: extend

| extend HostName=substring(split(DeviceCustomString1,")")[0],1)

Stage 6: summarize

| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), NumberOfErrors = dcount(SourceIP) by HostName, SourceIP

Stage 7: where

| where NumberOfErrors > 400

Stage 8: sort

| sort by NumberOfErrors desc

Stage 9: extend

| extend timestamp = StartTime

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
EndTimesummarize
HostNamesummarize
NumberOfErrorssummarize
SourceIPsummarize
StartTimesummarize
timestampextend

Zscaler - ZPA connections from new IP

#
Status
available
Severity
medium
Time window
14d
Group by
DstUserName, SrcIpAddr
Source
github.com/Azure/Azure-Sentinel

'Detects ZPA connections from new IP.'

MITRE ATT&CK Coverage

Rule Body

id: 24f0779d-3927-403a-aac1-cc8791653606
name: Zscaler - ZPA connections from new IP
description: |
  'Detects ZPA connections from new IP.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: CustomLogsAma
    datatypes:
      - ZPA_CL
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1078
  - T1133
query: |
  let listIPs =
  ZPAEvent 
  | where TimeGenerated > ago(14d)
  | where DvcAction == 'open'
  | summarize ListofIPs = make_set(SrcIpAddr) by DstUserName
  | project ListofIPs;
  ZPAEvent
  | where isnotempty(SrcIpAddr)
  | where SrcIpAddr !in (listIPs)
  | summarize EventCount = count() by DstUserName, SrcIpAddr
  | project-away EventCount
  | extend IPCustomEntity = SrcIpAddr, AccountCustomEntity = DstUserName
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountCustomEntity
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPCustomEntity
version: 1.0.2
kind: Scheduled

Stages and Predicates

Let Binding: listIPs used in Stage 3

let listIPs = ZPAEvent 
| where TimeGenerated > ago(14d)
| where DvcAction == 'open'
| summarize ListofIPs = make_set(SrcIpAddr) by DstUserName
| project ListofIPs;

Stage 1: source

ZPAEvent

Stage 2: where

| where isnotempty(SrcIpAddr)

Stage 3: where

| where SrcIpAddr !in (listIPs)

Stage 4: summarize

| summarize EventCount = count() by DstUserName, SrcIpAddr

Stage 5: project-away

| project-away EventCount

Stage 6: extend

| extend IPCustomEntity = SrcIpAddr, AccountCustomEntity = DstUserName

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
SrcIpAddris_not_null
  • (no value, null check)
field:"src_ip" kind:is_not_null

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
SrcIpAddreqlistIPsexcludes:SrcIpAddr field:"SrcIpAddr" value:"listIPs"

Output Fields

These fields are emitted when the rule matches.

FieldSource
DstUserNamesummarize
SrcIpAddrsummarize
AccountCustomEntityextend
IPCustomEntityextend

Back to all Kusto rules