AZ CLI

Virtual Machines

Enumerating VM’s

for a in $(cat azure_subscriptions.txt); do az vm list --subscription $a >> vm_$a.txt; done


App Registrations

Retrieve API Permissions

az ad app list --query '[].{Name:displayName,API:requiredResourceAccess[]}' --all

Check (https://s1hb.sharepoint.com/:x:/g/Technical%20Resources/EQGFqPrbAZBEiGtPa0BChucBBN4aCzF_2lsliHlzx9Oaag?e=6Bz3lU) for the resourceAccess ID to determine what permissions is given for the resourceAccess scope.

Functions

Generate Function Config Statements

for a in $(cat azure_subscriptions.txt); do az functionapp list --subscription $a | jq -rj '.[] | "az functionapp config appsettings list --name ", .name, " --resource-group ", .resourceGroup, .name,"\n"' >> all_function_config_statements.sh; done


Blob Public Access

Query Storage Accounts for Blob Public Access

az storage account list | jq -r '.[] | "Name: " + .name + " | Public Access: " + (.allowBlobPublicAccess|tostring)'


Classic Resources

Generate List of Classic Resources

az resource list | jq -r '.[].id' | grep -i classic | grep -v Tutorial > all_classic_resources.txt


Runbooks

Extract all the Runbooks for all the Automation Accounts for all the Resource Groups

Get-AzAutomationAccount|foreach{Get-AzAutomationRunbook $_.ResourceGroupName $_.AutomationAccountName|foreach{Export-AzAutomationRunbook $_.ResourceGroupName $_.AutomationAccountName $_.Name}}


Web Applications

Extract Hostnames from Websites and Website Slots

az graph query -q "resources | where type == 'microsoft.web/sites' or type == 'microsoft.web/sites/slots' | extend resourceProperties = parse_json(properties) | extend defaultHostName = tostring(resourceProperties.defaultHostName) | project defaultHostName" | jq -r '.data | .[].defaultHostName' >> all_webapp_urls.txt


Managed Identities

Extract managed identities being used by virtual machines

(az vm list | ConvertFrom-Json) | ForEach-Object {$_.name;(az vm identity show --resource-group $_.resourceGroup --name $_.name | ConvertFrom-Json)}


Deployment Parameters

Extracting sensitive data from parameters

Get-AzResourceGroup |Get-AzResourceGroupDeployment >> deployments.txt


RunBook to Extract Managed Identity SP JWT

$tokenAuthURI = $env:MSI_ENDPOINT + “?resource=https://graph.microsoft.com/&api-version=2017-09-01"$tokenResponse = Invoke-RestMethod -Method Get -Headers @{“Secret”=”$env:MSI_SECRET”} -Uri $tokenAuthURI$tokenResponse.access_token

RunBook to Extract Run As SP JWT

$connectionName = “AzureRunAsConnection”  
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName$TenantId = $servicePrincipalConnection.TenantId  
$ClientId = $servicePrincipalConnection.ApplicationId  
$CertificateThumbprint = $servicePrincipalConnection.CertificateThumbprintfunction GenerateJWT (){  
    $thumbprint = $CertificateThumbprint    $cert = Get-Item Cert:\CurrentUser\My\$Thumbprint    $hash = $cert.GetCertHash()  
    $hashValue = [System.Convert]::ToBase64String($hash) -replace ‘\+’,’-’ -replace ‘/’,’_’ -replace ‘=’    $exp = ([DateTimeOffset](Get-Date).AddHours(1).ToUniversalTime()).ToUnixTimeSeconds()  
    $nbf = ([DateTimeOffset](Get-Date).ToUniversalTime()).ToUnixTimeSeconds()    $jti = New-Guid  
    [hashtable]$header = @{alg = “RS256”; typ = “JWT”; x5t=$hashValue}  
    [hashtable]$payload = @{aud = “https://login.microsoftonline.com/$TenantId/oauth2/token"; iss = “$ClientId”; sub=”$ClientId”; jti = “$jti”; exp = $Exp; Nbf= $Nbf}  
    $headerjson = $header | ConvertTo-Json -Compress  
    $payloadjson = $payload | ConvertTo-Json -Compress    $headerjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($headerjson)).Split(‘=’)[0].Replace(‘+’, ‘-’).Replace(‘/’, ‘_’)  
    $payloadjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($payloadjson)).Split(‘=’)[0].Replace(‘+’, ‘-’).Replace(‘/’, ‘_’)    $toSign = [System.Text.Encoding]::UTF8.GetBytes($headerjsonbase64 + “.” + $payloadjsonbase64)    $rsa = $cert.PrivateKey -as [System.Security.Cryptography.RSACryptoServiceProvider]    $signature = [Convert]::ToBase64String($rsa.SignData($toSign,[Security.Cryptography.HashAlgorithmName]::SHA256,[Security.Cryptography.RSASignaturePadding]::Pkcs1)) -replace ‘\+’,’-’ -replace ‘/’,’_’ -replace ‘=’    $token = “$headerjsonbase64.$payloadjsonbase64.$signature”    return $token  
}$reqToken = GenerateJWT$Body = @{  
    scope = “https://graph.microsoft.com/.default"  
    client_id = $ClientId  
    client_assertion_type = “urn:ietf:params:oauth:client-assertion-type:jwt-bearer”  
    client_assertion = $reqToken  
    grant_type = “client_credentials” `  
}$MGToken = Invoke-RestMethod `  
    -URI “https://login.microsoftonline.com/$($TenantId)/oauth2/v2.0/token" `  
    -Body $Body `  
    -Method POST  
$MGToken.access_token

DevOps

Retrive Projects for Organization

Useful for most of the DevOps commands.

az devops project list --organization https://dev.azure.com/ORGANIZATION_NAME | jq -r '.value[].name'

Retrieve Projects and their Releases

Search release scripts for plaintext passwords, keys, and tokens

$orgUrl = 'https://dev.azure.com/ORGANIZATION_NAME'

az devops project list --organization $orgUrl | jq -r '.value[].name' | ForEach-Object { az pipelines release list --organization $orgUrl --project $_ | jq -r '.[].url' }