Detection rules › Splunk
O365 Privileged Role Assigned To Service Principal
The following analytic detects potential privilege escalation threats in Azure Active Directory (AD). This detection is important because it identifies instances where privileged roles that hold elevated permissions are assigned to service principals. This prevents unauthorized access or malicious activities, which occur when these non-human entities access Azure resources to exploit them. False positives might occur since administrators can legitimately assign privileged roles to service principals. This detection leverages the O365 Universal Audit Log data source.
Known false positives
- Administrators may legitimately assign the privileged roles to Service Principals as part of administrative tasks. Filter as needed.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | Add eligible member to role. |
| Microsoft 365 | Add member to role. |
Rules detecting the same action
These rules filter on the same operation.
- O365 High Privilege Role Granted (Splunk)
- O365 Privileged Role Assigned (Splunk)
Rule body
name: O365 Privileged Role Assigned To Service Principal
id: 80f3fc1b-705f-4080-bf08-f61bf013b900
version: 11
creation_date: '2024-04-13'
modification_date: '2026-05-13'
author: Steven Dick
status: production
type: TTP
description: The following analytic detects potential privilege escalation threats in Azure Active Directory (AD). This detection is important because it identifies instances where privileged roles that hold elevated permissions are assigned to service principals. This prevents unauthorized access or malicious activities, which occur when these non-human entities access Azure resources to exploit them. False positives might occur since administrators can legitimately assign privileged roles to service principals. This detection leverages the O365 Universal Audit Log data source.
data_source:
- Office 365 Universal Audit Log
search: "`o365_management_activity` Workload=AzureActiveDirectory Operation IN (\"Add member to role.\",\"Add eligible member to role.\") | eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),\"User\"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),\"ServicePrincipal\"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',\"Role\\.DisplayName\")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',\"Role\\.TemplateId\")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) | fillnull | stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, src, user, category, result, object_name, object_id, signature,vendor_account, vendor_product, dest | lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole | search isprvilegedadrole=\"TRUE\" category!=\"User\" | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `o365_privileged_role_assigned_to_service_principal_filter`"
how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events.
known_false_positives: Administrators may legitimately assign the privileged roles to Service Principals as part of administrative tasks. Filter as needed.
references:
- https://attack.mitre.org/techniques/T1098/003/
- https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference
- https://learn.microsoft.com/en-us/microsoft-365/admin/add-users/about-exchange-online-admin-role?view=o365-worldwide
- https://posts.specterops.io/azure-privilege-escalation-via-service-principal-abuse-210ae2be2a5
finding:
title: A privileged Azure AD role [$object_name$] was assigned to the Service Principal $user$ initiated by $src_user$
entity:
field: src_user
type: user
score: 50
intermediate_findings:
entities:
- field: user
type: user
score: 50
message: A privileged Azure AD role [$object_name$] was assigned to the Service Principal $user$ initiated by $src_user$
analytic_story:
- Azure Active Directory Privilege Escalation
- Scattered Lapsus$ Hunters
asset_type: O365 Tenant
mitre_attack_id:
- T1098.003
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
category: cloud
security_domain: identity
Stages and Predicates
Stage 1: search
`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.")
Stage 2: eval
| eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2)
src_user =if
match(mvindex('Actor{}.ID', -1), "User")mvindex('Actor{}.ID', 0)elif
match(mvindex('Actor{}.ID', -1), "ServicePrincipal")mvindex('Actor{}.ID', 3)else
mvindex('Actor{}.ID', 0)Stage 3: fillnull
| fillnull
Stage 4: stats
| stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, src, user, category, result, object_name, object_id, signature,vendor_account, vendor_product, dest
Stage 5: lookup
| lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole
Stage 6: search
| search isprvilegedadrole="TRUE" category!="User"
Stage 7: search
| `security_content_ctime(firstTime)`
Stage 8: search
| `security_content_ctime(lastTime)`
Stage 9: search
| `o365_privileged_role_assigned_to_service_principal_filter`
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Operation | in |
| field:"Operation" kind:in |
Workload | eq |
| field:"Workload" kind:eq value:"AzureActiveDirectory" |
category | ne |
| field:"category" kind:ne |
isprvilegedadrole | eq |
| field:"isprvilegedadrole" kind:eq |
sourcetype | eq |
| field:"sourcetype" kind:eq value:"o365:management:activity" |