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

Suspicious modification of Global Administrator user properties

Back
Id48602a24-67cf-4362-b258-3f4249e55def
RulenameSuspicious modification of Global Administrator user properties
DescriptionThis query will detect if user properties of Global Administrator are updated by an existing user. Usually only user administrator or other global administrator can update such properties.

Investigate if such user change is an attempt to elevate an existing low privileged identity or rogue administrator activity
SeverityMedium
TacticsPrivilegeEscalation
TechniquesT1078.004
Required data connectorsAzureActiveDirectory
BehaviorAnalytics
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/SuspiciousModificationofGlobalAdminProperties.yaml
Version1.0.4
Arm template48602a24-67cf-4362-b258-3f4249e55def.json
Deploy To Azure
let query_frequency = 1h;
let query_period = 14d;
IdentityInfo
| where TimeGenerated > ago(query_period)
| where set_has_element(AssignedRoles, "Global Administrator")
| distinct AccountUPN, AccountObjectId
| join kind=inner (
    AuditLogs
    | where TimeGenerated > ago(query_frequency)
    | where OperationName=~ "Update user" and Result =~ "success"
    // | where isnotempty(InitiatedBy["user"])
    | mv-expand TargetResource = TargetResources
    | where TargetResource["type"] == "User"
    | extend AccountObjectId = tostring(TargetResource["id"])
    | where tostring(TargetResource["modifiedProperties"]) != "[]"
    | mv-apply modifiedProperty = TargetResource["modifiedProperties"] on (
        summarize modifiedProperties = make_bag(
            bag_pack(tostring(modifiedProperty["displayName"]),
                bag_pack("oldValue", trim(@'[\"\s]+', tostring(modifiedProperty["oldValue"])),
                    "newValue", trim(@'[\"\s]+', tostring(modifiedProperty["newValue"])))))
    )
    | where not(tostring(modifiedProperties["Included Updated Properties"]["newValue"]) in ("LastDirSyncTime", ""))
    | where not(tostring(modifiedProperties["Included Updated Properties"]["newValue"]) == "StrongAuthenticationPhoneAppDetail" and isnotempty(modifiedProperties["StrongAuthenticationPhoneAppDetail"]) and tostring(array_sort_asc(extract_all(@'\"Id\"\:\"([^\"]+)\"', tostring(modifiedProperties["StrongAuthenticationPhoneAppDetail"]["newValue"])))) == tostring(array_sort_asc(extract_all(@'\"Id\"\:\"([^\"]+)\"', tostring(modifiedProperties["StrongAuthenticationPhoneAppDetail"]["oldValue"])))))
    | extend
        Initiator = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["displayName"]), tostring(InitiatedBy["user"]["userPrincipalName"])),
        InitiatorId = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["servicePrincipalId"]), tostring(InitiatedBy["user"]["id"])),
        IPAddress = tostring(InitiatedBy[tostring(bag_keys(InitiatedBy)[0])]["ipAddress"])
) on AccountObjectId
| project TimeGenerated, Category, Identity, Initiator, IPAddress, OperationName, Result, AccountUPN, InitiatedBy, AdditionalDetails, TargetResources, AccountObjectId, InitiatorId, CorrelationId
| extend
    InitiatorName = tostring(split(Initiator, "@")[0]),
    InitiatorUPNSuffix = tostring(split(Initiator, "@")[1]),
    AccountName = tostring(split(AccountUPN, "@")[0]),
    AccountUPNSuffix = tostring(split(AccountUPN, "@")[1])
relevantTechniques:
- T1078.004
name: Suspicious modification of Global Administrator user properties
requiredDataConnectors:
- dataTypes:
  - AuditLogs
  connectorId: AzureActiveDirectory
- dataTypes:
  - IdentityInfo
  connectorId: BehaviorAnalytics
entityMappings:
- fieldMappings:
  - identifier: FullName
    columnName: Initiator
  - identifier: Name
    columnName: InitiatorName
  - identifier: UPNSuffix
    columnName: InitiatorUPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: FullName
    columnName: AccountUPN
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: AccountUPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: IPAddress
  entityType: IP
