Detection rules › Kusto

Kusto rules: 2o

1Password - Log Ingestion Failure

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

This will alert when the log ingestion for the OnePasswordEventLogs_CL logs is failing. The alert is based on the healthevents that are created every 5 minutes and will trigger if no logs have been received for 1 hour. Log ingestion troubleshooting: <insert URL> Ref: https://1password.com/ Ref: https://github.com/securehats/

MITRE ATT&CK Coverage

TacticTechniques
Defense Impairment

Rule Body

id: bf9132c7-9d4d-4244-98c7-7d994703c208
name: 1Password - Log Ingestion Failure
version: 1.0.0
kind: Scheduled
description: |-
  This will alert when the log ingestion for the OnePasswordEventLogs_CL logs is failing. The alert is based on the healthevents that are created every 5 minutes and will trigger if no logs have been received for 1 hour.

  Log ingestion troubleshooting:
  <insert URL>

  Ref: https://1password.com/
  Ref: https://github.com/securehats/
severity: Medium
requiredDataConnectors:
  - connectorId: 1Password
    dataTypes:
      - OnePasswordEventLogs_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: Equal
triggerThreshold: 0
tactics:
- DefenseEvasion
relevantTechniques:
- T1562
query: |-
  OnePasswordEventLogs_CL
  | where log_source == "healthevents"
subTechniques:
- T1562.008
suppressionEnabled: false
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: 5h
    matchingMethod: AllEntities
suppressionDuration: 5h
eventGroupingSettings:
  aggregationKind: SingleAlert

Stages and Predicates

Stage 1: source

OnePasswordEventLogs_CL

Stage 2: where

| where log_source == "healthevents"

Indicators

These rows show field, operator, and value matches.

AIShield - Image classification AI Model Evasion high suspicious vulnerability detection

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

'This alert creates an incident when Image classification AI Model Evasion high suspicious, high severity vulnerability detected from the AIShield.'

Rule Body

id: 76c9e83d-c6f9-4270-ad21-761410f9cc6c
name: AIShield - Image classification AI Model Evasion high suspicious vulnerability detection
description: |
  'This alert creates an incident when Image classification AI Model Evasion high suspicious, high severity vulnerability detected from the AIShield.'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: BoschAIShield
    dataTypes:
      - AIShield
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: |
  AIShield
  | where Message has 'Image Classification AI Model Evasion Attack Identified'
  | where Severity =~ 'High'
  | where SuspiciousLevel =~ 'high suspicious attack'
  | extend NTDomain = tostring(split(Computer, '\\')[0]), HostName = tostring(split(Computer, '.')[0])
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: HostName
      - identifier: NTDomain
        columnName: NTDomain
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SourceName
eventGroupingSettings:
  aggregationKind: SingleAlert
alertDetailsOverride:
  alertDisplayNameFormat: AIShield - Image Classification AI Model Evasion high suspicious vulnerability detected.
  alertDescriptionFormat: |
    This query detects Image Classification AI Model Evasion high suspicious, high severity alert from AIShield generated at {{TimeGenerated}}.\n\nPlease check the source for more information and investigate further.
  alertTacticsColumnName: null
  alertSeverityColumnName: Severity
version: 1.0.4
kind: Scheduled

Stages and Predicates

Stage 1: source

AIShield

Stage 2: where

| where Message has 'Image Classification AI Model Evasion Attack Identified'

Stage 3: where

| where Severity =~ 'High'

Stage 4: where

| where SuspiciousLevel =~ 'high suspicious attack'

Stage 5: extend

| extend NTDomain = tostring(split(Computer, '\\')[0]), HostName = tostring(split(Computer, '.')[0])

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
HostNameextend
NTDomainextend

AWS Security Hub - Detect SSM documents public sharing enabled

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

This query detects AWS accounts where public sharing is enabled, using AWS Security Hub control SSM.7 findings. Allowing public sharing of SSM documents can expose automation content and enable unauthorized execution or tampering.

MITRE ATT&CK Coverage

Rule Body

id: 0aa20f8c-b8e4-4a34-a5b8-8b2d9dd7d1c2
name: AWS Security Hub - Detect SSM documents public sharing enabled
description: |
  This query detects AWS accounts where public sharing is enabled, using AWS Security Hub control SSM.7 findings.
  Allowing public sharing of SSM documents can expose automation content and enable unauthorized execution or tampering.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: AWSSecurityHub
    dataTypes:
      - AWSSecurityHubFindings
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Execution
relevantTechniques:
  - T1059
tags:
  - AWS Foundational Security Best Practices v1.0.0
query: |
  AWSSecurityHubFindings
  | where RecordState == "ACTIVE" and ComplianceStatus == "FAILED"
  | where tostring(AwsSecurityFindingGeneratorId) == "security-control/SSM.7"
        or tostring(ComplianceSecurityControlId) == "SSM.7"
  | summarize TimeGenerated = max(TimeGenerated)
      by AwsAccountId, AwsRegion, AwsSecurityFindingTitle, AwsSecurityFindingDescription,
         AwsSecurityFindingId, ComplianceSecurityControlId
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AwsAccountId
      - identifier: CloudAppAccountId
        columnName: AwsAccountId
customDetails:
  ComplianceControlId: ComplianceSecurityControlId
  Region: AwsRegion
  FindingId: AwsSecurityFindingId
alertDetailsOverride:
  alertDisplayNameFormat: "AWS Account {{AwsAccountId}} SSM documents public sharing enabled"
  alertDescriptionFormat: |-
    AWS Account {{AwsAccountId}} has SSM documents with public sharing enabled. Disable public sharing setting to prevent unintended exposure of automation documents.
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/SSM.7"
      or tostring(ComplianceSecurityControlId) == "SSM.7"

Stage 4: summarize

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

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
TimeGeneratedsummarize

AWSCloudTrail - Privilege escalation via CRUD KMS policy

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

Detects inline IAM policy updates that grant broad KMS create, read, update, enable/disable, and delete permissions. This pattern can support key management abuse and indicates possible privilege escalation through expanded cloud role capabilities.

MITRE ATT&CK Coverage

TacticTechniques
Privilege Escalation

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: d7c39e15-997f-49e5-a782-73bf07db8aa5
name: AWSCloudTrail - Privilege escalation via CRUD KMS policy
description: |
  Detects inline IAM policy updates that grant broad KMS create, read, update, enable/disable, and delete
  permissions. This pattern can support key management abuse and indicates possible privilege escalation through
  expanded cloud role capabilities.
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: AWS
    dataTypes:
      - AWSCloudTrail
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - PrivilegeEscalation
relevantTechniques:
  - T1098.003
query: |
  AWSCloudTrail
  | where EventName in ("PutUserPolicy","PutRolePolicy","PutGroupPolicy") and isempty(ErrorCode) and isempty(ErrorMessage)
  | extend PolicyName = tostring(parse_json(RequestParameters).policyName)
  | extend Statement = parse_json(tostring((parse_json(RequestParameters).policyDocument))).Statement
  | mvexpand Statement
  | extend Action = parse_json(Statement).Action , Effect = tostring(parse_json(Statement).Effect), Resource = tostring(parse_json(Statement).Resource), Condition = tostring(parse_json(Statement).Condition)
  | extend Action = tostring(Action)
  | where Effect =~ "Allow" and (Action contains "kms:Create" and (Action contains "kms:Get" or Action contains "kms:Describe")  and (Action contains "kms:Disable" or Action contains "kms:Enable") and Action contains "kms:Delete") and Resource == "*" and Condition == ""
  | 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]), "")
  | distinct TimeGenerated, EventName, PolicyName, SourceIpAddress, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityArn, UserIdentityUserName
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountName
      - identifier: UPNSuffix
        columnName: AccountUPNSuffix
      - identifier: CloudAppAccountId
        columnName: RecipientAccountId
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SourceIpAddress
customDetails:
  PolicyName: PolicyName
  EventName: EventName
  UserIdentityArn: UserIdentityArn
  RecipientAccountId: RecipientAccountId
