# Az - Entra ID (AzureAD) & Azure IAM

{{#include ../../../banners/hacktricks-training.md}}

## Osnovne informacije

Azure Active Directory (Azure AD) služi kao Microsoftova usluga zasnovana na oblaku za upravljanje identitetom i pristupom. Ona je ključna za omogućavanje zaposlenima da se prijave i dobiju pristup resursima, kako unutar tako i van organizacije, uključujući Microsoft 365, Azure portal i brojne druge SaaS aplikacije. Dizajn Azure AD se fokusira na pružanje osnovnih usluga identiteta, posebno uključujući **autentifikaciju, autorizaciju i upravljanje korisnicima**.

Ključne karakteristike Azure AD uključuju **višefaktorsku autentifikaciju** i **uslovni pristup**, uz besprekornu integraciju sa drugim Microsoftovim bezbednosnim uslugama. Ove karakteristike značajno povećavaju bezbednost identiteta korisnika i omogućavaju organizacijama da efikasno implementiraju i sprovode svoje politike pristupa. Kao osnovna komponenta Microsoftovog ekosistema usluga u oblaku, Azure AD je ključan za upravljanje identitetima korisnika zasnovano na oblaku.

## Enumeracija

### **Konekcija**

{{#tabs }}
{{#tab name="az cli" }}
```bash
az login #This will open the browser (if not use --use-device-code)
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
## With password
az login --service-principal -u <application ID> -p VerySecret --tenant contoso.onmicrosoft.com # Tenant can also be the tenant UUID
## With cert
az login --service-principal -u <application ID> -p ~/mycertfile.pem --tenant contoso.onmicrosoft.com

# 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 name="Mg" }}
```bash
# Login Open browser
Connect-MgGraph

# Login with service principal secret
## App ID and Tenant ID of your Azure AD App Registration
$appId = "<appId>"
$tenantId = "<tenantId>"
$clientSecret = "<clientSecret>"
## Convert the client secret to a SecureString
$secureSecret = ConvertTo-SecureString -String $clientSecret -AsPlainText -Force
## Create a PSCredential object
$credential = New-Object System.Management.Automation.PSCredential ($appId, $secureSecret)
## Connect using client credentials
Connect-MgGraph -TenantId $tenantId -ClientSecretCredential $credential

# Login with token
$token = (az account get-access-token --resource https://graph.microsoft.com --query accessToken -o tsv)
$secureToken = ConvertTo-SecureString $token -AsPlainText -Force
Connect-MgGraph -AccessToken $secureToken

# Get token from session
Parameters = @{
Method     = "GET"
Uri        = "/v1.0/me"
OutputType = "HttpResponseMessage"
}
$Response = Invoke-MgGraphRequest @Parameters
$Headers = $Response.RequestMessage.Headers
$Headers.Authorization.Parameter


# Find commands
Find-MgGraphCommand -command *Mg*
```
{{#endtab }}

{{#tab name="Az" }}
```bash
Connect-AzAccount #Open browser
# Using credentials
$passwd = ConvertTo-SecureString "Welcome2022!" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential("test@corp.onmicrosoft.com", $passwd)
Connect-AzAccount -Credential $creds

# Get Access Token
# Request access token to other endpoints: AadGraph, AnalysisServices, Arm, Attestation, Batch, DataLake, KeyVault, MSGraph, OperationalInsights, ResourceManager, Storage, Synapse
(ConvertFrom-SecureString (Get-AzAccessToken -ResourceTypeName Arm -AsSecureString).Token -AsPlainText)

# Connect with access token
Connect-AzAccount -AccountId test@corp.onmicrosoft.com [-AccessToken $ManagementToken] [-GraphAccessToken $AADGraphToken] [-MicrosoftGraphAccessToken $MicrosoftGraphToken] [-KeyVaultAccessToken $KeyVaultToken]

# 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 name="Raw PS" }}
```bash
#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}
```
{{#endtab }}

{{#tab name="curl" }}
```bash
# 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
```
{{#endtab }}
{{#tab name="MS Graph" }}
```bash
Get-MgTenantRelationshipDelegatedAdminCustomer
# Install the Microsoft Graph PowerShell module if not already installed
Install-Module Microsoft.Graph -Scope CurrentUser

# Import the module
Import-Module Microsoft.Graph

# Login to Microsoft Graph
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All", "Directory.Read.All"

# Enumerate available commands in Microsoft Graph PowerShell
Get-Command -Module Microsoft.Graph*

# Example: List users
Get-MgUser -All

# Example: List groups
Get-MgGroup -All

# Example: Get roles assigned to a user
Get-MgUserAppRoleAssignment -UserId <UserId>

# Disconnect from Microsoft Graph
Disconnect-MgGraph
```
{{#endtab }}

{{#tab name="Azure AD" }}
```bash
Connect-AzureAD #Open browser
# Using credentials
$passwd = ConvertTo-SecureString "Welcome2022!" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("test@corp.onmicrosoft.com", $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
```
{{#endtab }}
{{#endtabs }}

Kada se **prijavite** putem **CLI** u Azure sa bilo kojim programom, koristite **Azure aplikaciju** iz **tenanta** koji pripada **Microsoftu**. Ove aplikacije, poput onih koje možete kreirati u svom nalogu, **imaju klijent ID**. **Nećete moći da vidite sve njih** u **listama dozvoljenih aplikacija** koje možete videti u konzoli, **ali su podrazumevano dozvoljene**.

Na primer, **powershell skripta** koja **autentifikuje** koristi aplikaciju sa klijent ID **`1950a258-227b-4e31-a9cf-717495945fc2`**. Čak i ako aplikacija ne pojavljuje u konzoli, sysadmin može **blokirati tu aplikaciju** tako da korisnici ne mogu pristupiti koristeći alate koji se povezuju putem te aplikacije.

Međutim, postoje **drugi klijent-IDs** aplikacija koje **će vam omogućiti da se povežete na Azure**:
```bash
# 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
```
### Tenants

{{#tabs }}
{{#tab name="az cli" }}
```bash
# List tenants
az account tenant list
```
{{#endtab }}
{{#endtabs }}

### Korisnici

Za više informacija o Entra ID korisnicima pogledajte:

{{#ref}}
../az-basic-information/
{{#endref}}

{{#tabs }}
{{#tab name="az cli" }}
```bash
# Enumerate users
az ad user list --output table
az ad user list --query "[].userPrincipalName"
# Get info of 1 user
az ad user show --id "test@corp.onmicrosoft.com"
# 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 Entra ID
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 in Azure (NOT in Entra ID)
az role assignment list --include-inherited --include-groups --include-classic-administrators true --assignee <email>
# Get ALL roles assigned in Azure in the current subscription (NOT in Entra ID)
az role assignment list --include-inherited --include-groups --include-classic-administrators true --all

# Get EntraID roles assigned to a user
## Get Token
export TOKEN=$(az account get-access-token --resource https://graph.microsoft.com/ --query accessToken -o tsv)
## Get users
curl -X GET "https://graph.microsoft.com/v1.0/users" \
-H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" | jq
## Get EntraID roles assigned to an user
curl -X GET "https://graph.microsoft.com/beta/rolemanagement/directory/transitiveRoleAssignments?\$count=true&\$filter=principalId%20eq%20'86b10631-ff01-4e73-a031-29e505565caa'" \
-H "Authorization: Bearer $TOKEN" \
-H "ConsistencyLevel: eventual" \
-H "Content-Type: application/json" | jq
## Get role details
curl -X GET "https://graph.microsoft.com/beta/roleManagement/directory/roleDefinitions/cf1c38e5-3621-4004-a7cb-879624dced7c" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" | jq
```
{{#endtab }}

{{#tab name="MS Graph" }}
```bash
# Enumerate users using Microsoft Graph PowerShell
Get-MgUser -All

# Get user details
Get-MgUser -UserId "test@corp.onmicrosoft.com" | Format-List *

# Search "admin" users
Get-MgUser -All | Where-Object { $_.DisplayName -like "*test*" } | Select-Object DisplayName

# Search attributes containing the word "password"
Get-MgUser -All | Where-Object { $_.AdditionalProperties.PSObject.Properties.Name -contains "password" }

# All users from Entra ID
Get-MgUser -Filter "startswith(userPrincipalName, 't')" -All | Select-Object DisplayName, UserPrincipalName

# Get groups where the user is a member
Get-MgUserMemberOf -UserId <UserId>

# Get roles assigned to the user in Entra ID
Get-MgUserAppRoleAssignment -UserId <UserId>

# List available commands in Microsoft Graph PowerShell
Get-Command -Module Microsoft.Graph.Users
```
{{#endtab }}

{{#tab name="Azure AD" }}
```bash
# 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 'test@corp.onmicrosoft.com'
# 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 'bill@example.com'"
Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember -Id $_.Id | where { $_.Id -eq $userObj.ObjectId } }
```
{{#endtab }}

{{#tab name="Az" }}
```bash
# 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 }}

#### Promena lozinke korisnika
```bash
$password = "ThisIsTheNewPassword.!123" | ConvertTo- SecureString -AsPlainText –Force

(Get-AzureADUser -All $true | ?{$_.UserPrincipalName -eq "victim@corp.onmicrosoft.com"}).ObjectId | Set- AzureADUserPassword -Password $password –Verbose
```
### MFA & Conditional Access Policies

Preporučuje se da se doda MFA za svakog korisnika, međutim, neke kompanije to neće postaviti ili će možda postaviti uz Conditional Access: Korisnik će biti **required MFA if** se prijavi sa određene lokacije, pretraživača ili **some condition**. Ove politike, ako nisu pravilno konfigurisane, mogu biti podložne **bypasses**. Proverite:

{{#ref}}
../az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md
{{#endref}}

### Groups

Za više informacija o Entra ID grupama proverite:

{{#ref}}
../az-basic-information/
{{#endref}}

{{#tabs }}
{{#tab name="az cli" }}
```bash
# 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 Entra ID
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 roles assigned to the group in Azure (NOT in Entra ID)
az role assignment list --include-groups --include-classic-administrators true --assignee <group-id>

# To get Entra ID roles assigned check how it's done with users and use a group ID
```
{{#endtab }}

{{#tab name="Az" }}
```bash
# 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 }}
{{#tab name="MS Graph" }}
```bash
# Enumerate groups using Microsoft Graph PowerShell
Get-MgGroup -All

# Get group details
Get-MgGroup -GroupId <GroupId> | Format-List *

# Search "admin" groups
Get-MgGroup -All | Where-Object { $_.DisplayName -like "*admin*" } | Select-Object DisplayName

# Get members of a group
Get-MgGroupMember -GroupId <GroupId> -All

# Get groups a group is member of
Get-MgGroupMemberOf -GroupId <GroupId>

# Get roles assigned to the group in Entra ID
Get-MgGroupAppRoleAssignment -GroupId <GroupId>

# Get group owner
Get-MgGroupOwner -GroupId <GroupId>

# List available commands in Microsoft Graph PowerShell
Get-Command -Module Microsoft.Graph.Groups
```
{{#endtab }}
{{#tab name="Azure AD" }}
```bash
# 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} }
# Get Apps where a group has a role (role not shown)
Get-AzureADGroup -ObjectId <id> | Get-AzureADGroupAppRoleAssignment | fl *
```
{{#endtab }}
{{#endtabs }}

#### Dodavanje korisnika u grupu

Vlasnici grupe mogu dodavati nove korisnike u grupu
```bash
Add-AzureADGroupMember -ObjectId <group_id> -RefObjectId <user_id> -Verbose
```
> [!WARNING]
> Grupe mogu biti dinamične, što u suštini znači da **ako korisnik ispunjava određene uslove, biće dodat u grupu**. Naravno, ako su uslovi zasnovani na **atributima** koje **korisnik** može **kontrolisati**, mogao bi zloupotrebiti ovu funkciju da **uđe u druge grupe**.\
> Proverite kako zloupotrebiti dinamične grupe na sledećoj stranici:

{{#ref}}
../az-privilege-escalation/az-entraid-privesc/dynamic-groups.md
{{#endref}}

### Service Principals

Za više informacija o Entra ID servisnim principalima proverite:

{{#ref}}
../az-basic-information/
{{#endref}}

{{#tabs }}
{{#tab name="az cli" }}
```bash
# Get Service Principals
az ad sp list --all
az ad sp list --all --query "[].[displayName,appId]" -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

# Get SPs with generated secret or certificate
az ad sp list --query '[?length(keyCredentials) > `0` || length(passwordCredentials) > `0`].[displayName, appId, keyCredentials, passwordCredentials]' -o json
```
{{#endtab }}

{{#tab name="Az" }}
```bash
# 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 name="Raw" }}
```bash
$Token = 'eyJ0eX..'
$URI = 'https://graph.microsoft.com/v1.0/applications'
$RequestParams = @{
Method  = 'GET'
Uri     = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
}
(Invoke-RestMethod @RequestParams).value
```
{{#endtab }}
{{#tab name="MS Graph" }}
```bash
# Get Service Principals using Microsoft Graph PowerShell
Get-MgServicePrincipal -All

# Get details of one Service Principal
Get-MgServicePrincipal -ServicePrincipalId <ServicePrincipalId> | Format-List *

# Search SP by display name
Get-MgServicePrincipal -All | Where-Object { $_.DisplayName -like "*app*" } | Select-Object DisplayName

# Get owner of Service Principal
Get-MgServicePrincipalOwner -ServicePrincipalId <ServicePrincipalId>

# Get objects owned by a Service Principal
Get-MgServicePrincipalOwnedObject -ServicePrincipalId <ServicePrincipalId>

# Get groups where the SP is a member
Get-MgServicePrincipalMemberOf -ServicePrincipalId <ServicePrincipalId>

# List available commands in Microsoft Graph PowerShell
Get-Command -Module Microsoft.Graph.ServicePrincipals
```
{{#endtab }}

{{#tab name="Azure AD" }}
```bash
# 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 }}
{{#endtabs }}

> [!WARNING]
> Vlasnik Service Principal-a može promeniti svoju lozinku.

<details>

<summary>Lista i pokušaj dodavanja klijentske tajne na svaku Enterprise App</summary>
```bash
# 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."
}
}
```
</details>

### Aplikacije

Za više informacija o Aplikacijama proverite:

{{#ref}}
../az-basic-information/
{{#endref}}

Kada se aplikacija generiše, dodeljuju se 2 tipa dozvola:

- **Dozvole** dodeljene **Servisnom Principalu**
- **Dozvole** koje **aplikacija** može imati i koristiti **u ime korisnika**.

{{#tabs }}
{{#tab name="az cli" }}
```bash
# List Apps
az ad app list
az ad app list --query "[].[displayName,appId]" -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
# Get SPs owned by current user
az ad app list --show-mine
# Get apps with generated secret or certificate
az ad app list --query '[?length(keyCredentials) > `0` || length(passwordCredentials) > `0`].[displayName, appId, keyCredentials, passwordCredentials]' -o json
# Get Global Administrators (full access over apps)
az rest --method GET --url "https://graph.microsoft.com/v1.0/directoryRoles/1b2256f9-46c1-4fc2-a125-5b2f51bb43b7/members"
# Get Application Administrators (full access over apps)
az rest --method GET --url "https://graph.microsoft.com/v1.0/directoryRoles/1e92c3b7-2363-4826-93a6-7f7a5b53e7f9/members"
# Get Cloud Applications Administrators (full access over apps)
az rest --method GET --url "https://graph.microsoft.com/v1.0/directoryRoles/0d601d27-7b9c-476f-8134-8e7cd6744f02/members"

```
{{#endtab }}

{{#tab name="Az" }}
```bash
# 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 }}

{{#tab name="MS Graph" }}
```bash
# List Applications using Microsoft Graph PowerShell
Get-MgApplication -All

# Get application details
Get-MgApplication -ApplicationId 7861f72f-ad49-4f8c-96a9-19e6950cffe1 | Format-List *

# Search App by display name
Get-MgApplication -Filter "startswith(displayName, 'app')" | Select-Object DisplayName

# Get owner of an application
Get-MgApplicationOwner -ApplicationId <ApplicationId>

# List available commands in Microsoft Graph PowerShell
Get-Command -Module Microsoft.Graph.Applications
```
{{#endtab }}

{{#tab name="Azure AD" }}
```bash
# 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 }}
{{#endtabs }}

> [!WARNING]
> Aplikacija sa dozvolom **`AppRoleAssignment.ReadWrite`** može **povećati privilegije na Global Admin** dodeljujući sebi tu ulogu.\
> Za više informacija [**proverite ovo**](https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48).

> [!NOTE]
> Tajni niz koji aplikacija koristi da dokaže svoj identitet prilikom traženja tokena je lozinka aplikacije.\
> Dakle, ako pronađete ovu **lozinku**, možete pristupiti kao **service principal** **unutar** **tenanta**.\
> Imajte na umu da je ova lozinka vidljiva samo kada je generisana (možete je promeniti, ali je ne možete ponovo dobiti).\
> **Vlasnik** **aplikacije** može **dodati lozinku** (tako da može da se pretvara da je ona).\
> Prijave kao ovi service principals **nisu označene kao rizične** i **neće imati MFA.**

Moguće je pronaći listu često korišćenih App ID-ova koji pripadaju Microsoft-u na [https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications](https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications)

### Managed Identities

Za više informacija o Managed Identities proverite:

{{#ref}}
../az-basic-information/
{{#endref}}

{{#tabs }}
{{#tab name="az cli" }}
```bash
# List all manged identities
az identity list --output table
# With the principal ID you can continue the enumeration in service principals
```
{{#endtab }}
{{#endtabs }}

### Azure Uloge

Za više informacija o Azure ulogama pogledajte:

{{#ref}}
../az-basic-information/
{{#endref}}

{{#tabs }}
{{#tab name="az cli" }}
```bash
# Get roles
az role definition list
# Get all 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,scope:scope,roleDefinitionName:roleDefinitionName}[?roleDefinitionName=='<ROLE_NAME>']"
# Get all the roles assigned to a user
az role assignment list --assignee "<email>" --all --output table
# Get all the roles assigned to a user by filtering
az role assignment list --all --query "[?principalName=='admin@organizationadmin.onmicrosoft.com']" --output table
# Get deny assignments
az rest --method GET --uri "https://management.azure.com/{scope}/providers/Microsoft.Authorization/denyAssignments?api-version=2022-04-01"
## Example scope of subscription
az rest --method GET --uri "https://management.azure.com/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/providers/Microsoft.Authorization/denyAssignments?api-version=2022-04-01"
```
{{#endtab }}

{{#tab name="MS Graph" }}
```bash

# List all available role templates using Microsoft Graph PowerShell
Get-MgDirectoryRoleTemplate -All

# List enabled built-in Entra ID roles
Get-MgDirectoryRole -All

# List all Entra ID roles with their permissions (including custom roles)
Get-MgDirectoryRoleDefinition -All

# List members of a Entra ID role
Get-MgDirectoryRoleMember -DirectoryRoleId <RoleId> -All

# List available commands in Microsoft Graph PowerShell
Get-Command -Module Microsoft.Graph.Identity.DirectoryManagement
```
{{#endtab }}

{{#tab name="Az" }}
```bash
# 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>
# Get deny assignments
Get-AzDenyAssignment # Get from current subscription
Get-AzDenyAssignment -Scope '/subscriptions/96231a05-34ce-4eb4-aa6a-70759cbb5e83/resourcegroups/testRG/providers/Microsoft.Web/sites/site1'
```
{{#tab name="Raw" }}
```bash
# 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 }}

### Entra ID Uloge

Za više informacija o Azure ulogama proverite:

{{#ref}}
../az-basic-information/
{{#endref}}

{{#tabs }}
{{#tab name="az cli" }}
```bash
# List template Entra ID roles
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/directoryRoleTemplates"

# List enabled built-in Entra ID roles
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/directoryRoles"

# List all Entra ID roles with their permissions (including custom roles)
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions"

# List only custom Entra ID roles
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions" | jq '.value[] | select(.isBuiltIn == false)'

# List all assigned Entra ID roles
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments"

# List members of a Entra ID roles
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/directoryRoles/<role-id>/members"

# List Entra ID roles assigned to a user
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/users/<user-id>/memberOf/microsoft.graph.directoryRole" \
--query "value[]" \
--output json

# List Entra ID roles assigned to a group
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/groups/$GROUP_ID/memberOf/microsoft.graph.directoryRole" \
--query "value[]" \
--output json

# List Entra ID roles assigned to a service principal
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$SP_ID/memberOf/microsoft.graph.directoryRole" \
--query "value[]" \
--output json
```
{{#endtab }}

{{#tab name="Azure AD" }}
```bash
# 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 }}
{{#endtabs }}

### Uređaji

{{#tabs }}
{{#tab name="az cli" }}
```bash
# If you know how to do this send a PR!
```
{{#endtab }}
{{#tab name="MS Graph" }}
```bash
# Enumerate devices using Microsoft Graph PowerShell
Get-MgDevice -All

# Get device details
Get-MgDevice -DeviceId <DeviceId> | Format-List *

# Get devices managed using Intune
Get-MgDevice -Filter "isCompliant eq true" -All

# Get devices owned by a user
Get-MgUserOwnedDevice -UserId test@corp.onmicrosoft.com

# List available commands in Microsoft Graph PowerShell
Get-Command -Module Microsoft.Graph.Identity.DirectoryManagement
```
{{#endtab }}

{{#tab name="Azure AD" }}
```bash
# 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 }}

> [!WARNING]
> Ako je uređaj (VM) **AzureAD povezan**, korisnici iz AzureAD će moći da se **prijave**.\
> Štaviše, ako je prijavljeni korisnik **Vlasnik** uređaja, on će biti **lokalni administrator**.

### Administrativne jedinice

Za više informacija o administrativnim jedinicama pogledajte:

{{#ref}}
../az-basic-information/
{{#endref}}

{{#tabs }}
{{#tab name="az cli" }}
```bash
# List all administrative units
az rest --method GET --uri "https://graph.microsoft.com/v1.0/directory/administrativeUnits"
# Get AU info
az rest --method GET --uri "https://graph.microsoft.com/v1.0/directory/administrativeUnits/a76fd255-3e5e-405b-811b-da85c715ff53"
# Get members
az rest --method GET --uri "https://graph.microsoft.com/v1.0/directory/administrativeUnits/a76fd255-3e5e-405b-811b-da85c715ff53/members"
# Get principals with roles over the AU
az rest --method GET --uri "https://graph.microsoft.com/v1.0/directory/administrativeUnits/a76fd255-3e5e-405b-811b-da85c715ff53/scopedRoleMembers"
```
{{#endtab }}

{{#tab name="AzureAD" }}
```bash
# 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 }}

## Entra ID Eskalacija Privilegija

{{#ref}}
../az-privilege-escalation/az-entraid-privesc/
{{#endref}}

## Azure Eskalacija Privilegija

{{#ref}}
../az-privilege-escalation/az-authorization-privesc.md
{{#endref}}

## Odbrambeni Mehanizmi

### Upravljanje Privilegovanim Identitetima (PIM)

Upravljanje Privilegovanim Identitetima (PIM) u Azure pomaže da se **spreči dodeljivanje prekomernih privilegija** korisnicima nepotrebno.

Jedna od glavnih funkcija koju PIM pruža je da omogućava da se ne dodeljuju uloge principima koji su konstantno aktivni, već da ih učini **prikladnim na određeni vremenski period (npr. 6 meseci)**. Tada, kada korisnik želi da aktivira tu ulogu, mora da je zatraži navodeći vreme koje mu je potrebno za privilegiju (npr. 3 sata). Tada **administrator mora da odobri** zahtev.\
Napomena: korisnik će takođe moći da zatraži da se **prolongira** vreme.

Pored toga, **PIM šalje emailove** svaki put kada se privilegovana uloga dodeljuje nekome.

<figure><img src="../../../images/image (354).png" alt=""><figcaption></figcaption></figure>

Kada je PIM omogućen, moguće je konfigurisati svaku ulogu sa određenim zahtevima kao što su:

- Maksimalno trajanje (sati) aktivacije
- Zahteva MFA prilikom aktivacije
- Zahteva kontekst autentifikacije uslovnog pristupa
- Zahteva opravdanje prilikom aktivacije
- Zahteva informacije o tiketu prilikom aktivacije
- Zahteva odobrenje za aktivaciju
- Maksimalno vreme za isteknuće prikladnih dodela
- Puno više konfiguracije o tome kada i kome slati obaveštenja kada se određene radnje dogode sa tom ulogom

### Politike Uslovnog Pristupa

Proverite:

{{#ref}}
../az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md
{{#endref}}

### Entra Zaštita Identiteta

Entra Zaštita Identiteta je bezbednosna usluga koja omogućava da se **otkrije kada je korisnik ili prijavljivanje previše rizično** da bi bilo prihvaćeno, omogućavajući da se **blokira** korisnik ili pokušaj prijavljivanja.

Omogućava administratoru da je konfiguriše da **blokira** pokušaje kada je rizik "Nizak i iznad", "Srednji i iznad" ili "Visok". Iako, po defaultu je potpuno **onemogućena**:

<figure><img src="../../../images/image (356).png" alt=""><figcaption></figcaption></figure>

> [!TIP]
> Danas se preporučuje dodavanje ovih ograničenja putem politika uslovnog pristupa gde je moguće konfigurisati iste opcije.

### Entra Zaštita Lozinki

Entra Zaštita Lozinki ([https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade](https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade)) je bezbednosna funkcija koja **pomaže u sprečavanju zloupotrebe slabih lozinki tako što zaključava naloge kada se dogodi nekoliko neuspešnih pokušaja prijavljivanja**.\
Takođe omogućava da se **zabranjuje prilagođena lista lozinki** koju treba da obezbedite.

Može se **primeniti i** na nivou oblaka i na lokalnom Active Directory-ju.

Podrazumevani režim je **Revizija**:

<figure><img src="../../../images/image (355).png" alt=""><figcaption></figcaption></figure>

## Reference

- [https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units](https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units)

{{#include ../../../banners/hacktricks-training.md}}