triggerThreshold: 0
id: 48602a24-67cf-4362-b258-3f4249e55def
tactics:
- PrivilegeEscalation
version: 1.0.4
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/SuspiciousModificationofGlobalAdminProperties.yaml
queryPeriod: 14d
kind: Scheduled
metadata:
  categories:
    domains:
    - Security - Others
    - Identity
  author:
    name: Microsoft Security Research
  support:
    tier: Community
  source:
    kind: Community
queryFrequency: 1h
severity: Medium
description: |
  'This query will detect if user properties of Global Administrator are updated by an existing user. Usually only user administrator or other global administrator can update such properties.
  Investigate if such user change is an attempt to elevate an existing low privileged identity or rogue administrator activity'  
query: |
  let query_frequency = 1h;
  let query_period = 14d;
  IdentityInfo
  | where TimeGenerated > ago(query_period)
  | where set_has_element(AssignedRoles, "Global Administrator")
  | distinct AccountUPN, AccountObjectId
  | join kind=inner (
      AuditLogs
      | where TimeGenerated > ago(query_frequency)
      | where OperationName=~ "Update user" and Result =~ "success"
      // | where isnotempty(InitiatedBy["user"])
      | mv-expand TargetResource = TargetResources
      | where TargetResource["type"] == "User"
      | extend AccountObjectId = tostring(TargetResource["id"])
      | where tostring(TargetResource["modifiedProperties"]) != "[]"
      | mv-apply modifiedProperty = TargetResource["modifiedProperties"] on (
          summarize modifiedProperties = make_bag(
              bag_pack(tostring(modifiedProperty["displayName"]),
                  bag_pack("oldValue", trim(@'[\"\s]+', tostring(modifiedProperty["oldValue"])),
                      "newValue", trim(@'[\"\s]+', tostring(modifiedProperty["newValue"])))))
      )
      | where not(tostring(modifiedProperties["Included Updated Properties"]["newValue"]) in ("LastDirSyncTime", ""))
      | where not(tostring(modifiedProperties["Included Updated Properties"]["newValue"]) == "StrongAuthenticationPhoneAppDetail" and isnotempty(modifiedProperties["StrongAuthenticationPhoneAppDetail"]) and tostring(array_sort_asc(extract_all(@'\"Id\"\:\"([^\"]+)\"', tostring(modifiedProperties["StrongAuthenticationPhoneAppDetail"]["newValue"])))) == tostring(array_sort_asc(extract_all(@'\"Id\"\:\"([^\"]+)\"', tostring(modifiedProperties["StrongAuthenticationPhoneAppDetail"]["oldValue"])))))
      | extend
          Initiator = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["displayName"]), tostring(InitiatedBy["user"]["userPrincipalName"])),
          InitiatorId = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["servicePrincipalId"]), tostring(InitiatedBy["user"]["id"])),
          IPAddress = tostring(InitiatedBy[tostring(bag_keys(InitiatedBy)[0])]["ipAddress"])
  ) on AccountObjectId
  | project TimeGenerated, Category, Identity, Initiator, IPAddress, OperationName, Result, AccountUPN, InitiatedBy, AdditionalDetails, TargetResources, AccountObjectId, InitiatorId, CorrelationId
  | extend
      InitiatorName = tostring(split(Initiator, "@")[0]),
      InitiatorUPNSuffix = tostring(split(Initiator, "@")[1]),
      AccountName = tostring(split(AccountUPN, "@")[0]),
      AccountUPNSuffix = tostring(split(AccountUPN, "@")[1])  
