#
Azure Pentesting Notes
#
⚠️ Rules of Engagement
Microsoft Rules of Engagements for pentesting: pentest-rules-of-engagement
The goal of this program is to enable customers to test their services hosted in Microsoft Cloud services without causing harm to any other Microsoft customers.
The following activities are prohibited:
- Scanning or testing assets belonging to any other Microsoft Cloud customers.
- Gaining access to any data that is not wholly your own.
- Performing any kind of denial of service testing.
- Performing network intensive fuzzing against any asset except your Azure Virtual Machine
- Performing automated testing of services that generates significant amounts of traffic.
- Deliberately accessing any other customer’s data.
- Moving beyond "proof of concept" repro steps for infrastructure execution issues (i.e. proving that you have sysadmin access with SQLi is acceptable, running xp_cmdshell is not).
- Using our services in a way that violates the Acceptable Use Policy, as set forth in the Microsoft Online Service Terms.
- Attempting phishing or other social engineering attacks against our employees.
The following activities are encouraged:
- Load testing your application by generating traffic which is expected to be seen during the normal course of business. This includes testing surge capacity.
- Testing security monitoring and detections (e.g. generating anomalous security logs, dropping EICAR, etc).
- Attempt to break out of a shared service container such as Azure Websites or Azure Functions. However, should you succeed you must both immediately report it to Microsoft and cease digging deeper. Deliberately accessing another customer’s data is a violation of the terms.
- Applying conditional access or mobile application management (MAM) policies within Microsoft Intune to test the enforcement of the restriction enforced by those policies.
Even with these prohibitions, Microsoft reserves the right to respond to any actions on its networks that appear to be malicious. Many automated mitigation mechanisms are employed across the Microsoft Cloud. These will not be disabled to facilitate a penetration test.
#
🔧 Technical Requirements
Make sure to have these PowerShell modules installed in your Windows or Linux machine (Using the pwsh command for linux)
Install-Module AzureAD
Install-Module Az
Install-Module AADIternals
Install-Module MSOnline
#
🔍 Outsider - Recon
The goal is to map the target attack surface. Looking for Tenant informations, exposed applications and storages, any credentials stored inside public repositories.
#
User Enumeration
The goal here is to create a user list of maybe valid email accounts.
Source & Data
- Data Breach
- LinkedIn Company page
- Google Dorking
- Custom Email List with a known pattern (name.last@company.com / n.last@company.com ...)
#
Tenant ID
An Azure tenant ID is a 128-bit GUID that uniquely identifies a Microsoft Entra ID (formerly Azure AD) directory, typically shown in 8-4-4-4-12 hex format like 00000000-0000-0000-0000-000000000000.
This Tenant ID is often used by services and tools to scope authentication and API access, making it valuable during post-exploitation and lateral movement planning. While it’s not a secret, it’s highly useful for reconnaissance and chaining attacks, so record it carefully for later use in your engagement notes. Microsoft does not treat tenant IDs as confidential and they are commonly exposed in endpoints, tokens, and metadata, so adversaries can often discover them with basic OSINT or unauthenticated queries.
#
OpenID Configuration
You have multiple ways to get this tenant ID, the first one is to use the .well-known url of a target domaine name like so:
https://login.microsoftonline.com/TAREGT-DOMAIN-NAME.COM/v2.0/.well-known/openid-configuration
You can then find it inside the token_endpoint URL.
#
AADInternals Outsider
The second option is to use AADInternals with the Outsider enumeration module.
Install-Module AADInternals
Invoke-AADIntReconAsOutsider -Domain "company.com" | Format-Table
Full Documentation
#
Blob Enumeration
Tool Name: MicroBurst
This tool doesn't require an account. It's going to enumerate public accessible Azure storage (Blobs) using a pattern variation of the target name.
Import-Module .\MicroBurst.psm1
Invoke-EnumerateAzureBlobs –Base targetname
Once you find a public exposed blob you can start to enumerate the content using Storage Explorer
Exposed Blobs
If during your engagement you found any exposed blob, make sure that they belongs to your target. You can't really know if the blob is in the scope or not.
Predictable URL’s for core.windows.net:
- storage-name.blob.core.windows.net
- storage-name.queue.core.windows.net
- storage-name.table.core.windows.net
- storage-name.file.core.windows.net
#
Multi-Cloud Enumeration
Multi-cloud OSINT tool. Enumerate public resources in AWS, Azure, and Google Cloud.
Tool Name: cloud_enum
pip3 install -r ./requirements.txt
./cloud_enum.py -k targetname -t 10
#
Public Secrets
The goal here is to search for secrets and password that may grant us an Initial Access.
- Google Dorking
- Look for sensitive documents
- Code Repositories
#
Public Code Repo
Tools:
#Scan a repo
trufflehog git https://github.com/trufflesecurity/test_keys --results=verified
#Scan an organization
trufflehog github --org=trufflesecurity --results=verified
#
Password Attacks
Password Spaying
Tool Name: MSOLSpray
A password spraying tool for Microsoft Online accounts (Azure/O365). The script logs if a user cred is valid, if MFA is enabled on the account, if a tenant doesn't exist, if a user doesn't exist, if the account is locked, or if the account is disabled.
Import-Module MSOLSpray.ps1
Invoke-MSOLSpray -UserList .\userlist.txt -Password Winter2020
Account Lockdown
Be careful if you try an incorrect password, you may lock the user account after a few failed attempts.
#
Phishing Device Code
Device code is an OAuth 2.0 flow for devices or CLIs that can’t open a browser: the app shows a short user code and a URL (e.g., microsoft.com/devicelogin), you complete sign-in and MFA in a normal browser, and the app polls until it exchanges its device_code for tokens.
How it works: Client requests a device code set, displays user_code and verification_uri, user authenticates at the URL, client polls at the specified interval until it receives access/refresh/ID tokens.
Typical cues: Prompts like
az login --use-device-codeinstruct to visit microsoft.com/devicelogin and enter a short code.Security notes: It’s MFA-compatible but phishable; attackers can social-engineer victims to enter the code, granting tokens to the waiting client. Monitor and restrict this flow via Conditional Access if it’s not needed.
Tool Name: GraphRunner
The goal is to generate a Device Code and Social-Engineer a target.
. ./GraphRunner
Get-GraphTokens
Once the target enter the code and authenticate to the microsoft portal, you'll receive an access_token and a refresh_token. They are both stored inside the $tokens global variable.
You can now start to enumerate the tenant with your initial access.
#
👹 Initial Access - Recon
You are trying to authenticate into the Tenant of the target.
#
Validate Conditional Access
Tool Name: MFASweep
This command will use the provided credentials and attempt to authenticate to the Microsoft Graph API, Azure Service Management API, Microsoft 365 Exchange Web Services, Microsoft 365 Web Portal with both a desktop browser and mobile, and Microsoft 365 Active Sync. If any authentication methods result in success, tokens and/or cookies will be written to AccessTokens.json.
Invoke-MFASweep -Username targetuser@targetdomain.com -Password Winter2024 -WriteTokens
Account Lockdown
Be careful if you try an incorrect password, you may lock the user account after a few failed attempts.
#
Token CheatSheets
Access tokens prove what the client can do right now, while Refresh tokens let the client get new access tokens later without re-prompting the user.
Access tokens
- Purpose: Bearer token presented to an API (e.g., Microsoft Graph) to authorize requests; contains granted scopes/roles and expires quickly.
- Scope/audience: Issued for a specific resource (e.g., https://graph.microsoft.com) and a set of permissions listed in the token response’s scope claim.
- Lifetime: Short-lived, typically around an hour; apps must replace them when expires_in elapses.
- Usage: Sent as
Authorization: Bearer <access_token>on each API call; do not reuse across different resources.
Refresh tokens
- Purpose: Used by the client to obtain new access token/refresh token pairs after the access token expires, avoiding user interaction.
- Scope/audience behavior: Not tied to a single resource; with appropriate grants, the same refresh token can mint access tokens for other resources or tenants the client is permitted to access.
- Lifetime and rotation: Much longer-lived (commonly up to 90 days for most apps; 24 hours for SPA redirect URIs), and they rotate-store only the latest token you receive.
- Prerequisite: Returned only if offline_access was requested in the scope during authorization.
#
Find Tokens in Local Machine
#
Azure TokenCache
If you gain access to a target machine remotely, you may need to look for tokens stored inside the machine.
Legacy Az PowerShell
The legacy Az PowerShell and Azure CLI token cache location on Windows was often referenced as %USERPROFILE%\.azure\TokenCache.dat, but modern tooling no longer stores reusable cleartext bearer tokens there. Current releases use per-tool, DPAPI-protected caches that prevent straightforward extraction as plaintext.
Where tokens live now:
- Azure CLI: Stores account and token cache under
%USERPROFILE%\.azureon Windows, but sensitive material is DPAPI-protected and structured across JSON/db files rather than a simple reusableTokenCache.dat. Even when you locate "accessTokens.json" or similar artifacts, they are not reliably plain, reusable bearer tokens. - Microsoft Graph PowerShell SDK / MSAL-based apps: Token caches are managed by MSAL and, on Windows, encrypted via DPAPI tied to the current user profile. The SDK exposes Connect-MgGraph and related commands but does not provide plaintext tokens on disk.
#
PowerShell History
PowerShell history is a great place to recover pasted tokens, client secrets, device codes, or one‑off commands that fetched tokens, because PSReadLine persists commands to a plain text file by default.
#Show HIstory Path
(Get-PSReadLineOption).HistorySavePath
#Read an Search
Get-Content (Get-PSReadLineOption).HistorySavePath | Select-String -Pattern 'token|asplaintext|password|secret|apikey'
#Default Path
%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Powershell\PSReadLine\ConsoleHost_history.txt
#
More Location
- Azure Publish Files
.publishettingsextension web.config- Visual Studio Azure Cloud Service Packages
.cspkgextension
#
🧙♂️ Post Exploitation
You manage to get your Initial Access, your goal is to enumerate and elevate your privileges.
#
Get new tokens with different scopes
Request a new token for a new resource audience (scope). In this example you'll change your Microsoft Graph scope into an Azure Resource Manager (Management).
Keep your refresh token handy and mint separate access tokens for each API (e.g., Microsoft Graph vs. https://management.azure.com).
Use GraphRunner to refresh your Microsoft Graph tokens, ensuring your access token isn’t expired.
# Refresh MS Graph tokens in $tokens (access/refresh/id)
Invoke-RefreshGraphTokens
Connect to Microsoft Graph with an access token
Recent Microsoft Graph PowerShell versions accept -AccessToken as a SecureString; convert accordingly.
# Convert the MS Graph access token for Connect-MgGraph
$secureGraphToken = ($tokens.access_token | ConvertTo-SecureString -AsPlainText -Force)
Connect-MgGraph -AccessToken $secureGraphToken
Obtain an Azure Resource Manager (Management) token
Request a separate token for the ARM audience and use Az modules or direct REST calls.
# Interactive or device code as needed
Connect-AzAccount
# Get ARM token for Management API
$arm = Get-AzAccessToken -ResourceUrl https://management.azure.com
$armToken = $arm.Token
#
Compliance & Audit
This part isn't really focused into pentesting but it could give you some highlight about the configuration of the Azure Tenant.
#
Prowler
Prowler is like ScoutSuite and can generate a compliance check with a nice and shiny template, but the scan ca take few hours to perform. It's using azure cli
Tool Name: Prowler
#Running Scans from the terminal and generate differents reports format
prowler azure -M csv json-asff json-ocsf html
# List the available checks and services
prowler azure --list-checks
prowler azure --list-services
#Running an HTML Dashboard
prowler dashboard
