Internal Network Pentest and IR Reference: azure devices users sp

# Azure AD - IAM

> Root Management Group (Tenant) > Management Group > Subscription > Resource Group > Resource

* Users (User, Groups, Dynamic Groups)
* Devices
* Service Principals (Application and Managed Identities)

## Users

* List users: `Get-AzureADUser -All $true`
* Enumerate groups

    ```ps1
    # List groups
    Get-AzureADGroup -All $true
    
    # Get members of a group
    Get-AzADGroup -DisplayName '<GROUP-NAME>'
    Get-AzADGroupMember -GroupDisplayName '<GROUP-NAME>' | select UserPrincipalName
    ```

* Enumerate roles: `Get-AzureADDirectoryRole -Filter "DisplayName eq 'Global Administrator'" | Get-AzureADDirectoryRoleMember`
* List roles: `Get-AzureADMSRoleDefinition | ?{$_.IsBuiltin -eq $False} | select DisplayName`
* Add user to a group

    ```ps1
    $groupid = "<group-id>"
    $targetmember = "<user-id>"
    $group = Get-MgGroup -GroupId $groupid
    $members = Get-MgGroupMember -GroupId $groupid
    New-MgGroupMember -GroupId $groupid -DirectoryObjectid $targetmember
    ```

### Dynamic Group Membership

Get groups that allow Dynamic membership:

* Powershell Azure AD: `Get-AzureADMSGroup | ?{$_.GroupTypes -eq 'DynamicMembership'}`
* RoadRecon database: `select objectId, displayName, description, membershipRule, membershipRuleProcessingState, isMembershipRuleLocked from groups where membershipRule is not null;`

Rule example : `(user.otherMails -any (_ -contains "vendor")) -and (user.userType -eq "guest")`
Rule description: Any Guest user whose secondary email contains the string 'vendor' will be added to the group

1. Open user's profile, click on **Manage**
2. Click on **Resend** invite and to get an invitation URL
3. Set the secondary email

    ```powershell
    PS> Set-AzureADUser -ObjectId <OBJECT-ID> -OtherMails <Username>@<TENANT NAME>.onmicrosoft.com -Verbose
    ```

### Administrative Unit

Enumerate Administrative Units.

```ps1
PS AzureAD> Get-AzureADMSAdministrativeUnit -All $true
PS AzureAD> Get-AzureADMSAdministrativeUnit -Id <ID>
PS AzureAD> Get-AzureADMSAdministrativeUnitMember -Id <ID>
PS AzureAD> Get-AzureADMSScopedRoleMembership -Id <ID> | fl
PS AzureAD> Get-AzureADDirectoryRole -ObjectId <RoleId>
PS AzureAD> Get-AzureADUser -ObjectId <RoleMemberInfo.Id> | fl
```

Administrative Unit can be used as a persistence mechanism. When the `visibility` attribute is set to `HiddenMembership`, only members of the administrative unit can list other members of the administrative unit.

```ps1
az rest \
  --method post \
  --url https://graph.microsoft.com/v1.0/directory/administrativeUnits \
  --body '{"displayName": "Hidden AU Administrative Unit", "isMemberManagementRestricted":false, "visibility": "HiddenMembership"}'
```

* Create a new Administrative Unit using the `New-MgDirectoryAdministrativeUnit` cmdlet.

    ```ps1
    Connect-MgGraph -Scopes "AdministrativeUnit.ReadWrite.All"
    Import-Module Microsoft.Graph.Identity.DirectoryManagement

    $params = @{
        displayName = "Marketing Department"
        description = "Marketing Department Administration"
        visibility = "HiddenMembership"
    }

    New-MgDirectoryAdministrativeUnit -BodyParameter $params
    ```

* Add a member with `New-MgDirectoryAdministrativeUnitMemberByRef`

    ```ps1
    Connect-MgGraph -Scopes "AdministrativeUnit.ReadWrite.All"
    Import-Module Microsoft.Graph.Identity.DirectoryManagement

    $administrativeUnitId = "0b22c83d-c5ac-43f2-bb6e-88af3016d49f"
    $paramsUser1 = @{
        "@odata.id" = "https://graph.microsoft.com/v1.0/users/52e26d18-d251-414f-af14-a4a93123b2b2"
    }
    New-MgDirectoryAdministrativeUnitMemberByRef -AdministrativeUnitId $administrativeUnitId -BodyParameter $paramsUser1
    ```

