Analytic rule catalog
Suspicious linking of existing user to external User
Back
| Id | 22a320c2-e1e5-4c74-a35b-39fc9cdcf859 |
| Rulename | Suspicious linking of existing user to external User |
| Description | This query will detect when an attempt is made to update an existing user and link it to an guest or external identity. These activities are unusual and such linking of external identities should be investigated. In some cases you may see internal Entra ID sync accounts (Sync_) do this which may be benign |
| Severity | Medium |
| Tactics | PrivilegeEscalation |
| Techniques | T1078.004 |
| Required data connectors | AzureActiveDirectory |
| Kind | Scheduled |
| Query frequency | 1d |
| Query period | 1d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Detections/AuditLogs/SuspiciousLinkingofExternalIdtoExistingUsers.yaml |
| Version | 1.1.0 |
| Arm template | 22a320c2-e1e5-4c74-a35b-39fc9cdcf859.json |
AuditLogs
| where OperationName=~ "Update user"
| where Result =~ "success"
| mv-expand TargetResources
| mv-expand TargetResources.modifiedProperties
| extend displayName = tostring(TargetResources_modifiedProperties.displayName),
TargetUPN_oldValue = tostring(parse_json(tostring(TargetResources_modifiedProperties.oldValue))[0]),
TargetUPN_newValue = tostring(parse_json(tostring(TargetResources_modifiedProperties.newValue))[0])
| where displayName == "UserPrincipalName" and TargetUPN_oldValue !has "#EXT" and TargetUPN_newValue has "#EXT"
| 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(InitiatedBy.user.ipAddress)
| extend InitiatedBy = tostring(iff(isnotempty(InitiatingUserPrincipalName),InitiatingUserPrincipalName, InitiatingAppName))
| summarize arg_max(TimeGenerated, *) by CorrelationId
| project-reorder TimeGenerated, InitiatedBy, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingIPAddress, TargetUPN_oldValue, TargetUPN_newValue
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
| extend TargetAccountName = tostring(split(TargetUPN_oldValue, "@")[0]), TargetUPNSuffix = tostring(split(TargetUPN_oldValue, "@")[1])
relevantTechniques:
- T1078.004
triggerThreshold: 0
id: 22a320c2-e1e5-4c74-a35b-39fc9cdcf859
tags:
- GuestorExternalIdentities
queryPeriod: 1d
triggerOperator: gt
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/AuditLogs/SuspiciousLinkingofExternalIdtoExistingUsers.yaml
queryFrequency: 1d
requiredDataConnectors:
- dataTypes:
- AuditLogs
connectorId: AzureActiveDirectory
version: 1.1.0
tactics:
- PrivilegeEscalation
query: |
AuditLogs
| where OperationName=~ "Update user"
| where Result =~ "success"
| mv-expand TargetResources
| mv-expand TargetResources.modifiedProperties
| extend displayName = tostring(TargetResources_modifiedProperties.displayName),
TargetUPN_oldValue = tostring(parse_json(tostring(TargetResources_modifiedProperties.oldValue))[0]),
TargetUPN_newValue = tostring(parse_json(tostring(TargetResources_modifiedProperties.newValue))[0])
| where displayName == "UserPrincipalName" and TargetUPN_oldValue !has "#EXT" and TargetUPN_newValue has "#EXT"
| 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(InitiatedBy.user.ipAddress)
| extend InitiatedBy = tostring(iff(isnotempty(InitiatingUserPrincipalName),InitiatingUserPrincipalName, InitiatingAppName))
| summarize arg_max(TimeGenerated, *) by CorrelationId
| project-reorder TimeGenerated, InitiatedBy, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingIPAddress, TargetUPN_oldValue, TargetUPN_newValue
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
| extend TargetAccountName = tostring(split(TargetUPN_oldValue, "@")[0]), TargetUPNSuffix = tostring(split(TargetUPN_oldValue, "@")[1])
name: Suspicious linking of existing user to external User
severity: Medium
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: InitiatingAppName
- identifier: AadUserId
columnName: InitiatingAppServicePrincipalId
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: InitiatingUserPrincipalName
- identifier: Name
columnName: InitiatingAccountName
- identifier: UPNSuffix
columnName: InitiatingAccountUPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: InitiatingAadUserId
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: TargetUPN_oldValue
- identifier: Name
columnName: TargetAccountName
- identifier: UPNSuffix
columnName: TargetUPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: InitiatingIPAddress
metadata:
support:
tier: Community
source:
kind: Community
categories:
domains:
- Security - Others
- Identity
author:
name: Microsoft Security Research
description: |
' This query will detect when an attempt is made to update an existing user and link it to an guest or external identity. These activities are unusual and such linking of external
identities should be investigated. In some cases you may see internal Entra ID sync accounts (Sync_) do this which may be benign'
kind: Scheduled
{
"$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/22a320c2-e1e5-4c74-a35b-39fc9cdcf859')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/22a320c2-e1e5-4c74-a35b-39fc9cdcf859')]",
"properties": {
"alertRuleTemplateName": "22a320c2-e1e5-4c74-a35b-39fc9cdcf859",
"customDetails": null,
"description": "' This query will detect when an attempt is made to update an existing user and link it to an guest or external identity. These activities are unusual and such linking of external \nidentities should be investigated. In some cases you may see internal Entra ID sync accounts (Sync_) do this which may be benign'\n",
"displayName": "Suspicious linking of existing user to external User",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "InitiatingAppName",
"identifier": "Name"
},
{
"columnName": "InitiatingAppServicePrincipalId",
"identifier": "AadUserId"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "InitiatingUserPrincipalName",
"identifier": "FullName"
},
{
"columnName": "InitiatingAccountName",
"identifier": "Name"
},
{
"columnName": "InitiatingAccountUPNSuffix",
"identifier": "UPNSuffix"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "InitiatingAadUserId",
"identifier": "AadUserId"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "TargetUPN_oldValue",
"identifier": "FullName"
},
{
"columnName": "TargetAccountName",
"identifier": "Name"
},
{
"columnName": "TargetUPNSuffix",
"identifier": "UPNSuffix"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "InitiatingIPAddress",
"identifier": "Address"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Detections/AuditLogs/SuspiciousLinkingofExternalIdtoExistingUsers.yaml",
"query": "AuditLogs\n| where OperationName=~ \"Update user\" \n| where Result =~ \"success\" \n| mv-expand TargetResources \n| mv-expand TargetResources.modifiedProperties \n| extend displayName = tostring(TargetResources_modifiedProperties.displayName), \nTargetUPN_oldValue = tostring(parse_json(tostring(TargetResources_modifiedProperties.oldValue))[0]), \nTargetUPN_newValue = tostring(parse_json(tostring(TargetResources_modifiedProperties.newValue))[0])\n| where displayName == \"UserPrincipalName\" and TargetUPN_oldValue !has \"#EXT\" and TargetUPN_newValue has \"#EXT\"\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(InitiatedBy.user.ipAddress)\n| extend InitiatedBy = tostring(iff(isnotempty(InitiatingUserPrincipalName),InitiatingUserPrincipalName, InitiatingAppName))\n| summarize arg_max(TimeGenerated, *) by CorrelationId\n| project-reorder TimeGenerated, InitiatedBy, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingIPAddress, TargetUPN_oldValue, TargetUPN_newValue\n| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, \"@\")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, \"@\")[1])\n| extend TargetAccountName = tostring(split(TargetUPN_oldValue, \"@\")[0]), TargetUPNSuffix = tostring(split(TargetUPN_oldValue, \"@\")[1])\n",
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"severity": "Medium",
"subTechniques": [
"T1078.004"
],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"PrivilegeEscalation"
],
"tags": [
"GuestorExternalIdentities"
],
"techniques": [
"T1078"
],
"templateVersion": "1.1.0",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}