Analytic rule catalog
User State changed from Guest to Member
Back
| Id | a09a0b8e-30fe-4ebf-94a0-cffe50f579cd |
| Rulename | User State changed from Guest to Member |
| Description | Detects when a guest account in a tenant is converted to a member of the tenant. Monitoring guest accounts and the access they are provided is important to detect potential account abuse. Accounts converted to members should be investigated to ensure the activity was legitimate. Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#monitoring-for-failed-unusual-sign-ins |
| Severity | Medium |
| Tactics | Persistence |
| Techniques | T1098 |
| 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/UserStatechangedfromGuesttoMember.yaml |
| Version | 1.1.0 |
| Arm template | a09a0b8e-30fe-4ebf-94a0-cffe50f579cd.json |
AuditLogs
| where OperationName =~ "Update user"
| where Result =~ "success"
| mv-expand TargetResources
| mv-expand TargetResources.modifiedProperties
| where TargetResources_modifiedProperties.displayName =~ "TargetId.UserType"
| extend UpdatingAppName = tostring(parse_json(tostring(InitiatedBy.app)).displayName)
| extend UpdatingServicePrincipalId = tostring(parse_json(tostring(InitiatedBy.app)).servicePrincipalId)
| extend UpdatingUserPrincipalName = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
| extend UpdatingUserAadUserId = tostring(parse_json(tostring(InitiatedBy.user)).id)
| extend UpdatingUserIPAddress = tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)
| extend UpdatingUser = iif(isnotempty(UpdatingServicePrincipalId), UpdatingServicePrincipalId, UpdatingUserPrincipalName)
| extend UpdatedUserPrincipalName = tostring(TargetResources.userPrincipalName)
| project-reorder TimeGenerated, UpdatedUserPrincipalName, UpdatingUser
| where parse_json(tostring(TargetResources_modifiedProperties.newValue)) =~ "\"Member\"" and parse_json(tostring(TargetResources_modifiedProperties.oldValue)) =~ "\"Guest\""
| extend InitiatingAccountName = tostring(split(UpdatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(UpdatingUserPrincipalName, "@")[1])
| extend TargetAccountName = tostring(split(UpdatedUserPrincipalName, "@")[0]), TargetAccountUPNSuffix = tostring(split(UpdatedUserPrincipalName, "@")[1])
name: User State changed from Guest to Member
triggerOperator: gt
query: |
AuditLogs
| where OperationName =~ "Update user"
| where Result =~ "success"
| mv-expand TargetResources
| mv-expand TargetResources.modifiedProperties
| where TargetResources_modifiedProperties.displayName =~ "TargetId.UserType"
| extend UpdatingAppName = tostring(parse_json(tostring(InitiatedBy.app)).displayName)
| extend UpdatingServicePrincipalId = tostring(parse_json(tostring(InitiatedBy.app)).servicePrincipalId)
| extend UpdatingUserPrincipalName = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
| extend UpdatingUserAadUserId = tostring(parse_json(tostring(InitiatedBy.user)).id)
| extend UpdatingUserIPAddress = tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)
| extend UpdatingUser = iif(isnotempty(UpdatingServicePrincipalId), UpdatingServicePrincipalId, UpdatingUserPrincipalName)
| extend UpdatedUserPrincipalName = tostring(TargetResources.userPrincipalName)
| project-reorder TimeGenerated, UpdatedUserPrincipalName, UpdatingUser
| where parse_json(tostring(TargetResources_modifiedProperties.newValue)) =~ "\"Member\"" and parse_json(tostring(TargetResources_modifiedProperties.oldValue)) =~ "\"Guest\""
| extend InitiatingAccountName = tostring(split(UpdatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(UpdatingUserPrincipalName, "@")[1])
| extend TargetAccountName = tostring(split(UpdatedUserPrincipalName, "@")[0]), TargetAccountUPNSuffix = tostring(split(UpdatedUserPrincipalName, "@")[1])
queryFrequency: 1d
description: |
'Detects when a guest account in a tenant is converted to a member of the tenant.
Monitoring guest accounts and the access they are provided is important to detect potential account abuse.
Accounts converted to members should be investigated to ensure the activity was legitimate.
Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#monitoring-for-failed-unusual-sign-ins'
id: a09a0b8e-30fe-4ebf-94a0-cffe50f579cd
triggerThreshold: 0
queryPeriod: 1d
version: 1.1.0
kind: Scheduled
relevantTechniques:
- T1098
tags:
- AADSecOpsGuide
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
metadata:
categories:
domains:
- Security - Others
- Identity
support:
tier: Community
author:
name: Microsoft Security Research
source:
kind: Community
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/AuditLogs/UserStatechangedfromGuesttoMember.yaml
tactics:
- Persistence
entityMappings:
- fieldMappings:
- identifier: Name
columnName: UpdatingAppName
- identifier: AadUserId
columnName: UpdatingServicePrincipalId
entityType: Account
- fieldMappings:
- identifier: FullName
columnName: UpdatingUserPrincipalName
- identifier: Name
columnName: InitiatingAccountName
- identifier: UPNSuffix
columnName: InitiatingAccountUPNSuffix
entityType: Account
- fieldMappings:
- identifier: AadUserId
columnName: UpdatingUserAadUserId
entityType: Account
- fieldMappings:
- identifier: FullName
columnName: UpdatedUserPrincipalName
- identifier: Name
columnName: TargetAccountName
- identifier: UPNSuffix
columnName: TargetAccountUPNSuffix
entityType: Account
- fieldMappings:
- identifier: Address
columnName: UpdatingUserIPAddress
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/a09a0b8e-30fe-4ebf-94a0-cffe50f579cd')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/a09a0b8e-30fe-4ebf-94a0-cffe50f579cd')]",
"properties": {
"alertRuleTemplateName": "a09a0b8e-30fe-4ebf-94a0-cffe50f579cd",
"customDetails": null,
"description": "'Detects when a guest account in a tenant is converted to a member of the tenant.\n Monitoring guest accounts and the access they are provided is important to detect potential account abuse.\n Accounts converted to members should be investigated to ensure the activity was legitimate.\n Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-user-accounts#monitoring-for-failed-unusual-sign-ins'\n",
"displayName": "User State changed from Guest to Member",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "UpdatingAppName",
"identifier": "Name"
},
{
"columnName": "UpdatingServicePrincipalId",
"identifier": "AadUserId"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "UpdatingUserPrincipalName",
"identifier": "FullName"
},
{
"columnName": "InitiatingAccountName",
"identifier": "Name"
},
{
"columnName": "InitiatingAccountUPNSuffix",
"identifier": "UPNSuffix"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "UpdatingUserAadUserId",
"identifier": "AadUserId"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "UpdatedUserPrincipalName",
"identifier": "FullName"
},
{
"columnName": "TargetAccountName",
"identifier": "Name"
},
{
"columnName": "TargetAccountUPNSuffix",
"identifier": "UPNSuffix"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "UpdatingUserIPAddress",
"identifier": "Address"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Detections/AuditLogs/UserStatechangedfromGuesttoMember.yaml",
"query": "AuditLogs\n | where OperationName =~ \"Update user\"\n | where Result =~ \"success\"\n | mv-expand TargetResources\n | mv-expand TargetResources.modifiedProperties\n | where TargetResources_modifiedProperties.displayName =~ \"TargetId.UserType\"\n | extend UpdatingAppName = tostring(parse_json(tostring(InitiatedBy.app)).displayName)\n | extend UpdatingServicePrincipalId = tostring(parse_json(tostring(InitiatedBy.app)).servicePrincipalId)\n | extend UpdatingUserPrincipalName = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)\n | extend UpdatingUserAadUserId = tostring(parse_json(tostring(InitiatedBy.user)).id)\n | extend UpdatingUserIPAddress = tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)\n | extend UpdatingUser = iif(isnotempty(UpdatingServicePrincipalId), UpdatingServicePrincipalId, UpdatingUserPrincipalName)\n | extend UpdatedUserPrincipalName = tostring(TargetResources.userPrincipalName)\n | project-reorder TimeGenerated, UpdatedUserPrincipalName, UpdatingUser\n | where parse_json(tostring(TargetResources_modifiedProperties.newValue)) =~ \"\\\"Member\\\"\" and parse_json(tostring(TargetResources_modifiedProperties.oldValue)) =~ \"\\\"Guest\\\"\"\n | extend InitiatingAccountName = tostring(split(UpdatingUserPrincipalName, \"@\")[0]), InitiatingAccountUPNSuffix = tostring(split(UpdatingUserPrincipalName, \"@\")[1])\n | extend TargetAccountName = tostring(split(UpdatedUserPrincipalName, \"@\")[0]), TargetAccountUPNSuffix = tostring(split(UpdatedUserPrincipalName, \"@\")[1])\n",
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"severity": "Medium",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"Persistence"
],
"tags": [
"AADSecOpsGuide"
],
"techniques": [
"T1098"
],
"templateVersion": "1.1.0",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}