# AZ\_OWNER

## Summary

|                               |                                                                                                 |
| ----------------------------- | ----------------------------------------------------------------------------------------------- |
| **FSProtect ACL Alias**       | AZ\_OWNER                                                                                       |
| **Entra ID (Azure AD) Alias** | Owner                                                                                           |
| **Affected Object Types**     | Groups, Applications, Service Principals, Devices                                               |
| **Exploitation Certainty**    | Certain                                                                                         |
| **Graph Permission / Role**   | Object-level owner assignment via Group Owners, Application Owners, or Service Principal Owners |

## Description

`AZ_OWNER` represents the ownership relationship in Microsoft Entra ID (Azure AD) where a principal (user or service principal) has been designated as an **Owner** of an object. Ownership in Entra ID grants significant privileges depending on the object type:

* **Group Owner**: Can add/remove members, modify group properties, and manage group settings. For role-assignable groups, this allows privilege escalation by adding members who inherit directory roles.
* **Application Owner**: Can modify application configurations, add credentials (secrets/certificates), change redirect URIs, and manage API permissions. This can lead to credential theft and unauthorized access.
* **Service Principal Owner**: Can modify the service principal configuration, add credentials, and change authentication settings. Compromising this can allow impersonation of the application.
* **Device Owner**: Can manage device properties and settings.

Ownership is a critical control point that attackers target for privilege escalation and persistence.

## Identification

### PowerShell

#### Comprehensive Owner Enumeration

```powershell
Import-Module Microsoft.Graph.Groups
Import-Module Microsoft.Graph.Applications
Import-Module Microsoft.Graph.Identity.DirectoryManagement

Connect-MgGraph -Scopes "Group.Read.All", "Application.Read.All", "Device.Read.All"

function Get-AllAzureOwnership {
    $allOwnership = [System.Collections.Generic.List[PSCustomObject]]::new()
    
    # Groups - use ExpandProperty to get owners in single call per group batch
    Write-Host "Fetching groups with owners..."
    $groups = Get-MgGroup -All -ExpandProperty "owners"
    foreach ($g in $groups) {
        foreach ($o in $g.Owners) {
            $odataType = $o.AdditionalProperties['@odata.type']
            $ownerType = if ($odataType) { ($odataType -replace '^#microsoft\.graph\.', '') } else { 'Unknown' }
            $allOwnership.Add([PSCustomObject]@{
                TargetType  = "Group"
                TargetName  = $g.DisplayName
                TargetId    = $g.Id
                OwnerName   = $o.AdditionalProperties.displayName
                OwnerType   = $ownerType
                OwnerId     = $o.Id
            })
        }
    }
    Write-Host "Found $($groups.Count) groups"
    
    # Applications - use ExpandProperty to get owners in single call per app batch
    Write-Host "Fetching applications with owners..."
    $apps = Get-MgApplication -All -ExpandProperty "owners"
    foreach ($a in $apps) {
        foreach ($o in $a.Owners) {
            $odataType = $o.AdditionalProperties['@odata.type']
            $ownerType = if ($odataType) { ($odataType -replace '^#microsoft\.graph\.', '') } else { 'Unknown' }
            $allOwnership.Add([PSCustomObject]@{
                TargetType  = "Application"
                TargetName  = $a.DisplayName
                TargetId    = $a.Id
                OwnerName   = $o.AdditionalProperties.displayName
                OwnerType   = $ownerType
                OwnerId     = $o.Id
            })
        }
    }
    Write-Host "Found $($apps.Count) applications"
    
    # Service Principals - use ExpandProperty to get owners in single call per SP batch
    Write-Host "Fetching service principals with owners..."
    $sps = Get-MgServicePrincipal -All -ExpandProperty "owners"
    foreach ($s in $sps) {
        foreach ($o in $s.Owners) {
            $odataType = $o.AdditionalProperties['@odata.type']
            $ownerType = if ($odataType) { ($odataType -replace '^#microsoft\.graph\.', '') } else { 'Unknown' }
            $allOwnership.Add([PSCustomObject]@{
                TargetType  = "ServicePrincipal"
                TargetName  = $s.DisplayName
                TargetId    = $s.Id
                OwnerName   = $o.AdditionalProperties.displayName
                OwnerType   = $ownerType
                OwnerId     = $o.Id
            })
        }
    }
    Write-Host "Found $($sps.Count) service principals"
    
    # Devices - use ExpandProperty for registered owners
    Write-Host "Fetching devices with owners..."
    $devices = Get-MgDevice -All -ExpandProperty "registeredOwners"
    foreach ($d in $devices) {
        foreach ($o in $d.RegisteredOwners) {
            $odataType = $o.AdditionalProperties['@odata.type']
            $ownerType = if ($odataType) { ($odataType -replace '^#microsoft\.graph\.', '') } else { 'Unknown' }
            $allOwnership.Add([PSCustomObject]@{
                TargetType  = "Device"
                TargetName  = $d.DisplayName
                TargetId    = $d.Id
                OwnerName   = $o.AdditionalProperties.displayName
                OwnerType   = $ownerType
                OwnerId     = $o.Id
            })
        }
    }
    Write-Host "Found $($devices.Count) devices"
    
    $allOwnership
}

$ownership = Get-AllAzureOwnership
$ownership | Export-Csv -Path ".\AllAzureOwnership.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Total ownership relationships: $($ownership.Count)"
$ownership | Sort-Object TargetType, TargetName | Format-Table -AutoSize
```

