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

Detecting Impossible travel with mailbox permission tampering Privilege Escalation attempt

Back
Id1399664f-9434-497c-9cde-42e4d74ae20e
RulenameDetecting Impossible travel with mailbox permission tampering & Privilege Escalation attempt
DescriptionThis hunting query will alert on any Impossible travel activity in correlation with mailbox permission tampering followed by account being added to a PIM managed privileged group.

Ensure this impossible travel incident with increase of privileges is legitimate in your environment.
SeverityMedium
TacticsInitialAccess
PrivilegeEscalation
TechniquesT1078
T1548
Required data connectorsAzureActiveDirectory
AzureActivity
AzureSecurityCenter
Office365
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/MailBoxTampering.yaml
Version1.0.2
Arm template1399664f-9434-497c-9cde-42e4d74ae20e.json
Deploy To Azure
SecurityAlert 
| where AlertName == "Impossible travel activity"
| extend Extprop = parsejson(Entities)
| mv-expand Extprop
| extend Extprop = parsejson(Extprop)
| extend CmdLine = iff(Extprop['Type']=="process", Extprop['CommandLine'], '')
| extend File = iff(Extprop['Type']=="file", Extprop['Name'], '')
| extend Account = Extprop['Name']
| extend Domain = Extprop['UPNSuffix']
| extend Account = iif(isnotempty(Domain) and Extprop['Type']=="account", tolower(strcat(Account, "@", Domain)), iif(Extprop['Type']=="account", tolower(Account), ""))
| extend IpAddress = iff(Extprop["Type"] == "ip",Extprop['Address'], '')
| extend Process = iff(isnotempty(CmdLine), CmdLine, File)
| project TimeGenerated,Account,IpAddress,CompromisedEntity,Description,ProviderName,ResourceId
| join kind=inner
(
OfficeActivity
| where Operation =~ "Add-MailboxPermission"
| extend value = tostring(parse_json(Parameters)[3].Value)
| where value contains "FullAccess"
| where ResultStatus == "True"
| project Parameters,TimeGenerated,value,RecordType,Operation,OrganizationId,UserType,UserKey,OfficeWorkload,ResultStatus,OfficeObjectId,UserId,ClientIP,ExternalAccess,OriginatingServer,OrganizationName,TenantId,ElevationTime,SourceSystem,OfficeId,OfficeTenantId,Type,SourceRecordId
) on $left.Account == $right.UserId
| join kind=inner
(
AuditLogs
| where ActivityDisplayName =~ "Add eligible member to role in PIM requested (timebound)"
| where AADOperationType =~ "CreateRequestEligibleRole"
| where TargetResources has_any ("-PRIV", "Administrator", "Security")
| extend BuiltinRole = tostring(parse_json(TargetResources[0].displayName))
| extend CustomGroup = tostring(parse_json(TargetResources[3].displayName))
| extend TargetAccount = tostring(parse_json(TargetResources[2].displayName))
| extend Initiatedby = Identity
| project TimeGenerated, ActivityDisplayName, AADOperationType, Initiatedby, TargetAccount, BuiltinRole, CustomGroup, LoggedByService, Result, ResourceId, Id
| sort by TimeGenerated desc
) on $left.UserId == $right.Initiatedby
| extend AccountName = tostring(split(Initiatedby, "@")[0]), AccountUPNSuffix = tostring(split(Initiatedby, "@")[1])
| project AADOperationType, ActivityDisplayName,AccountName, AccountUPNSuffix, Id,ResourceId,IpAddress
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: Initiatedby
    identifier: FullName
  - columnName: AccountName
    identifier: Name
  - columnName: AccountUPNSuffix
    identifier: UPNSuffix
- entityType: IP
  fieldMappings:
  - columnName: IpAddress
    identifier: Address
tactics:
- InitialAccess
- PrivilegeEscalation
triggerOperator: gt
description: |
  'This hunting query will alert on any Impossible travel activity in correlation with mailbox permission tampering followed by account being added to a PIM managed privileged group.
  Ensure this impossible travel incident with increase of privileges is legitimate in your environment.'  
requiredDataConnectors:
- connectorId: AzureSecurityCenter
  dataTypes:
  - SecurityAlert (ASC)
- connectorId: Office365
  dataTypes:
  - OfficeActivity
- connectorId: AzureActivity
  dataTypes:
  - AzureActivity
- connectorId: AzureActiveDirectory
  dataTypes:
  - AuditLogs
