Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Suspicious Entra ID Joined Device Update

Back
Id3a3c6835-0086-40ca-b033-a93bf26d878f
RulenameSuspicious Entra ID Joined Device Update
DescriptionThis query looks for suspicious updates to an Microsoft Entra ID joined device where the device name is changed and the device falls out of compliance.

This could occur when a threat actor updates the details of an Autopilot provisioned device using a stolen device ticket, in order to access certificates and keys.

Ref: https://dirkjanm.io/assets/raw/Insomnihack%20Breaking%20and%20fixing%20Azure%20AD%20device%20identity%20security.pdf
SeverityMedium
TacticsCredentialAccess
TechniquesT1528
Required data connectorsAzureActiveDirectory
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/SuspiciousAADJoinedDeviceUpdate.yaml
Version1.0.4
Arm template3a3c6835-0086-40ca-b033-a93bf26d878f.json
Deploy To Azure
AuditLogs
| where OperationName =~ "Update device"
| mv-apply TargetResource=TargetResources on (
    where TargetResource.type =~ "Device"
    | extend ModifiedProperties = TargetResource.modifiedProperties
    | extend DeviceId = TargetResource.id)
| mv-apply Prop=ModifiedProperties on ( 
    where Prop.displayName =~ "CloudDisplayName"
    | extend OldName = Prop.oldValue 
    | extend NewName = Prop.newValue)
| mv-apply Prop=ModifiedProperties on ( 
    where Prop.displayName =~ "IsCompliant"
    | extend OldComplianceState = Prop.oldValue  
    | extend NewComplianceState = Prop.newValue)
| mv-apply Prop=ModifiedProperties on ( 
    where Prop.displayName =~ "TargetId.DeviceTrustType"
    | extend OldTrustType = Prop.oldValue  
    | extend NewTrustType = Prop.newValue)
| mv-apply Prop=ModifiedProperties on ( 
    where Prop.displayName =~ "Included Updated Properties" 
    | extend UpdatedProperties = Prop.newValue)
| extend OldDeviceName = tostring(parse_json(tostring(OldName))[0])
| extend NewDeviceName = tostring(parse_json(tostring(NewName))[0])
| extend OldComplianceState = tostring(parse_json(tostring(OldComplianceState))[0])
| extend NewComplianceState = tostring(parse_json(tostring(NewComplianceState))[0])
| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))
| extend UpdatedPropertiesCount = array_length(split(UpdatedProperties, ','))
| where OldDeviceName != NewDeviceName
| where OldComplianceState =~ 'true' and NewComplianceState =~ 'false'
// Most common is transferring from AAD Registered to AAD Joined - we just want AAD Joined devices
| where NewTrustType == '"AzureAd"' and OldTrustType != '"Workplace"'
// We can modify this value to tune FPs - more properties changed about the device beyond its name the more suspicious it could be
| where UpdatedPropertiesCount > 1
| project-reorder TimeGenerated, DeviceId, NewDeviceName, OldDeviceName, NewComplianceState, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingIpAddress, AADOperationType, OldTrustType, NewTrustType, UpdatedProperties, UpdatedPropertiesCount
| extend InitiatedByName = tostring(split(InitiatingUserPrincipalName,'@',0)[0]), InitiatedByUPNSuffix = tostring(split(InitiatingUserPrincipalName,'@',1)[0])
id: 3a3c6835-0086-40ca-b033-a93bf26d878f
tactics:
- CredentialAccess
queryPeriod: 1d
triggerThreshold: 0
name: Suspicious Entra ID Joined Device Update
query: |
  AuditLogs
  | where OperationName =~ "Update device"
  | mv-apply TargetResource=TargetResources on (
      where TargetResource.type =~ "Device"
      | extend ModifiedProperties = TargetResource.modifiedProperties
      | extend DeviceId = TargetResource.id)
  | mv-apply Prop=ModifiedProperties on ( 
      where Prop.displayName =~ "CloudDisplayName"
      | extend OldName = Prop.oldValue 
      | extend NewName = Prop.newValue)
  | mv-apply Prop=ModifiedProperties on ( 
      where Prop.displayName =~ "IsCompliant"
      | extend OldComplianceState = Prop.oldValue  
      | extend NewComplianceState = Prop.newValue)
  | mv-apply Prop=ModifiedProperties on ( 
      where Prop.displayName =~ "TargetId.DeviceTrustType"
      | extend OldTrustType = Prop.oldValue  
      | extend NewTrustType = Prop.newValue)
  | mv-apply Prop=ModifiedProperties on ( 
      where Prop.displayName =~ "Included Updated Properties" 
      | extend UpdatedProperties = Prop.newValue)
  | extend OldDeviceName = tostring(parse_json(tostring(OldName))[0])
  | extend NewDeviceName = tostring(parse_json(tostring(NewName))[0])
  | extend OldComplianceState = tostring(parse_json(tostring(OldComplianceState))[0])
  | extend NewComplianceState = tostring(parse_json(tostring(NewComplianceState))[0])
  | extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
  | extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
  | extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
  | extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
  | extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))
  | extend UpdatedPropertiesCount = array_length(split(UpdatedProperties, ','))
  | where OldDeviceName != NewDeviceName
  | where OldComplianceState =~ 'true' and NewComplianceState =~ 'false'
  // Most common is transferring from AAD Registered to AAD Joined - we just want AAD Joined devices
  | where NewTrustType == '"AzureAd"' and OldTrustType != '"Workplace"'
  // We can modify this value to tune FPs - more properties changed about the device beyond its name the more suspicious it could be
  | where UpdatedPropertiesCount > 1
  | project-reorder TimeGenerated, DeviceId, NewDeviceName, OldDeviceName, NewComplianceState, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingIpAddress, AADOperationType, OldTrustType, NewTrustType, UpdatedProperties, UpdatedPropertiesCount
  | extend InitiatedByName = tostring(split(InitiatingUserPrincipalName,'@',0)[0]), InitiatedByUPNSuffix = tostring(split(InitiatingUserPrincipalName,'@',1)[0])  