### Azure CLI

```bash
# List owners of a group
az ad group owner list --group "<GroupObjectIdOrName>" --query "[].{displayName:displayName,id:id}"

# List owners of an application
az ad app owner list --id "<AppObjectIdOrAppId>" --query "[].{displayName:displayName,id:id}"

# List owners of a service principal
az ad sp owner list --id "<SPObjectIdOrAppId>" --query "[].{displayName:displayName,id:id}"

# List registered owners of a device (using Graph API)
az rest --method GET --url "https://graph.microsoft.com/v1.0/devices/<DeviceObjectId>/registeredOwners" --query "value[].{displayName:displayName,id:id}"
```

![Azure CLI](/files/owWPHPeR1m5xCengl4v8)

### Azure GUI

#### Group Owners

* Open **Microsoft Entra admin center** -> **Groups** -> select the **target group**.
* Go to **Owners** in the left menu.

  ![Group Owners UI](/files/iPVUMb5Kkllryo2UA3rB)

#### Application Owners

* Open **Microsoft Entra admin center** -> **Applications** -> **App registrations** -> select the **target app**.
* Go to **Owners** in the left menu.

  ![Application Owners UI](/files/4inHyO6Lcb2bNtUipkha)

#### Service Principal Owners

* Open **Microsoft Entra admin center** -> **Applications** -> **Enterprise applications** -> select the **target app**.
* Go to **Owners** in the left menu.

  ![Service Principal Owners UI](/files/BwrBbUE16uEt9XoyzcRY)

#### Device Owners

* Open **Microsoft Entra admin center** -> **Devices** -> **All devices** -> select the **target device**.
* Go to **Registered owners** in the device details.

## Exploitation