alertDetailsOverride:
  alertDisplayNameFormat: 'AWS KMS privilege escalation policy update by {{AccountName}}'
  alertDescriptionFormat: 'Detected {{EventName}} Event, updating inline KMS escalation policy {{PolicyName}} in account {{RecipientAccountId}}.'
version: 1.0.2
kind: Scheduled

Stages and Predicates

Stage 1: source

AWSCloudTrail

Stage 2: where

| where EventName in ("PutUserPolicy","PutRolePolicy","PutGroupPolicy") and isempty(ErrorCode) and isempty(ErrorMessage)

Stage 3: extend

| extend PolicyName = tostring(parse_json(RequestParameters).policyName)

Stage 4: extend

| extend Statement = parse_json(tostring((parse_json(RequestParameters).policyDocument))).Statement

Stage 5: mv-expand

| mvexpand Statement

Stage 6: extend

| extend Action = parse_json(Statement).Action , Effect = tostring(parse_json(Statement).Effect), Resource = tostring(parse_json(Statement).Resource), Condition = tostring(parse_json(Statement).Condition)

Stage 7: extend

| extend Action = tostring(Action)

Stage 8: where

| where Effect =~ "Allow" and (Action contains "kms:Create" and (Action contains "kms:Get" or Action contains "kms:Describe")  and (Action contains "kms:Disable" or Action contains "kms:Enable") and Action contains "kms:Delete") and Resource == "*" and Condition == ""

Stage 9: extend (4 consecutive steps)

| 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]), "")

Stage 10: distinct

| distinct TimeGenerated, EventName, PolicyName, SourceIpAddress, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityArn, UserIdentityUserName

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Actioncontains
  • kms:Create
  • kms:Delete
  • kms:Describe
  • kms:Disable
  • kms:Enable
  • kms:Get
field:"Action" kind:contains
Effecteq
  • Allow
field:"Effect" kind:eq value:"Allow"
ErrorCodeis_null
  • (no value, null check)
field:"aws::errorCode" kind:is_null
ErrorMessageis_null
  • (no value, null check)
field:"aws::errorMessage" kind:is_null
EventNamein
  • PutGroupPolicy corpus 12 (kusto 11, panther 1)
  • PutRolePolicy corpus 12 (kusto 11, panther 1)
  • PutUserPolicy corpus 12 (kusto 11, panther 1)
field:"aws::eventName" kind:in
Resourceeq
  • *
field:"Resource" kind:eq value:"*"

Output Fields

These fields are emitted when the rule matches.

FieldSource
PolicyNameextend
Statementextend
Actionextend
Conditionextend
Effectextend
Resourceextend
UserIdentityArnextend
UserNameextend
AccountNameextend
AccountUPNSuffixextend

CiscoISE - Attempt to delete local store logs

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

'Detects when attempt to delete local store logs failed.'

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

id: b6549a28-d61c-476e-b350-4404352ee427
name: CiscoISE - Attempt to delete local store logs
description: |
  'Detects when attempt to delete local store logs failed.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: SyslogAma
    datatypes:
      - Syslog
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1070
query: |
  let lbtime = 5m;
  CiscoISEEvent
  | where TimeGenerated > ago(lbtime)
  | where EventId == '59103'
  | project TimeGenerated, DvcHostname, DvcIpAddr, DstUserName
  | extend HostCustomEntity = DvcHostname
  | extend IPCustomEntity = DvcIpAddr
  | extend AccountCustomEntity = DstUserName
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountCustomEntity
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPCustomEntity
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: HostCustomEntity
version: 1.0.3
kind: Scheduled

Stages and Predicates

Parameters

let lbtime = 5m;

Stage 1: source

CiscoISEEvent

Stage 2: where

| where TimeGenerated > ago(lbtime)

Stage 3: where

| where EventId == '59103'

Stage 4: project

| project TimeGenerated, DvcHostname, DvcIpAddr, DstUserName

Stage 5: extend (3 consecutive steps)

| extend HostCustomEntity = DvcHostname
| extend IPCustomEntity = DvcIpAddr
| extend AccountCustomEntity = DstUserName

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
DstUserNameproject
DvcHostnameproject
DvcIpAddrproject
TimeGeneratedproject
HostCustomEntityextend
IPCustomEntityextend
AccountCustomEntityextend

Cyble Vision Alerts IP Risk Score

#

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

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

'Triggers when the risk score for a monitored IP increases significantly. This may indicate new malicious behavior or updated threat intelligence classification.'

MITRE ATT&CK Coverage

TacticTechniques
Reconnaissance

Rule Body

id: 1e7c8d9f-1d42-42b3-b6ce-12a637e05f16
name: Cyble Vision Alerts IP Risk Score
description: |
  'Triggers when the risk score for a monitored IP increases significantly. This may indicate new malicious behavior or updated threat intelligence classification.'
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:
- T1595
query: |
  Alerts_ip_risk_score  
  | where Service == "ip_risk_score" 
  | extend MappedSeverity = Severity
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
  alertDetailsOverride:
  alertDisplayNameFormat: Risk Score Increased for IP {{IPRS_IP}}
  alertDescriptionFormat: |
    The risk score for IP {{IPRS_IP}} has increased. Previous score {{IPRS_OldScore}}. New score {{IPRS_NewScore}}. This may represent newly observed malicious activity or updated threat intelligence.
customDetails:
  MappedSeverity: Severity
  Status: Status
  AlertID: AlertID
  Service: Service
  IPRS_IP: IPRS_IP
  IPRS_OldScore: IPRS_OldScore
  IPRS_NewScore: IPRS_NewScore
entityMappings:
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: IPRS_IP
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

Alerts_ip_risk_score

Stage 2: where

| where Service == "ip_risk_score"

Stage 3: extend

| extend MappedSeverity = Severity

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Serviceeq
  • ip_risk_score
field:"Service" kind:eq value:"ip_risk_score"

Output Fields

These fields are emitted when the rule matches.

FieldSource
MappedSeverityextend

Cyble Vision Alerts Physical Threat Alert

#

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

'Creates an incident for physical threats identified by Cyble Intelligence such as explosions, safety incidents, riots, or violence. Each alert generates a single incident for SOC evaluation.'

MITRE ATT&CK Coverage

TacticTechniques
Impact

Rule Body

id: 88db8505-1889-46aa-a4e2-4e866262dcb9
name: Cyble Vision Alerts Physical Threat Alert
description: |
  'Creates an incident for physical threats identified by Cyble Intelligence such as explosions, safety incidents, riots, or violence. Each alert generates a single incident for SOC evaluation.'
severity: Low
status: Available
requiredDataConnectors:
- connectorId: CybleVisionAlerts
  dataTypes:
  - CybleVisionAlerts_CL
enabled: true
queryFrequency: 30m
queryPeriod: 30m
triggerOperator: GreaterThan
triggerThreshold: 0
suppressionDuration: PT5M
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics:
- Impact
relevantTechniques:
- T1486
query: |
  Alerts_physical_threats
  | where Service == "physical_threats"
  | extend MappedSeverity = Severity
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
alertDetailsOverride:
  alertDisplayNameFormat: Physical Threat Detected  {{PT_Title_Nested}}
  alertDescriptionFormat: |
    A physical threat incident was identified by Cyble Intelligence.
    Title {{PT_Title_Nested}}
    Threat Type {{PT_ThreatType}}
    Published At {{PT_PublishedAt}}
customDetails:
  MappedSeverity: Severity
  Status: Status
  AlertID: AlertID
  Service: Service
  ThreatTitle: PT_Title_Nested
  ThreatType: PT_ThreatType
  Location: PT_LocationName
  LocationType: PT_LocationType
  Latitude: PT_Latitude
  Longitude: PT_Longitude
entityMappings:
- entityType: URL
  fieldMappings:
  - identifier: Url
    columnName: PT_BaseSourceURL
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

Alerts_physical_threats

Stage 2: where

| where Service == "physical_threats"

Stage 3: extend

| extend MappedSeverity = Severity

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Serviceeq
  • physical_threats