relevantTechniques:
- T1078
- T1548
version: 1.0.2
id: 1399664f-9434-497c-9cde-42e4d74ae20e
queryPeriod: 1d
kind: Scheduled
triggerThreshold: 0
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/MailBoxTampering.yaml
queryFrequency: 1d
severity: Medium
name: Detecting Impossible travel with mailbox permission tampering & Privilege Escalation attempt
query: |
  SecurityAlert 
  | where AlertName == "Impossible travel activity"
  | extend Extprop = parsejson(Entities)
  | mv-expand Extprop
  | extend Extprop = parsejson(Extprop)
  | extend CmdLine = iff(Extprop['Type']=="process", Extprop['CommandLine'], '')
  | extend File = iff(Extprop['Type']=="file", Extprop['Name'], '')
  | extend Account = Extprop['Name']
  | extend Domain = Extprop['UPNSuffix']
  | extend Account = iif(isnotempty(Domain) and Extprop['Type']=="account", tolower(strcat(Account, "@", Domain)), iif(Extprop['Type']=="account", tolower(Account), ""))
  | extend IpAddress = iff(Extprop["Type"] == "ip",Extprop['Address'], '')
  | extend Process = iff(isnotempty(CmdLine), CmdLine, File)
  | project TimeGenerated,Account,IpAddress,CompromisedEntity,Description,ProviderName,ResourceId
  | join kind=inner
  (
  OfficeActivity
  | where Operation =~ "Add-MailboxPermission"
  | extend value = tostring(parse_json(Parameters)[3].Value)
  | where value contains "FullAccess"
  | where ResultStatus == "True"
  | project Parameters,TimeGenerated,value,RecordType,Operation,OrganizationId,UserType,UserKey,OfficeWorkload,ResultStatus,OfficeObjectId,UserId,ClientIP,ExternalAccess,OriginatingServer,OrganizationName,TenantId,ElevationTime,SourceSystem,OfficeId,OfficeTenantId,Type,SourceRecordId
  ) on $left.Account == $right.UserId
  | join kind=inner
  (
  AuditLogs
  | where ActivityDisplayName =~ "Add eligible member to role in PIM requested (timebound)"
  | where AADOperationType =~ "CreateRequestEligibleRole"
  | where TargetResources has_any ("-PRIV", "Administrator", "Security")
  | extend BuiltinRole = tostring(parse_json(TargetResources[0].displayName))
  | extend CustomGroup = tostring(parse_json(TargetResources[3].displayName))
  | extend TargetAccount = tostring(parse_json(TargetResources[2].displayName))
  | extend Initiatedby = Identity
  | project TimeGenerated, ActivityDisplayName, AADOperationType, Initiatedby, TargetAccount, BuiltinRole, CustomGroup, LoggedByService, Result, ResourceId, Id
  | sort by TimeGenerated desc
  ) on $left.UserId == $right.Initiatedby
  | extend AccountName = tostring(split(Initiatedby, "@")[0]), AccountUPNSuffix = tostring(split(Initiatedby, "@")[1])
  | project AADOperationType, ActivityDisplayName,AccountName, AccountUPNSuffix, Id,ResourceId,IpAddress  
metadata:
  support:
    tier: Community
  categories:
    domains:
    - Security - Others
    - Identity
  source:
    kind: Community
  author:
    name: Microsoft Security Research
{
  "$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/1399664f-9434-497c-9cde-42e4d74ae20e')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/1399664f-9434-497c-9cde-42e4d74ae20e')]",
      "properties": {
        "alertRuleTemplateName": "1399664f-9434-497c-9cde-42e4d74ae20e",
        "customDetails": null,
        "description": "'This hunting query will alert on any Impossible travel activity in correlation with mailbox permission tampering followed by account being added to a PIM managed privileged group.\nEnsure this impossible travel incident with increase of privileges is legitimate in your environment.'\n",
        "displayName": "Detecting Impossible travel with mailbox permission tampering & Privilege Escalation attempt",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "Initiatedby",
                "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/MailBoxTampering.yaml",
        "query": "SecurityAlert \n| where AlertName == \"Impossible travel activity\"\n| extend Extprop = parsejson(Entities)\n| mv-expand Extprop\n| extend Extprop = parsejson(Extprop)\n| extend CmdLine = iff(Extprop['Type']==\"process\", Extprop['CommandLine'], '')\n| extend File = iff(Extprop['Type']==\"file\", Extprop['Name'], '')\n| extend Account = Extprop['Name']\n| extend Domain = Extprop['UPNSuffix']\n| extend Account = iif(isnotempty(Domain) and Extprop['Type']==\"account\", tolower(strcat(Account, \"@\", Domain)), iif(Extprop['Type']==\"account\", tolower(Account), \"\"))\n| extend IpAddress = iff(Extprop[\"Type\"] == \"ip\",Extprop['Address'], '')\n| extend Process = iff(isnotempty(CmdLine), CmdLine, File)\n| project TimeGenerated,Account,IpAddress,CompromisedEntity,Description,ProviderName,ResourceId\n| join kind=inner\n(\nOfficeActivity\n| where Operation =~ \"Add-MailboxPermission\"\n| extend value = tostring(parse_json(Parameters)[3].Value)\n| where value contains \"FullAccess\"\n| where ResultStatus == \"True\"\n| project Parameters,TimeGenerated,value,RecordType,Operation,OrganizationId,UserType,UserKey,OfficeWorkload,ResultStatus,OfficeObjectId,UserId,ClientIP,ExternalAccess,OriginatingServer,OrganizationName,TenantId,ElevationTime,SourceSystem,OfficeId,OfficeTenantId,Type,SourceRecordId\n) on $left.Account == $right.UserId\n| join kind=inner\n(\nAuditLogs\n| where ActivityDisplayName =~ \"Add eligible member to role in PIM requested (timebound)\"\n| where AADOperationType =~ \"CreateRequestEligibleRole\"\n| where TargetResources has_any (\"-PRIV\", \"Administrator\", \"Security\")\n| extend BuiltinRole = tostring(parse_json(TargetResources[0].displayName))\n| extend CustomGroup = tostring(parse_json(TargetResources[3].displayName))\n| extend TargetAccount = tostring(parse_json(TargetResources[2].displayName))\n| extend Initiatedby = Identity\n| project TimeGenerated, ActivityDisplayName, AADOperationType, Initiatedby, TargetAccount, BuiltinRole, CustomGroup, LoggedByService, Result, ResourceId, Id\n| sort by TimeGenerated desc\n) on $left.UserId == $right.Initiatedby\n| extend AccountName = tostring(split(Initiatedby, \"@\")[0]), AccountUPNSuffix = tostring(split(Initiatedby, \"@\")[1])\n| project AADOperationType, ActivityDisplayName,AccountName, AccountUPNSuffix, Id,ResourceId,IpAddress\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "InitialAccess",
          "PrivilegeEscalation"
        ],
        "techniques": [
          "T1078",
          "T1548"
        ],
        "templateVersion": "1.0.2",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}