triggerOperator: gt
{
  "$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/48602a24-67cf-4362-b258-3f4249e55def')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/48602a24-67cf-4362-b258-3f4249e55def')]",
      "properties": {
        "alertRuleTemplateName": "48602a24-67cf-4362-b258-3f4249e55def",
        "customDetails": null,
        "description": "'This query will detect if user properties of Global Administrator are updated by an existing user. Usually only user administrator or other global administrator can update such properties.\nInvestigate if such user change is an attempt to elevate an existing low privileged identity or rogue administrator activity'\n",
        "displayName": "Suspicious modification of Global Administrator user properties",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "Initiator",
                "identifier": "FullName"
              },
              {
                "columnName": "InitiatorName",
                "identifier": "Name"
              },
              {
                "columnName": "InitiatorUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "AccountUPN",
                "identifier": "FullName"
              },
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "AccountUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "IPAddress",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/SuspiciousModificationofGlobalAdminProperties.yaml",
        "query": "let query_frequency = 1h;\nlet query_period = 14d;\nIdentityInfo\n| where TimeGenerated > ago(query_period)\n| where set_has_element(AssignedRoles, \"Global Administrator\")\n| distinct AccountUPN, AccountObjectId\n| join kind=inner (\n    AuditLogs\n    | where TimeGenerated > ago(query_frequency)\n    | where OperationName=~ \"Update user\" and Result =~ \"success\"\n    // | where isnotempty(InitiatedBy[\"user\"])\n    | mv-expand TargetResource = TargetResources\n    | where TargetResource[\"type\"] == \"User\"\n    | extend AccountObjectId = tostring(TargetResource[\"id\"])\n    | where tostring(TargetResource[\"modifiedProperties\"]) != \"[]\"\n    | mv-apply modifiedProperty = TargetResource[\"modifiedProperties\"] on (\n        summarize modifiedProperties = make_bag(\n            bag_pack(tostring(modifiedProperty[\"displayName\"]),\n                bag_pack(\"oldValue\", trim(@'[\\\"\\s]+', tostring(modifiedProperty[\"oldValue\"])),\n                    \"newValue\", trim(@'[\\\"\\s]+', tostring(modifiedProperty[\"newValue\"])))))\n    )\n    | where not(tostring(modifiedProperties[\"Included Updated Properties\"][\"newValue\"]) in (\"LastDirSyncTime\", \"\"))\n    | where not(tostring(modifiedProperties[\"Included Updated Properties\"][\"newValue\"]) == \"StrongAuthenticationPhoneAppDetail\" and isnotempty(modifiedProperties[\"StrongAuthenticationPhoneAppDetail\"]) and tostring(array_sort_asc(extract_all(@'\\\"Id\\\"\\:\\\"([^\\\"]+)\\\"', tostring(modifiedProperties[\"StrongAuthenticationPhoneAppDetail\"][\"newValue\"])))) == tostring(array_sort_asc(extract_all(@'\\\"Id\\\"\\:\\\"([^\\\"]+)\\\"', tostring(modifiedProperties[\"StrongAuthenticationPhoneAppDetail\"][\"oldValue\"])))))\n    | extend\n        Initiator = iif(isnotempty(InitiatedBy[\"app\"]), tostring(InitiatedBy[\"app\"][\"displayName\"]), tostring(InitiatedBy[\"user\"][\"userPrincipalName\"])),\n        InitiatorId = iif(isnotempty(InitiatedBy[\"app\"]), tostring(InitiatedBy[\"app\"][\"servicePrincipalId\"]), tostring(InitiatedBy[\"user\"][\"id\"])),\n        IPAddress = tostring(InitiatedBy[tostring(bag_keys(InitiatedBy)[0])][\"ipAddress\"])\n) on AccountObjectId\n| project TimeGenerated, Category, Identity, Initiator, IPAddress, OperationName, Result, AccountUPN, InitiatedBy, AdditionalDetails, TargetResources, AccountObjectId, InitiatorId, CorrelationId\n| extend\n    InitiatorName = tostring(split(Initiator, \"@\")[0]),\n    InitiatorUPNSuffix = tostring(split(Initiator, \"@\")[1]),\n    AccountName = tostring(split(AccountUPN, \"@\")[0]),\n    AccountUPNSuffix = tostring(split(AccountUPN, \"@\")[1])\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "subTechniques": [
          "T1078.004"
        ],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "PrivilegeEscalation"
        ],
        "techniques": [
          "T1078"
        ],
        "templateVersion": "1.0.4",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}