* List members even when the administrative unit is hidden.

    ```ps1
    Connect-MgGraph -Scopes "AdministrativeUnit.Read.All", "Member.Read.Hidden", "Directory.Read.All"
    Import-Module Microsoft.Graph.Identity.DirectoryManagement

    $administrativeUnitId = "0b22c83d-c5ac-43f2-bb6e-88af3016d49f"
    Get-MgDirectoryAdministrativeUnitMemberAsUser -AdministrativeUnitId $administrativeUnitId
    ```

* Assign the `User Administrator` role, its ID is `947ccf23-ee27-4951-8110-96c62c680311` in this tenant.

    ```ps1
    Connect-MgGraph -Scopes "RoleManagement.ReadWrite.Directory"
    Import-Module Microsoft.Graph.Identity.DirectoryManagement

    $administrativeUnitId = "0b22c83d-c5ac-43f2-bb6e-88af3016d49f"
    $userAdministratorRoleId = "947ccf23-ee27-4951-8110-96c62c680311"
    $params = @{
        roleId = $userAdministratorRoleId
        roleMemberInfo = @{
            id = "61b0d52f-a902-4769-9a09-c6528336b00a"
        }
    }

    New-MgDirectoryAdministrativeUnitScopedRoleMember -AdministrativeUnitId $administrativeUnitId -BodyParameter $params
    ```

* Now the user with the id `61b0d52f-a902-4769-9a09-c6528336b00a` can edit the property of the other users in the Administrative Units.

Administrative Units can reset password of another user.

```powershell
PS C:\Tools> $[CREDENTIAL_REDACTED]" | ConvertToSecureString -AsPlainText -Force
PS C:\Tools> (Get-AzureADUser -All $true | ?{$_.UserPrincipalName -eq "<Username>@<TENANT NAME>.onmicrosoft.com"}).ObjectId | SetAzureADUserPassword -Password $Password -Verbose
```

### Convert GUID to SID

The user's Entra ID is translated to SID by concatenating `"S-1–12–1-"` to the decimal representation of each section of the Entra ID.

```powershell
GUID: [base16(a1)]-[base16(a2)]-[ base16(a3)]-[base16(a4)]
SID: S-1–12–1-[base10(a1)]-[ base10(a2)]-[ base10(a3)]-[ base10(a4)]
```

For example, the representation of `6aa89ecb-1f8f-4d92–810d-b0dce30b6c82` is `S-1–12–1–[PII_REDACTED]–[PII_REDACTED]–[PII_REDACTED]–[PII_REDACTED]`

## Devices

### List Devices

```ps1
Connect-AzureAD
Get-AzureADDevice
$user = Get-AzureADUser -SearchString "username"
Get-AzureADUserRegisteredDevice -ObjectId $user.ObjectId -All $true
```

### Device State

```ps1
PS> dsregcmd.exe /status
+----------------------------------------------------------------------+
| Device State |
+----------------------------------------------------------------------+
 AzureAdJoined : YES
 EnterpriseJoined : NO
 DomainJoined : NO
 Device Name : jumpvm
```

* [**Azure AD Joined**](https://pbs.twimg.com/media/EQZv62NWAAEQ8wE?format=jpg&name=large)
* [**Workplace Joined**](https://pbs.twimg.com/media/EQZv7UHXsAArdhn?format=jpg&name=large)
* [**Hybrid Joined**](https://pbs.twimg.com/media/EQZv77jXkAAC4LK?format=jpg&name=large)
* [**Workplace joined on AADJ or Hybrid**](https://pbs.twimg.com/media/EQZv8qBX0AAMWuR?format=jpg&name=large)

### Join Devices

[Enroll Windows 10/11 devices in Intune](https://learn.microsoft.com/en-us/mem/intune/user-help/enroll-windows-10-device)

* [secureworks/pytune](https://github.com/secureworks/pytune) - Pytune is a post-exploitation tool for enrolling a fake device into Intune with mulitple platform support.

    ```ps1
    usage: pytune.py [-h] {entra_join,entra_delete,enroll_intune,checkin,retire_intune,check