> **Related Attack Paths:**
>
> * [AZ\_ADD\_OWNER](https://gitlab.com/forestall/fsprotect-knowledge-base/-/blob/main/edges/AZ_ADD_OWNER/README.md) - Grants the ability to add owners to objects, which can then be exploited via this edge.
> * [AZ\_ADD\_SECRET](https://gitlab.com/forestall/fsprotect-knowledge-base/-/blob/main/edges/AZ_ADD_SECRET/README.md) - Application/SP owners can add secrets to impersonate the application.
> * [AZ\_ADD\_MEMBERS](https://gitlab.com/forestall/fsprotect-knowledge-base/-/blob/main/edges/AZ_ADD_MEMBERS/README.md) - Group owners can add members to groups.
> * [AZ\_MG\_APPLICATION\_READWRITE\_ALL](https://gitlab.com/forestall/fsprotect-knowledge-base/-/blob/main/edges/AZ_MG_APPLICATION_READWRITE_ALL/README.md) - Applications with this permission can modify any app, similar to ownership.
> * [AZ\_MG\_APPROLEASSIGNMENT\_READWRITE\_ALL](https://gitlab.com/forestall/fsprotect-knowledge-base/-/blob/main/edges/AZ_MG_APPROLEASSIGNMENT_READWRITE_ALL/README.md) - After compromising an app via ownership, grant it dangerous permissions.
> * [AZ\_MG\_ROLEMANAGEMENT\_READWRITE\_DIRECTORY](https://gitlab.com/forestall/fsprotect-knowledge-base/-/blob/main/edges/AZ_MG_ROLEMANAGEMENT_READWRITE_DIRECTORY/README.md) - Escalate to Global Admin after gaining control of an application.

Ownership exploitation depends on the object type:

| Owner Type                  | Exploitation Method                         | See Edge                                                                                                             |
| --------------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Group Owner**             | Add members to gain group privileges        | [AZ\_ADD\_MEMBERS](https://gitlab.com/forestall/fsprotect-knowledge-base/-/blob/main/edges/AZ_ADD_MEMBERS/README.md) |
| **Application Owner**       | Add credentials to impersonate app          | [AZ\_ADD\_SECRET](https://gitlab.com/forestall/fsprotect-knowledge-base/-/blob/main/edges/AZ_ADD_SECRET/README.md)   |
| **Service Principal Owner** | Add credentials to impersonate SP           | [AZ\_ADD\_SECRET](https://gitlab.com/forestall/fsprotect-knowledge-base/-/blob/main/edges/AZ_ADD_SECRET/README.md)   |
| **Device Owner**            | Limited - modify properties, disable device | N/A                                                                                                                  |

## Mitigation

* **Minimize the number of owners** for sensitive objects (groups, applications, service principals).
  * Go to **Microsoft Entra ID** -> **Groups** / **App registrations** / **Enterprise applications**.
  * Select the object -> **Owners** -> remove unnecessary owners.
* **Use Privileged Identity Management (PIM)** for just-in-time owner access to sensitive objects.
* **Monitor owner assignments** and alert on unexpected changes.
* **Avoid assigning ownership to regular users** for applications that have sensitive permissions.
* **Implement Access Reviews** for application and group owners:
  * Go to **Identity Governance** -> **Access Reviews** -> **New access review**.
  * Select the target and configure owner reviews.

## Detection

Detect ownership changes in **Audit logs**.

* Go to **Microsoft Entra ID** -> **Audit logs**.
* Filter by activities:
  * **Add owner to group**
  * **Remove owner from group**
  * **Add owner to application**
  * **Remove owner from application**
  * **Add owner to service principal**
  * **Remove owner from service principal**

![Audit logs](/files/TCxY53Op89LsH24aL5kp)

Monitor for suspicious patterns:

* Owner additions to role-assignable groups.
* Owner additions to applications with privileged API permissions.
* Credential additions to applications shortly after owner assignment.
* Ownership changes outside of change management windows.

## References

* <https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept>
* <https://learn.microsoft.com/en-us/powershell/module/az.resources/get-azadgroupowner>
* <https://learn.microsoft.com/en-us/powershell/module/az.resources/get-azadapplication>
* <https://learn.microsoft.com/en-us/powershell/module/az.resources/get-azadserviceprincipal>
* <https://learn.microsoft.com/en-us/powershell/module/az.resources/new-azadappcredential>
* <https://learn.microsoft.com/en-us/powershell/module/az.resources/add-azadgroupmember>
* <https://learn.microsoft.com/en-us/cli/azure/ad/group/owner>
* <https://learn.microsoft.com/en-us/cli/azure/ad/app/owner>


---

# 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_owner.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.