field:"Service" kind:eq value:"physical_threats"

Output Fields

These fields are emitted when the rule matches.

FieldSource
MappedSeverityextend

CYFIRMA - Medium severity File Hash Indicators with Monitor Action and Malware

#

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

"This KQL query retrieves file hash indicators (MD5, SHA1, SHA256) from the CyfirmaIndicators_CL table within the last 5 minutes. It filters records with a confidence score of 80 or higher, containing file hash patterns, a recommended action of 'Monitor', and roles marked as 'Malware'. Extracted hashes and key threat intelligence details are projected for monitoring and investigation."

MITRE ATT&CK Coverage

Rule Body

id: ca16daff-28dd-499d-93fe-0bb232d76d4f
name: CYFIRMA - Medium severity File Hash Indicators with Monitor Action and Malware
description: |
  "This KQL query retrieves file hash indicators (MD5, SHA1, SHA256) from the CyfirmaIndicators_CL table within the last 5 minutes. 
  It filters records with a confidence score of 80 or higher, containing file hash patterns, a recommended action of 'Monitor', and roles marked as 'Malware'. 
  Extracted hashes and key threat intelligence details are projected for monitoring and investigation."
version: 1.0.1
kind: Scheduled
severity: Medium
enabled: false
requiredDataConnectors:
  - connectorId: CyfirmaCyberIntelligenceDC
    dataTypes:
      - CyfirmaIndicators_CL
query: |
  // File Hash Indicators with Monitor Action and Malware
  let timeFrame = 5m;
  CyfirmaIndicators_CL 
  | where  (ConfidenceScore < 80 and ConfidenceScore >= 50)
      and TimeGenerated between (ago(timeFrame) .. now())
      and pattern contains 'file:hashes' and RecommendedActions has 'Monitor' and (Roles contains 'Malware')
  | extend MD5 = extract(@"file:hashes\.md5\s*=\s*'([a-fA-F0-9]{32})'", 1, pattern)
  | extend SHA1 = extract(@"file:hashes\.'SHA-1'\s*=\s*'([a-fA-F0-9]{40})'", 1, pattern)
  | extend SHA256 = extract(@"file:hashes\.'SHA-256'\s*=\s*'([a-fA-F0-9]{64})'", 1, pattern)
  | extend
      Algo_MD5='md5',
      Algo_SHA1= 'SHA1',
      Algo_SHA256='SHA256',
      ProviderName = 'CYFIRMA',
      ProductName = 'DeCYFIR/DeTCT'
  | project  
      MD5,
      Algo_MD5,
      SHA1,
      Algo_SHA1,
      SHA256,
      Algo_SHA256,
      ThreatActors,
      Sources,
      RecommendedActions,
      Roles,
      Country,
      name,
      Description,
      ConfidenceScore,
      SecurityVendors,
      IndicatorID,
      created,
      modified,
      valid_from,
      Tags,
      ThreatType,
      TimeGenerated,
      ProductName,
      ProviderName
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: GreaterThan
triggerThreshold: 0
suppressionDuration: 5m
suppressionEnabled: true
tactics:
  - DefenseEvasion
  - InitialAccess
  - Impact
  - Execution
relevantTechniques:
  - T1027
  - T1486
  - T1204
  - T1485
  - T1218
  - T1566.001
alertDetailsOverride:
  alertDisplayNameFormat: "High-Confidence File Hash Indicators with Monitor Action and Malware - {{name}} "
  alertDescriptionFormat: "{{Description}} - {{name}} "
  alertDynamicProperties:
    - alertProperty: ProviderName
      value: ProviderName
    - alertProperty: ProductName
      value: ProductName
customDetails:
  ThreatActors: ThreatActors
  Sources: Sources
  RecommendedActions: RecommendedActions
  Roles: Roles
  Country: Country
  Description: Description
  ConfidenceScore: ConfidenceScore
  SecurityVendors: SecurityVendors
  IndicatorID: IndicatorID
  created: created
  modified: modified
  valid_from: valid_from
  Tags: Tags
  ThreatType: ThreatType
  TimeGenerated: TimeGenerated
entityMappings:
  - entityType: FileHash
    fieldMappings:
      - identifier: Algorithm
        columnName: Algo_MD5
      - identifier: Value
        columnName: MD5
  - entityType: FileHash
    fieldMappings:
      - identifier: Algorithm
        columnName: Algo_SHA1
      - identifier: Value
        columnName: SHA1
  - entityType: FileHash
    fieldMappings:
      - identifier: Algorithm
        columnName: Algo_SHA256
      - identifier: Value
        columnName: SHA256
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
eventGroupingSettings:
  aggregationKind: AlertPerResult

Stages and Predicates

Parameters

let timeFrame = 5m;

Stage 1: source

CyfirmaIndicators_CL

Stage 2: where

| where  (ConfidenceScore < 80 and ConfidenceScore >= 50)
    and TimeGenerated between (ago(timeFrame) .. now())
    and pattern contains 'file:hashes' and RecommendedActions has 'Monitor' and (Roles contains 'Malware')

Stage 3: extend (4 consecutive steps)

| extend MD5 = extract(@"file:hashes\.md5\s*=\s*'([a-fA-F0-9]{32})'", 1, pattern)
| extend SHA1 = extract(@"file:hashes\.'SHA-1'\s*=\s*'([a-fA-F0-9]{40})'", 1, pattern)
| extend SHA256 = extract(@"file:hashes\.'SHA-256'\s*=\s*'([a-fA-F0-9]{64})'", 1, pattern)
| extend
    Algo_MD5='md5',
    Algo_SHA1= 'SHA1',
    Algo_SHA256='SHA256',
    ProviderName = 'CYFIRMA',
    ProductName = 'DeCYFIR/DeTCT'

Stage 4: project

| project  
    MD5,
    Algo_MD5,
    SHA1,
    Algo_SHA1,
    SHA256,
    Algo_SHA256,
    ThreatActors,
    Sources,
    RecommendedActions,
    Roles,
    Country,
    name,
    Description,
    ConfidenceScore,
    SecurityVendors,
    IndicatorID,
    created,
    modified,
    valid_from,
    Tags,
    ThreatType,
    TimeGenerated,
    ProductName,
    ProviderName

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
Algo_MD5project
Algo_SHA1project
Algo_SHA256project
ConfidenceScoreproject
Countryproject
Descriptionproject
IndicatorIDproject
MD5project
ProductNameproject
ProviderNameproject
RecommendedActionsproject
Rolesproject
SHA1project
SHA256project
SecurityVendorsproject
Sourcesproject
Tagsproject
ThreatActorsproject
ThreatTypeproject
TimeGeneratedproject
createdproject
modifiedproject
nameproject
valid_fromproject

New executable via Office FileUploaded Operation

#
Status
available
Severity
low
Time window
8d
Group by
ClientIP, OfficeWorkload, Operation, RecordType, SiteUrlUserFolder, Site_Url, SourceFileName, SourceRelativeUrl, UserId, UserIdDiffThanUserFolder, UserIdUserFolderFormat, UserKey, UserType
Source
github.com/Azure/Azure-Sentinel

Identifies when executable file types are uploaded to Office services such as SharePoint and OneDrive. List currently includes 'exe', 'inf', 'gzip', 'cmd', 'bat' file extensions. Additionally, identifies when a given user is uploading these files to another users workspace. This may be indication of a staging location for malware or other malicious activity.

MITRE ATT&CK Coverage

TacticTechniques
Lateral Movement
Command & Control

Telemetry Coverage

PlatformRecord / event type
Microsoft 365FileUploaded

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: d722831e-88f5-4e25-b106-4ef6e29f8c13
name: New executable via Office FileUploaded Operation
description: |
  'Identifies when executable file types are uploaded to Office services such as SharePoint and OneDrive.
  List currently includes 'exe', 'inf', 'gzip', 'cmd', 'bat' file extensions.
  Additionally, identifies when a given user is uploading these files to another users workspace.
  This may be indication of a staging location for malware or other malicious activity.'