severity: Medium
triggerOperator: gt
kind: Scheduled
relevantTechniques:
- T1528
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/SuspiciousAADJoinedDeviceUpdate.yaml
queryFrequency: 1d
requiredDataConnectors:
- connectorId: AzureActiveDirectory
  dataTypes:
  - AuditLogs
version: 1.0.4
description: |
  'This query looks for suspicious updates to an Microsoft Entra ID joined device where the device name is changed and the device falls out of compliance.
  This could occur when a threat actor updates the details of an Autopilot provisioned device using a stolen device ticket, in order to access certificates and keys.
  Ref: https://dirkjanm.io/assets/raw/Insomnihack%20Breaking%20and%20fixing%20Azure%20AD%20device%20identity%20security.pdf'  
status: Available
alertDetailsOverride:
  alertDisplayNameFormat: Suspicious Entra ID Joined Device Update {{OldDeviceName}} renamed to {{NewDeviceName}} and {{UpdatedPropertiesCount}} properties changed
  alertDescriptionFormat: |
    This query looks for suspicious updates to an Microsoft Entra ID joined device where the device name is changed and the device falls out of compliance.
    In this case {{OldDeviceName}} was renamed to {{NewDeviceName}} and {{UpdatedPropertiesCount}} properties were changed.
    This could occur when a threat actor updates the details of an Autopilot provisioned device using a stolen device ticket, in order to access certificates and keys.
    Ref: https://dirkjanm.io/assets/raw/Insomnihack%20Breaking%20and%20fixing%20Azure%20AD%20device%20identity%20security.pdf    
entityMappings:
- fieldMappings:
  - columnName: NewDeviceName
    identifier: HostName
  entityType: Host
- fieldMappings:
  - columnName: OldDeviceName
    identifier: HostName
  entityType: Host
- fieldMappings:
  - columnName: DeviceId
    identifier: AzureID
  entityType: Host
- fieldMappings:
  - columnName: InitiatingUserPrincipalName
    identifier: FullName
  - columnName: InitiatedByName
    identifier: Name
  - columnName: InitiatedByUPNSuffix
    identifier: UPNSuffix
  entityType: Account
- fieldMappings:
  - columnName: InitiatingAadUserId
    identifier: AadUserId
  entityType: Account
- fieldMappings:
  - columnName: InitiatingAppServicePrincipalId
    identifier: AadUserId
  entityType: Account
