User State changed from Guest to Member
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])
triggerThreshold: 0
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
requiredDataConnectors:
- dataTypes:
- AuditLogs
connectorId: AzureActiveDirectory
queryPeriod: 1d
id: a09a0b8e-30fe-4ebf-94a0-cffe50f579cd
relevantTechniques:
- T1098
triggerOperator: gt
name: 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'
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
categories:
domains:
- Security - Others
- Identity
support:
tier: Community
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])
version: 1.1.0
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/AuditLogs/UserStatechangedfromGuesttoMember.yaml
severity: Medium
queryFrequency: 1d
tags:
- AADSecOpsGuide
tactics:
- Persistence
{
"$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"
}
]
}