severity: Low
status: Available
requiredDataConnectors:
  - connectorId: Office365
    dataTypes:
      - OfficeActivity (SharePoint) 
queryFrequency: 1d
queryPeriod: 8d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CommandAndControl
  - LateralMovement
relevantTechniques:
  - T1105
  - T1570
query: |
  // a threshold can be enabled, see commented line below for PrevSeenCount
  let threshold = 2;
  let uploadOp = 'FileUploaded';
  // Extensions that are interesting. Add/Remove to this list as you see fit
  let execExt = dynamic(['exe', 'inf', 'gzip', 'cmd', 'bat']);
  let starttime = 8d;
  let endtime = 1d;
  OfficeActivity | where TimeGenerated >= ago(endtime)
  // Limited to File Uploads due to potential noise, comment out the Operation statement below to include any operation type
  // Additional, but potentially noisy operation types that include Uploads and Downloads can be included by adding the following - Operation contains "upload" or Operation contains "download"
  | where Operation =~ uploadOp
  | where SourceFileExtension has_any (execExt)
  | project TimeGenerated, OfficeId, OfficeWorkload, RecordType, Operation, UserType, UserKey, UserId, ClientIP, UserAgent, Site_Url, SourceRelativeUrl, SourceFileName
  | join kind= leftanti (
  OfficeActivity | where TimeGenerated between (ago(starttime) .. ago(endtime))
  | where Operation =~ uploadOp
  | where SourceFileExtension has_any (execExt)
  | summarize SourceRelativeUrl = make_set(SourceRelativeUrl, 100000), UserId = make_set(UserId, 100000) , PrevSeenCount = count() by SourceFileName
  // To exclude previous matches when only above a specific count, change threshold above and uncomment the line below
  //| where PrevSeenCount > threshold
  | mvexpand SourceRelativeUrl, UserId
  | extend SourceRelativeUrl = tostring(SourceRelativeUrl), UserId = tostring(UserId)
  ) on SourceFileName, SourceRelativeUrl, UserId
  | extend SiteUrlUserFolder = tolower(split(Site_Url, '/')[-2])
  | extend UserIdUserFolderFormat = tolower(replace_regex(UserId, '@|\\.', '_'))
  // identify when UserId is not a match to the specific site url personal folder reference
  | extend UserIdDiffThanUserFolder = iff(Site_Url has '/personal/' and SiteUrlUserFolder != UserIdUserFolderFormat, true , false )
  | summarize TimeGenerated = make_list(TimeGenerated, 100000), StartTime = min(TimeGenerated), EndTime = max(TimeGenerated),
  UserAgents = make_list(UserAgent, 100000), OfficeIds = make_list(OfficeId, 100000), SourceRelativeUrls = make_list(SourceRelativeUrl, 100000), FileNames = make_list(SourceFileName, 100000)
  by OfficeWorkload, RecordType, Operation, UserType, UserKey, UserId, ClientIP, Site_Url, SiteUrlUserFolder, UserIdUserFolderFormat, UserIdDiffThanUserFolder
  | extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1])
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: UserId
      - identifier: Name
        columnName: AccountName
      - identifier: UPNSuffix
        columnName: AccountUPNSuffix
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: ClientIP
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: Site_Url
  - entityType: File
    fieldMappings:
      - identifier: Name
        columnName: FileNames       
version: 2.0.5
kind: Scheduled

Stages and Predicates

Parameters

let threshold = 2;
let uploadOp = 'FileUploaded';
let execExt = dynamic(['exe', 'inf', 'gzip', 'cmd', 'bat']);
let starttime = 8d;
let endtime = 1d;

Stage 1: source

OfficeActivity

Stage 2: where

| where TimeGenerated >= ago(endtime)

Stage 3: where

| where Operation =~ uploadOp

Stage 4: where

| where SourceFileExtension has_any (execExt)

Stage 5: project

| project TimeGenerated, OfficeId, OfficeWorkload, RecordType, Operation, UserType, UserKey, UserId, ClientIP, UserAgent, Site_Url, SourceRelativeUrl, SourceFileName

Stage 6: join (negated)

join kind=leftanti (OfficeActivity) on SourceFileName, SourceRelativeUrl, UserId

Stage 7: extend (3 consecutive steps)

extend SiteUrlUserFolder, UserIdDiffThanUserFolder, UserIdUserFolderFormat

Stage 8: summarize

summarize EndTime, FileNames, OfficeIds, SourceRelativeUrls, StartTime, TimeGenerated, UserAgents by OfficeWorkload, RecordType, Operation, UserType, UserKey, UserId, ClientIP, Site_Url, SiteUrlUserFolder, UserIdUserFolderFormat, UserIdDiffThanUserFolder

Stage 9: extend

extend AccountName, AccountUPNSuffix

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Operationeq
  • FileUploaded
field:"Operation" kind:eq value:"FileUploaded"
SourceFileExtensionmatch
  • bat transforms: term
  • cmd transforms: term
  • exe transforms: term
  • gzip transforms: term
  • inf transforms: term
field:"SourceFileExtension" kind:match

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
OperationeqFileUploadedexcludes:Operation field:"Operation" value:"FileUploaded"
SourceFileExtensionmatchexe, inf, gzip, cmd, batexcludes:SourceFileExtension

Output Fields

These fields are emitted when the rule matches.

FieldSource
ClientIPsummarize
EndTimesummarize
FileNamessummarize
OfficeIdssummarize
OfficeWorkloadsummarize
Operationsummarize
RecordTypesummarize
SiteUrlUserFoldersummarize
Site_Urlsummarize
SourceRelativeUrlssummarize
StartTimesummarize
TimeGeneratedsummarize
UserAgentssummarize
UserIdsummarize
UserIdDiffThanUserFoldersummarize
UserIdUserFolderFormatsummarize
UserKeysummarize
UserTypesummarize
AccountNameextend
AccountUPNSuffixextend

Palo Alto Prisma Cloud - Network ACL allow all outbound traffic

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

'Detects network ACLs with outbound rule to allow all traffic.'

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

id: 4264e133-eec2-438f-af85-05e869308f94
name: Palo Alto Prisma Cloud - Network ACL allow all outbound traffic
description: |
  'Detects network ACLs with outbound rule to allow all traffic.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: PaloAltoPrismaCloud
    dataTypes:
      - PaloAltoPrismaCloud
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1133
query: |
  PaloAltoPrismaCloud
  | where Reason =~ 'NEW_ALERT'
  | where Status =~ 'open'
  | where AlertMessage has 'Network ACLs with Outbound rule to allow All Traffic'
  | extend AccountCustomEntity = UserName
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountCustomEntity
version: 1.0.1
kind: Scheduled

Stages and Predicates

Stage 1: source

PaloAltoPrismaCloud

Stage 2: where

| where Reason =~ 'NEW_ALERT'

Stage 3: where

| where Status =~ 'open'

Stage 4: where

| where AlertMessage has 'Network ACLs with Outbound rule to allow All Traffic'

Stage 5: extend

| extend AccountCustomEntity = UserName

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
AccountCustomEntityextend

SAP LogServ - HANA DB - Assign Admin Authorizations

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

Identifies admin privileges/roles assignment. Source Action: Assign a user with any Admin role / privileges. Data Sources: SAP LogServ - HANA DB (Syslog)

MITRE ATT&CK Coverage

TacticTechniques
Privilege EscalationNo specific technique

Rule Body

id: 4981469b-8618-43a7-b44c-5744594fa494
kind: Scheduled
name: SAP LogServ - HANA DB - Assign Admin Authorizations
description: |
  Identifies admin privileges/roles assignment.
  
  Source Action: Assign a user with any Admin role / privileges.
  
  *Data Sources: SAP LogServ - HANA DB (Syslog)*
severity: High
status: Available
requiredDataConnectors:
  - connectorId: SAPLogServ
    dataTypes:
      - Syslog
