Detection rules › Kusto

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

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

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

MITRE ATT&CK coverage

Telemetry coverage

PlatformRecord / event type
AzureUpdate conditional access policy

Rules detecting the same action

These rules filter on the same operation.

Rule body

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

Stages and Predicates

Stage 1: source

AuditLogs

Stage 2: where

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

Stage 3: extend

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

Stage 4: extend

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

Stage 5: where

| where excludePlatformsOld != excludePlatformsNew

Stage 6: extend (3 consecutive steps)

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

Stage 7: project

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

Stage 8: sort

| order by TimeGenerated desc

Indicators

These rows show field, operator, and value matches.

Output fields

These fields are emitted when the rule matches.

FieldSource
OperationNameproject
TimeGeneratedproject
accountNameproject
excludePlatformsNewproject
excludePlatformsOldproject
modifiedByproject
policyproject
resultproject
upnSuffixproject