- fieldMappings:
  - columnName: InitiatingIpAddress
    identifier: Address
  entityType: IP
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2024-01-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/3a3c6835-0086-40ca-b033-a93bf26d878f')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/3a3c6835-0086-40ca-b033-a93bf26d878f')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "This query looks for suspicious updates to an Microsoft Entra ID joined device where the device name is changed and the device falls out of compliance.\nIn this case {{OldDeviceName}} was renamed to {{NewDeviceName}} and {{UpdatedPropertiesCount}} properties were changed.\nThis could occur when a threat actor updates the details of an Autopilot provisioned device using a stolen device ticket, in order to access certificates and keys.\nRef: https://dirkjanm.io/assets/raw/Insomnihack%20Breaking%20and%20fixing%20Azure%20AD%20device%20identity%20security.pdf\n",
          "alertDisplayNameFormat": "Suspicious Entra ID Joined Device Update {{OldDeviceName}} renamed to {{NewDeviceName}} and {{UpdatedPropertiesCount}} properties changed"
        },
        "alertRuleTemplateName": "3a3c6835-0086-40ca-b033-a93bf26d878f",
        "customDetails": null,
        "description": "'This query looks for suspicious updates to an Microsoft Entra ID joined device where the device name is changed and the device falls out of compliance.\nThis could occur when a threat actor updates the details of an Autopilot provisioned device using a stolen device ticket, in order to access certificates and keys.\nRef: https://dirkjanm.io/assets/raw/Insomnihack%20Breaking%20and%20fixing%20Azure%20AD%20device%20identity%20security.pdf'\n",
        "displayName": "Suspicious Entra ID Joined Device Update",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "NewDeviceName",
                "identifier": "HostName"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "OldDeviceName",
                "identifier": "HostName"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "DeviceId",
                "identifier": "AzureID"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "InitiatingUserPrincipalName",
                "identifier": "FullName"
              },
              {
                "columnName": "InitiatedByName",
                "identifier": "Name"
              },
              {
                "columnName": "InitiatedByUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "InitiatingAadUserId",
                "identifier": "AadUserId"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "InitiatingAppServicePrincipalId",
                "identifier": "AadUserId"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "InitiatingIpAddress",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Entra ID/Analytic Rules/SuspiciousAADJoinedDeviceUpdate.yaml",
        "query": "AuditLogs\n| where OperationName =~ \"Update device\"\n| mv-apply TargetResource=TargetResources on (\n    where TargetResource.type =~ \"Device\"\n    | extend ModifiedProperties = TargetResource.modifiedProperties\n    | extend DeviceId = TargetResource.id)\n| mv-apply Prop=ModifiedProperties on ( \n    where Prop.displayName =~ \"CloudDisplayName\"\n    | extend OldName = Prop.oldValue \n    | extend NewName = Prop.newValue)\n| mv-apply Prop=ModifiedProperties on ( \n    where Prop.displayName =~ \"IsCompliant\"\n    | extend OldComplianceState = Prop.oldValue  \n    | extend NewComplianceState = Prop.newValue)\n| mv-apply Prop=ModifiedProperties on ( \n    where Prop.displayName =~ \"TargetId.DeviceTrustType\"\n    | extend OldTrustType = Prop.oldValue  \n    | extend NewTrustType = Prop.newValue)\n| mv-apply Prop=ModifiedProperties on ( \n    where Prop.displayName =~ \"Included Updated Properties\" \n    | extend UpdatedProperties = Prop.newValue)\n| extend OldDeviceName = tostring(parse_json(tostring(OldName))[0])\n| extend NewDeviceName = tostring(parse_json(tostring(NewName))[0])\n| extend OldComplianceState = tostring(parse_json(tostring(OldComplianceState))[0])\n| extend NewComplianceState = tostring(parse_json(tostring(NewComplianceState))[0])\n| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)\n| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)\n| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)\n| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)\n| extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))\n| extend UpdatedPropertiesCount = array_length(split(UpdatedProperties, ','))\n| where OldDeviceName != NewDeviceName\n| where OldComplianceState =~ 'true' and NewComplianceState =~ 'false'\n// Most common is transferring from AAD Registered to AAD Joined - we just want AAD Joined devices\n| where NewTrustType == '\"AzureAd\"' and OldTrustType != '\"Workplace\"'\n// We can modify this value to tune FPs - more properties changed about the device beyond its name the more suspicious it could be\n| where UpdatedPropertiesCount > 1\n| project-reorder TimeGenerated, DeviceId, NewDeviceName, OldDeviceName, NewComplianceState, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingIpAddress, AADOperationType, OldTrustType, NewTrustType, UpdatedProperties, UpdatedPropertiesCount\n| extend InitiatedByName = tostring(split(InitiatingUserPrincipalName,'@',0)[0]), InitiatedByUPNSuffix = tostring(split(InitiatingUserPrincipalName,'@',1)[0])\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CredentialAccess"
        ],
        "techniques": [
          "T1528"
        ],
        "templateVersion": "1.0.4",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}