queryFrequency: 10m
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - PrivilegeEscalation
relevantTechniques: []
query: |
  let AuditTimeAgo = 60m;
  Syslog
  | where TimeGenerated >= ago(AuditTimeAgo)
  | where SourceSystem == "HANADB" and CollectorHostName == "SAPLogServ"
  | extend raw_split = split(SyslogMessage, ";")
  | extend
    event_timestamp__col_0 = tostring(raw_split[0]), 
    service_name__col_1 = tostring(raw_split[1]), 
    hostname__col_2 = tostring(raw_split[2]), 
    sid__col_3 = tostring(raw_split[3]), 
    instance_number__col_4 = tostring(raw_split[4]), 
    port_number__col_5 = tostring(raw_split[5]), 
    database_name__col_6 = tostring(raw_split[6]), 
    client_ip_address__col_7 = tostring(raw_split[7]), 
    client_name__col_8 = tostring(raw_split[8]), 
    client_process_id__col_9 = tostring(raw_split[9]), 
    client_port_number__col_10 = tostring(raw_split[10]), 
    policy_name__col_11 = tostring(raw_split[11]), 
    audit_level__col_12 = tostring(raw_split[12]), 
    audit_action__col_13 = tostring(raw_split[13]), 
    session_user__col_14 = tostring(raw_split[14]), 
    target_schema__col_15 = tostring(raw_split[15]), 
    target_object__col_16 = tostring(raw_split[16]), 
    privilege_name__col_17 = tostring(raw_split[17]), 
    grantable__col_18 = tostring(raw_split[18]), 
    role_name__col_19 = tostring(raw_split[19]), 
    target_principal__col_20 = tostring(raw_split[20]), 
    action_status__col_21 = tostring(raw_split[21]), 
    component__col_22 = tostring(raw_split[22]), 
    section__col_23 = tostring(raw_split[23]), 
    parameter__col_24 = tostring(raw_split[24]), 
    old_value__col_25 = tostring(raw_split[25]), 
    new_value__col_26 = tostring(raw_split[26]), 
    comment__col_27 = tostring(raw_split[27]), 
    executed_statement__col_28 = tostring(raw_split[28]), 
    session_id__col_29 = tostring(raw_split[29]), 
    application_user_name__col_30 = tostring(raw_split[30]), 
    role_schema_name__col_31 = tostring(raw_split[31]), 
    grantee_schema_name__col_32 = tostring(raw_split[32]), 
    origin_database_name__col_33 = tostring(raw_split[33]), 
    origin_user_name__col_34 = tostring(raw_split[34]), 
    xs_application_user_name__col_35 = tostring(raw_split[35]), 
    application_name__col_36 = tostring(raw_split[36]), 
    statement_user_name__col_37 = tostring(raw_split[37]), 
    create_time__col_38 = tostring(raw_split[38]), 
    xsa_message_ip__col_39 = tostring(raw_split[39]), 
    xsa_tenant__col_40 = tostring(raw_split[40]), 
    xsa_uuid__col_41 = tostring(raw_split[41]), 
    xsa_channel__col_42 = tostring(raw_split[42]), 
    xsa_attachment_id__col_43 = tostring(raw_split[43]), 
    xsa_attachment_name__col_44 = tostring(raw_split[44]), 
    xsa_organization_id__col_45 = tostring(raw_split[45]), 
    xsa_space_id__col_46 = tostring(raw_split[46]), 
    xsa_instance_id__col_47 = tostring(raw_split[47]), 
    xsa_binding_id__col_48 = tostring(raw_split[48]), 
    xsa_object__col_49 = tostring(raw_split[49]), 
    xsa_data_subject__col_50 = tostring(raw_split[50])
  | where 
    audit_action__col_13 =~ "GRANT PRIVILEGE"
    and privilege_name__col_17 contains "ADMIN"
  | extend AlertRuleUniqueName = 'hanadb-assignadminauthorizations-logserv'
eventGroupingSettings:
  aggregationKind: SingleAlert
entityMappings:
  - entityType: CloudApplication
    fieldMappings:
      - identifier: AppId
        columnName: sid__col_3
      - identifier: InstanceName
        columnName: database_name__col_6
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: hostname__col_2
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: client_ip_address__col_7
alertDetailsOverride:
  alertDisplayNameFormat: 'SAP LogServ - HANA DB - Assign Admin Authorizations'
  alertDescriptionFormat: |
    {{comment__col_27}}
customDetails:
  SAP_User: session_user__col_14
version: 1.0.1

Stages and Predicates

Parameters

let AuditTimeAgo = 60m;

Stage 1: source

Syslog

Stage 2: where

| where TimeGenerated >= ago(AuditTimeAgo)

Stage 3: where

| where SourceSystem == "HANADB" and CollectorHostName == "SAPLogServ"

Stage 4: extend

| extend raw_split = split(SyslogMessage, ";")

Stage 5: extend

| extend
  event_timestamp__col_0 = tostring(raw_split[0]), 
  service_name__col_1 = tostring(raw_split[1]), 
  hostname__col_2 = tostring(raw_split[2]), 
  sid__col_3 = tostring(raw_split[3]), 
  instance_number__col_4 = tostring(raw_split[4]), 
  port_number__col_5 = tostring(raw_split[5]), 
  database_name__col_6 = tostring(raw_split[6]), 
  client_ip_address__col_7 = tostring(raw_split[7]), 
  client_name__col_8 = tostring(raw_split[8]), 
  client_process_id__col_9 = tostring(raw_split[9]), 
  client_port_number__col_10 = tostring(raw_split[10]), 
  policy_name__col_11 = tostring(raw_split[11]), 
  audit_level__col_12 = tostring(raw_split[12]), 
  audit_action__col_13 = tostring(raw_split[13]), 
  session_user__col_14 = tostring(raw_split[14]), 
  target_schema__col_15 = tostring(raw_split[15]), 
  target_object__col_16 = tostring(raw_split[16]), 
  privilege_name__col_17 = tostring(raw_split[17]), 
  grantable__col_18 = tostring(raw_split[18]), 
  role_name__col_19 = tostring(raw_split[19]), 
  target_principal__col_20 = tostring(raw_split[20]), 
  action_status__col_21 = tostring(raw_split[21]), 
  component__col_22 = tostring(raw_split[22]), 
  section__col_23 = tostring(raw_split[23]), 
  parameter__col_24 = tostring(raw_split[24]), 
  old_value__col_25 = tostring(raw_split[25]), 
  new_value__col_26 = tostring(raw_split[26]), 
  comment__col_27 = tostring(raw_split[27]), 
  executed_statement__col_28 = tostring(raw_split[28]), 
  session_id__col_29 = tostring(raw_split[29]), 
  application_user_name__col_30 = tostring(raw_split[30]), 
  role_schema_name__col_31 = tostring(raw_split[31]), 
  grantee_schema_name__col_32 = tostring(raw_split[32]), 
  origin_database_name__col_33 = tostring(raw_split[33]), 
  origin_user_name__col_34 = tostring(raw_split[34]), 
  xs_application_user_name__col_35 = tostring(raw_split[35]), 
  application_name__col_36 = tostring(raw_split[36]), 
  statement_user_name__col_37 = tostring(raw_split[37]), 
  create_time__col_38 = tostring(raw_split[38]), 
  xsa_message_ip__col_39 = tostring(raw_split[39]), 
  xsa_tenant__col_40 = tostring(raw_split[40]), 
  xsa_uuid__col_41 = tostring(raw_split[41]), 
  xsa_channel__col_42 = tostring(raw_split[42]), 
  xsa_attachment_id__col_43 = tostring(raw_split[43]), 
  xsa_attachment_name__col_44 = tostring(raw_split[44]), 
  xsa_organization_id__col_45 = tostring(raw_split[45]), 
  xsa_space_id__col_46 = tostring(raw_split[46]), 
  xsa_instance_id__col_47 = tostring(raw_split[47]), 
  xsa_binding_id__col_48 = tostring(raw_split[48]), 
  xsa_object__col_49 = tostring(raw_split[49]), 
  xsa_data_subject__col_50 = tostring(raw_split[50])

Stage 6: where

| where 
  audit_action__col_13 =~ "GRANT PRIVILEGE"
  and privilege_name__col_17 contains "ADMIN"

Stage 7: extend

| extend AlertRuleUniqueName = 'hanadb-assignadminauthorizations-logserv'

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
raw_splitextend
action_status__col_21extend
application_name__col_36extend
application_user_name__col_30extend
audit_action__col_13extend
audit_level__col_12extend
client_ip_address__col_7extend
client_name__col_8extend
client_port_number__col_10extend
client_process_id__col_9extend
comment__col_27extend
component__col_22extend
create_time__col_38extend
database_name__col_6extend
event_timestamp__col_0extend
executed_statement__col_28extend
grantable__col_18extend
grantee_schema_name__col_32extend
hostname__col_2extend
instance_number__col_4extend
new_value__col_26extend
old_value__col_25extend
origin_database_name__col_33extend
origin_user_name__col_34extend
parameter__col_24extend
policy_name__col_11extend
port_number__col_5extend
privilege_name__col_17extend
role_name__col_19extend
role_schema_name__col_31extend
section__col_23extend
service_name__col_1extend
session_id__col_29extend
session_user__col_14extend
sid__col_3extend
statement_user_name__col_37extend
target_object__col_16extend
target_principal__col_20extend
target_schema__col_15extend
xs_application_user_name__col_35extend
xsa_attachment_id__col_43extend
xsa_attachment_name__col_44extend
xsa_binding_id__col_48extend
xsa_channel__col_42extend
xsa_data_subject__col_50extend
xsa_instance_id__col_47extend
xsa_message_ip__col_39extend
xsa_object__col_49extend
xsa_organization_id__col_45extend
xsa_space_id__col_46extend
xsa_tenant__col_40extend
xsa_uuid__col_41extend
AlertRuleUniqueNameextend

Semperis DSP Mimikatz's DCShadow Alert

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

'Mimikatz's DCShadow switch allows a user who has compromised an AD domain, to inject arbitrary changes into AD using a "fake" domain controller. These changes bypass the security event log and can't be spotted using normal AD tools. This rule looks for evidence that a machine has been used in this capacity.'

MITRE ATT&CK Coverage

TacticTechniques
Defense Impairment

Rule Body

id: 1a6d0a49-64b3-4ca1-96c3-f154c16c218c
name: Semperis DSP Mimikatz's DCShadow Alert
description: |
  'Mimikatz's DCShadow switch allows a user who has compromised an AD domain, to inject arbitrary changes into AD using a "fake" domain controller. These changes bypass the security event log and can't be spotted using normal AD tools. This rule looks for evidence that a machine has been used in this capacity.'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: SemperisDSP
    dataTypes:
      - dsp_parser
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1207
query: |
  dsp_parser
  | where EventID == 9212
  | where SecurityIndicatorName == "Evidence of Mimikatz DCShadow attack"
  | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
version: 2.0.7
kind: Scheduled

Stages and Predicates

Stage 1: source

dsp_parser

Stage 2: where

| where EventID == 9212

Stage 3: where

| where SecurityIndicatorName == "Evidence of Mimikatz DCShadow attack"

Stage 4: extend

| extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
DnsDomainextend
HostNameextend

T1566.002 Spearphishing Link - Rare URL Clicks

#

UniFi Site Manager: New WAN issue index recorded

#
Status
available
Severity
medium
Time window
45m
Group by
SiteName, siteId_s
Source
github.com/Azure/Azure-Sentinel

Identifies a newly-recorded UniFi WAN issue index. May indicate ISP problems, hardware fault, or active denial-of-service pressure on the gateway.

MITRE ATT&CK Coverage

TacticTechniques
Impact

Rule Body

id: 17d09e1b-8a3f-776b-6981-dbe2cc74d097
name: "UniFi Site Manager: New WAN issue index recorded"
description: |
  Identifies a newly-recorded UniFi WAN issue index. May indicate ISP problems, hardware fault, or active denial-of-service pressure on the gateway.
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: UniFiSiteManagerConnectorDefinition
    dataTypes:
      - Unifi_SiteManager_Sites_CL
queryFrequency: 15m
queryPeriod: 45m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Impact
relevantTechniques:
  - T1498
subTechniques:
  - T1498.001
query: |
  // UniFi reports a monotonically-rising wanIssues.count rather than discrete events.
  // Detect a NEW occurrence by checking whether the per-site max(count) has grown
  // in the most recent 15-min window vs the prior 15-min window.
  Unifi_SiteManager_Sites_CL
  | where TimeGenerated > ago(45m)
  | extend siteId_s = tostring(SiteId)
  | where isnotempty(tostring(SiteStatistics.wans.WAN))
  | mv-expand issue = todynamic(tostring(SiteStatistics.wans.WAN.wanIssues))
  | extend issueCount = tolong(issue.count), idx = tolong(issue.index)
  | summarize
      PrevMaxCount = maxif(issueCount, TimeGenerated < ago(15m)),
      CurrentMaxCount = maxif(issueCount, TimeGenerated >= ago(15m)),
      LatestIndex = maxif(idx, TimeGenerated >= ago(15m))
      by siteId_s, SiteName
  | extend PrevMaxCount = coalesce(PrevMaxCount, tolong(0))
  | where CurrentMaxCount > PrevMaxCount
  | extend
      TimeGenerated = now(),
      Delta = CurrentMaxCount - PrevMaxCount,
      Activity = strcat('New WAN issue: count rose from ', PrevMaxCount, ' to ', CurrentMaxCount)
  | project TimeGenerated, SiteId = siteId_s, SiteName, Activity, IssueIndex = LatestIndex, PrevMaxCount, CurrentMaxCount, Delta
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: SiteId
      - identifier: DnsDomain
        columnName: SiteName
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
kind: Scheduled
version: 1.0.1

Stages and Predicates

Stage 1: source

Unifi_SiteManager_Sites_CL

Stage 2: where

| where TimeGenerated > ago(45m)

Stage 3: extend

| extend siteId_s = tostring(SiteId)

Stage 4: where

| where isnotempty(tostring(SiteStatistics.wans.WAN))

Stage 5: mv-expand

| mv-expand issue = todynamic(tostring(SiteStatistics.wans.WAN.wanIssues))

Stage 6: extend

| extend issueCount = tolong(issue.count), idx = tolong(issue.index)

Stage 7: summarize

| summarize
    PrevMaxCount = maxif(issueCount, TimeGenerated < ago(15m)),
    CurrentMaxCount = maxif(issueCount, TimeGenerated >= ago(15m)),
    LatestIndex = maxif(idx, TimeGenerated >= ago(15m))
    by siteId_s, SiteName

Stage 8: extend

| extend PrevMaxCount = coalesce(PrevMaxCount, tolong(0))

Stage 9: where

| where CurrentMaxCount > PrevMaxCount

Stage 10: extend

| extend
    TimeGenerated = now(),
    Delta = CurrentMaxCount - PrevMaxCount,
    Activity = strcat('New WAN issue: count rose from ', PrevMaxCount, ' to ', CurrentMaxCount)

Stage 11: project

| project TimeGenerated, SiteId = siteId_s, SiteName, Activity, IssueIndex = LatestIndex, PrevMaxCount, CurrentMaxCount, Delta

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
SiteStatistics.wans.WANis_not_null
  • (no value, null check)
field:"SiteStatistics.wans.WAN" kind:is_not_null

Output Fields

These fields are emitted when the rule matches.

FieldSource
Activityproject
CurrentMaxCountproject
Deltaproject
IssueIndexproject
PrevMaxCountproject
SiteIdproject
SiteNameproject
TimeGeneratedproject

User agent search for log4j exploitation attempt

#
Status
available
Severity
high
Time window
1d
Group by
Account, AppDisplayName, ClientAppUsed, DstIpAddr, EventName, HttpStatus, HttpUserAgent, Operation, ResourceId, ResourceType, SourceIP, Type, Url, UserAgent, csMethod, ruleName_s, sSiteName
Source
github.com/Azure/Azure-Sentinel

This query uses various log sources having user agent data to look for log4j CVE-2021-44228 exploitation attempt based on user agent pattern. Log4j is an open-source Apache logging library that is used in many Java-based applications. The regex and the string matching look for the most common attacks. This might not be comprehensive to detect every possible user agent variation. Reference: https://msrc-blog.microsoft.com/2021/12/11/microsofts-response-to-cve-2021-44228-apache-log4j2/

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

id: 29283b22-a1c0-4d16-b0a9-3460b655a46a
name: User agent search for log4j exploitation attempt
description: |
  'This query uses various log sources having user agent data to look for log4j CVE-2021-44228 exploitation attempt based on user agent pattern.
  Log4j is an open-source Apache logging library that is used in many Java-based applications. The regex and the string matching look for the most common attacks. This might not be comprehensive to detect every possible user agent variation.
   Reference: https://msrc-blog.microsoft.com/2021/12/11/microsofts-response-to-cve-2021-44228-apache-log4j2/'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: SquidProxy
    dataTypes:
      - SquidProxy_CL
  - connectorId: Zscaler
    dataTypes:
      - CommonSecurityLog
  - connectorId: WAF
    dataTypes:
      - AzureDiagnostics
  - connectorId: Office365
    dataTypes:
      - OfficeActivity
  - connectorId: AzureActiveDirectory
    dataTypes:
      - SigninLogs
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AADNonInteractiveUserSignInLogs
  - connectorId: AWS
    dataTypes:
      - AWSCloudTrail
  - connectorId: AzureMonitor(IIS)
    dataTypes:
      - W3CIISLog
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
relevantTechniques:
  - T1190
tags:
    - log4j
    - log4shell
    - CVE2021-44228
    - Schema: ASimWebSession
    - SchemaVersion: 0.2.1
    - Schema: ASimNetworkSessions
    - SchemaVersion: 0.2.1
query: |
  let UserAgentString = dynamic (["${jndi:ldap:/", "${jndi:rmi:/", "${jndi:ldaps:/", "${jndi:dns:/", "${jndi:iiop:/","${jndi:","${jndi:nds:/","${jndi:corba/"]);
  let UARegexMinimalString=dynamic(['{','%7b', '%7B']);
  let UARegex = @'(\\$|%24)(\\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\\$|%24|}|%7D)';
  (union isfuzzy=true
  (OfficeActivity
  | where UserAgent has_any (UserAgentString) or UserAgent matches regex UARegex
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent, SourceIP = ClientIP, Account = UserId, Type, Operation
  ),
  (AzureDiagnostics
  | where Category in ("FrontdoorWebApplicationFirewallLog", "FrontdoorAccessLog", "ApplicationGatewayFirewallLog", "ApplicationGatewayAccessLog")
  | where userAgent_s has_any (UserAgentString) or userAgent_s matches regex UARegex
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent = userAgent_s, SourceIP = column_ifexists("clientIp_s",clientIP_s), Type, column_ifexists("originalHost_s",host_s), Url = requestUri_s, HttpStatus = column_ifexists("httpStatusDetails_s",httpStatus_d), column_ifexists("trackingReference_s",transactionId_g), ruleName_s, ResourceType, ResourceId
  ),
  (
  W3CIISLog
  | where csUserAgent has_any (UserAgentString) or csUserAgent matches regex UARegex
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent = csUserAgent, SourceIP = cIP, Account = csUserName, Type, sSiteName, csMethod, Url = csUriStem
  ),
  (
  AWSCloudTrail
  | where UserAgent has_any (UserAgentString) or UserAgent matches regex UARegex
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent, SourceIP = SourceIpAddress, Account = UserIdentityUserName, Type, EventName
  ),
  (SigninLogs
  | where UserAgent has_any (UserAgentString) or UserAgent matches regex UARegex
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent, SourceIP = IPAddress, Account = UserPrincipalName, Type, Operation = OperationName, tostring(LocationDetails), tostring(DeviceDetail),    AppDisplayName, ClientAppUsed
  ),
  (AADNonInteractiveUserSignInLogs 
  | where UserAgent has_any (UserAgentString) or UserAgent matches regex UARegex
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent, SourceIP = IPAddress, Account = UserPrincipalName, Type, Operation = OperationName, tostring(LocationDetails), tostring(DeviceDetail), AppDisplayName, ClientAppUsed
  ),
  (_Im_WebSession (httpuseragent_has_any=array_concat(UserAgentString,UARegexMinimalString))
  | where HttpUserAgent has_any (UserAgentString) or HttpUserAgent matches regex UARegex
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by HttpUserAgent, SourceIP = SrcIpAddr, DstIpAddr, Account = SrcUsername, Url, Type
  )
  )
entityMappings:
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: Url
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SourceIP
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: Account
version: 1.0.9
kind: Scheduled

Stages and Predicates

Parameters

let UserAgentString = dynamic (["${jndi:ldap:/", "${jndi:rmi:/", "${jndi:ldaps:/", "${jndi:dns:/", "${jndi:iiop:/","${jndi:","${jndi:nds:/","${jndi:corba/"]);
let UARegexMinimalString = dynamic(['{','%7b', '%7B']);

Let Binding: UARegex

let UARegex = @'(\\$|%24)(\\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\\$|%24|}|%7D)';

Union isfuzzy=true (7 Sources)

Each leg below queries one source; the rule matches if any leg does. Sources: OfficeActivity, AzureDiagnostics, W3CIISLog, AWSCloudTrail, SigninLogs, AADNonInteractiveUserSignInLogs, _Im_WebSession

Leg 1: OfficeActivity

OfficeActivity
| where UserAgent has_any (UserAgentString) or UserAgent matches regex UARegex
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent, SourceIP = ClientIP, Account = UserId, Type, Operation

Leg 2: AzureDiagnostics

AzureDiagnostics
| where Category in ("FrontdoorWebApplicationFirewallLog", "FrontdoorAccessLog", "ApplicationGatewayFirewallLog", "ApplicationGatewayAccessLog")
| where userAgent_s has_any (UserAgentString) or userAgent_s matches regex UARegex
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent = userAgent_s, SourceIP = column_ifexists("clientIp_s",clientIP_s), Type, column_ifexists("originalHost_s",host_s), Url = requestUri_s, HttpStatus = column_ifexists("httpStatusDetails_s",httpStatus_d), column_ifexists("trackingReference_s",transactionId_g), ruleName_s, ResourceType, ResourceId

Leg 3: W3CIISLog

W3CIISLog
| where csUserAgent has_any (UserAgentString) or csUserAgent matches regex UARegex
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent = csUserAgent, SourceIP = cIP, Account = csUserName, Type, sSiteName, csMethod, Url = csUriStem

Leg 4: AWSCloudTrail

AWSCloudTrail
| where UserAgent has_any (UserAgentString) or UserAgent matches regex UARegex
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent, SourceIP = SourceIpAddress, Account = UserIdentityUserName, Type, EventName

Leg 5: SigninLogs

SigninLogs
| where UserAgent has_any (UserAgentString) or UserAgent matches regex UARegex
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent, SourceIP = IPAddress, Account = UserPrincipalName, Type, Operation = OperationName, tostring(LocationDetails), tostring(DeviceDetail),    AppDisplayName, ClientAppUsed

Leg 6: AADNonInteractiveUserSignInLogs

AADNonInteractiveUserSignInLogs 
| where UserAgent has_any (UserAgentString) or UserAgent matches regex UARegex
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserAgent, SourceIP = IPAddress, Account = UserPrincipalName, Type, Operation = OperationName, tostring(LocationDetails), tostring(DeviceDetail), AppDisplayName, ClientAppUsed

Leg 7: _Im_WebSession

_Im_WebSession (httpuseragent_has_any=array_concat(UserAgentString,UARegexMinimalString))
| where HttpUserAgent has_any (UserAgentString) or HttpUserAgent matches regex UARegex
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by HttpUserAgent, SourceIP = SrcIpAddr, DstIpAddr, Account = SrcUsername, Url, Type

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Categoryin
  • ApplicationGatewayAccessLog
  • ApplicationGatewayFirewallLog corpus 2 (kusto 2)
  • FrontdoorAccessLog
  • FrontdoorWebApplicationFirewallLog corpus 2 (kusto 2)
field:"Category" kind:in
HttpUserAgentmatch
  • ${jndi: transforms: term
  • ${jndi:corba/ transforms: term
  • ${jndi:dns:/ transforms: term
  • ${jndi:iiop:/ transforms: term
  • ${jndi:ldap:/ transforms: term
  • ${jndi:ldaps:/ transforms: term
  • ${jndi:nds:/ transforms: term
  • ${jndi:rmi:/ transforms: term
field:"HttpUserAgent" kind:match
HttpUserAgentregex_match
  • (\$|%24)(\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\$|%24|}|%7D)
field:"HttpUserAgent" kind:regex_match value:"(\$|%24)(\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\$|%24|}|%7D)"
UserAgentmatch
  • ${jndi: transforms: term
  • ${jndi: transforms: term
  • ${jndi:corba/ transforms: term
  • ${jndi:corba/ transforms: term
  • ${jndi:dns:/ transforms: term
  • ${jndi:dns:/ transforms: term
  • ${jndi:iiop:/ transforms: term
  • ${jndi:iiop:/ transforms: term
  • ${jndi:ldap:/ transforms: term
  • ${jndi:ldap:/ transforms: term
  • ${jndi:ldaps:/ transforms: term
  • ${jndi:ldaps:/ transforms: term
  • ${jndi:nds:/ transforms: term
  • ${jndi:nds:/ transforms: term
  • ${jndi:rmi:/ transforms: term
  • ${jndi:rmi:/ transforms: term
field:"aws::userAgent" kind:match
UserAgentregex_match
  • (\$|%24)(\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\$|%24|}|%7D)
  • (\$|%24)(\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\$|%24|}|%7D)
field:"aws::userAgent" kind:regex_match
csUserAgentmatch
  • ${jndi: transforms: term
  • ${jndi:corba/ transforms: term
  • ${jndi:dns:/ transforms: term
  • ${jndi:iiop:/ transforms: term
  • ${jndi:ldap:/ transforms: term
  • ${jndi:ldaps:/ transforms: term
  • ${jndi:nds:/ transforms: term
  • ${jndi:rmi:/ transforms: term
field:"csUserAgent" kind:match
csUserAgentregex_match
  • (\$|%24)(\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\$|%24|}|%7D)
field:"csUserAgent" kind:regex_match value:"(\$|%24)(\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\$|%24|}|%7D)"
userAgent_smatch
  • ${jndi: transforms: term
  • ${jndi:corba/ transforms: term
  • ${jndi:dns:/ transforms: term
  • ${jndi:iiop:/ transforms: term
  • ${jndi:ldap:/ transforms: term
  • ${jndi:ldaps:/ transforms: term
  • ${jndi:nds:/ transforms: term
  • ${jndi:rmi:/ transforms: term
field:"userAgent_s" kind:match
userAgent_sregex_match
  • (\$|%24)(\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\$|%24|}|%7D)
field:"userAgent_s" kind:regex_match value:"(\$|%24)(\{|%7B)([^jJ]*[jJ])([^nN]*[nN])([^dD]*[dD])([^iI]*[iI])(:|%3A|\$|%24|}|%7D)"

Output Fields

These fields are emitted when the rule matches.

FieldSource
Accountsummarize
DstIpAddrsummarize
EndTimesummarize
HttpUserAgentsummarize
SourceIPsummarize
StartTimesummarize
Typesummarize
Urlsummarize

Vectra AI Detect - New Campaign Detected

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

'Identifies when a new Campaign has been detected. This occurs when multiple Detections accross different Hosts are suspected to be part of the same Attack Campaign.'

MITRE ATT&CK Coverage

TacticTechniques
Lateral Movement
Command & Control

Rule Body

id: a34d0338-eda0-42b5-8b93-32aae0d7a501
name: Vectra AI Detect - New Campaign Detected
description: |
  'Identifies when a new Campaign has been detected.  This occurs when multiple Detections accross different Hosts are suspected to be part of the same Attack Campaign.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: CefAma
    dataTypes:
      - CommonSecurityLog
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - LateralMovement
  - CommandAndControl
relevantTechniques:
  - T1021
  - T1071
query: |
  CommonSecurityLog
  | where DeviceVendor == "Vectra Networks"
  | where DeviceProduct == "X Series"
  | where DeviceEventClassID contains "campaign"
  | where DeviceAction == "START"
  | extend reason = coalesce(
                            column_ifexists("Reason", ""), 
                            extract("reason=(.+?)($|;)", 1, AdditionalExtensions),
                            ""
                        )
  | project-rename vectra_URL = DeviceCustomString4
  | sort by TimeGenerated
entityMappings:
  - entityType: DNS
    fieldMappings:
      - identifier: DomainName
        columnName: Activity
alertDetailsOverride:
  alertDisplayNameFormat: Vectra AI - New Campaign Detected
  alertDescriptionFormat: |
    A new campaign named {{Activity}} has been detected (reason is {{reason}})
  alertDynamicProperties:
    - alertProperty: AlertLink
      value: vectra_URL
    - alertProperty: ProductName
      value: DeviceProduct
    - alertProperty: ProviderName
      value: DeviceVendor
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: true
    lookbackDuration: 7d
    matchingMethod: AllEntities
customDetails:
  CampaignName: Activity 
  CampaignReason: reason 
  CampaignSourceHost: SourceHostName
version: 1.2.3
kind: Scheduled

Stages and Predicates

Stage 1: source

CommonSecurityLog

Stage 2: where

| where DeviceVendor == "Vectra Networks"

Stage 3: where

| where DeviceProduct == "X Series"

Stage 4: where

| where DeviceEventClassID contains "campaign"

Stage 5: where

| where DeviceAction == "START"

Stage 6: extend

| extend reason = coalesce(
                          column_ifexists("Reason", ""), 
                          extract("reason=(.+?)($|;)", 1, AdditionalExtensions),
                          ""
                      )

Stage 7: project-rename

| project-rename vectra_URL = DeviceCustomString4

Stage 8: sort

| sort by TimeGenerated

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
reasonextend
vectra_URLproject-rename

VMware Cloud Web Security - Data Loss Prevention Violation

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

This Analytics rule receives VMware CWS DLP alerts and combines them with their respective Web Log events. Each Data Loss Prevention event is an alert of policy violations and should be investigated.

Rule Body

id: d811ef72-66b9-43a3-ba29-cd9e4bf75b74
name: VMware Cloud Web Security - Data Loss Prevention Violation
version: 1.0.0
kind: Scheduled
description: This Analytics rule receives VMware CWS DLP alerts and combines them with their respective Web Log events. Each Data Loss Prevention event is an alert of policy violations and should be investigated.
severity: Medium
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
requiredDataConnectors:
  - connectorId: VMwareSDWAN
    dataTypes:
      - CWS
query: |-
  VMware_CWS_DLPLogs_CL
  | join kind=innerunique VMware_CWS_Weblogs_CL on TimeGenerated
suppressionEnabled: false
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: 5h
    matchingMethod: AllEntities
    groupByEntities: []
    groupByAlertDetails: []
    groupByCustomDetails: []
eventGroupingSettings:
  aggregationKind: AlertPerResult
customDetails:
  CWS_Policy_Name: policyName
  CWS_Rule_Name: ruleMatched
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: userId
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: sourceIp
- entityType: CloudApplication
  fieldMappings:
  - identifier: Name
    columnName: casbAppName
- entityType: URL
  fieldMappings:
  - identifier: Url
    columnName: dstUrl
suppressionDuration: 5h

Stages and Predicates

Stage 1: source

VMware_CWS_DLPLogs_CL

Stage 2: join

| join kind=innerunique VMware_CWS_Weblogs_CL on TimeGenerated

Back to all Kusto rules