# Az - Automation Accounts

{{#include ../../../banners/hacktricks-training.md}}

## 基本情報

Azure Automation Accountsは、Microsoft Azureのクラウドベースのサービスで、リソース管理、構成、更新などのタスクを**自動化**するのに役立ちます。これにより、Azureおよびオンプレミス環境全体での効率と一貫性を向上させるためのインフラストラクチャをコード（IaC）として提供し、**Runbooks**（実行される自動化用のスクリプト）、**スケジュール**、および**ハイブリッドワーカーグループ**を提供します。

### 設定

- **資格情報**: パスワードは自動化アカウント内のRunbook内でのみアクセス可能で、**ユーザー名とパスワードを安全に保存する**ために使用されます。
- **変数**: Runbook内で使用できる**構成データ**を保存するために使用されます。これにはAPIキーなどの機密情報も含まれる可能性があります。変数が**暗号化されて保存されている**場合、それは自動化アカウント内のRunbook内でのみ利用可能です。
- **証明書**: Runbook内で使用できる**証明書**を保存するために使用されます。
- **接続**: 外部サービスへの**接続情報**を保存するために使用されます。これには**機密情報**が含まれる可能性があります。
- **ネットワークアクセス**: **公開**または**プライベート**に設定できます。

### Runbooks & Jobs

Azure AutomationのRunbookは、クラウド環境内でタスクを**自動的に実行するスクリプト**です。RunbookはPowerShell、Python、またはグラフィカルエディタで記述できます。これにより、VM管理、パッチ適用、コンプライアンスチェックなどの管理タスクを自動化できます。

**Runbooks**内の**コード**には**機密情報**（資格情報など）が含まれる可能性があります。

**ジョブはRunbook実行のインスタンス**です。Runbookを実行すると、実行を追跡するためのジョブが作成されます。各ジョブには以下が含まれます：

- **ステータス**: キュー待ち、実行中、完了、失敗、保留。
- **出力**: Runbook実行の結果。
- **開始および終了時間**: ジョブが開始および完了した時間。

ジョブには**Runbook**実行の**出力**が含まれます。**ジョブ**を**読み取る**ことができる場合は、実行の**出力**（潜在的な**機密情報**）が含まれているため、必ず行ってください。

### スケジュール & Webhooks

Runbookを実行する主な方法は3つあります：

- **スケジュール**: 特定の**時間**または**間隔**でRunbookを**トリガー**するために使用されます。
- **Webhooks**: 外部サービスからRunbookを**トリガー**するために使用できる**HTTPエンドポイント**です。作成後、Webhook URLは**表示されません**。
- **手動トリガー**: AzureポータルおよびCLIからRunbookを**手動でトリガー**できます。

### ソース管理

**Github、Azure Devops (Git)、およびAzure Devops (TFVC)**からRunbookをインポートすることができます。リポジトリのRunbookをAzure Automationアカウントに公開するように指示することも、リポジトリからAzure Automationアカウントに**変更を同期**するように指示することも可能です。

同期が有効になっている場合、**GithubリポジトリにWebhookが作成され**、プッシュイベントが発生するたびに同期がトリガーされます。Webhook URLの例: `https://f931b47b-18c8-45a2-9d6d-0211545d8c02.webhook.eus.azure-automation.net/webhooks?token=DRjQyFiOrUtz%2fw7o23XbDpOlTe1%2bUqPQm4pQH2WBfJg%3d`

これらのWebhookは、Githubリポジトリに関連付けられたRunbookのWebhookをリストする際に**表示されません**。また、作成後にソース管理のリポジトリURLを**変更することはできません**。

構成されたソース管理が機能するためには、**Azure Automation Account**に**`Contributor`**ロールを持つマネージドアイデンティティ（システムまたはユーザー）が必要です。さらに、Automation Accountにユーザーマネージドアイデンティティを割り当てるには、変数**`AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID`**にユーザーMIのクライアントIDを指定する必要があります。

### ランタイム環境

Runbookを作成する際に、ランタイム環境を選択できます。デフォルトでは、以下のランタイム環境が利用可能です：

- **Powershell 5.1**
- **Powershell 7.1**
- **PowerShell 7.2**
- **Python 3.10**
- **Python 3.8**
- **Python 2.7**

ただし、これらのいずれかをベースにして**独自の環境を作成する**ことも可能です。Pythonの場合、使用する環境に`.whl`パッケージをアップロードできます。PowerShellの場合、ランタイムに必要なモジュールを含む`.zip`パッケージをアップロードできます。

### ハイブリッドワーカーグループ

Azure Automationでは、Runbookのデフォルトの実行環境は**Azure Sandbox**であり、Azureによって管理されるクラウドベースのプラットフォームで、Azureリソースに関わるタスクに適しています。ただし、このサンドボックスには、オンプレミスリソースへのアクセス制限や実行時間およびリソース使用の制約などの制限があります。これらの制限を克服するために、ハイブリッドワーカーグループが使用されます。ハイブリッドワーカーグループは、**自分のマシンにインストールされた1つ以上のハイブリッドRunbookワーカー**で構成され、オンプレミス、他のクラウド環境、またはAzure VM上で動作します。このセットアップにより、Runbookはこれらのマシン上で直接実行され、ローカルリソースへの直接アクセス、より長くリソース集約的なタスクの実行、Azureの即時の範囲を超えた環境との相互作用の柔軟性が提供されます。

ハイブリッドワーカーグループを作成する際には、使用する**資格情報**を指定する必要があります。2つのオプションがあります：

- **デフォルトの資格情報**: 資格情報を提供する必要はなく、Runbookは**System**としてVM内で実行されます。
- **特定の資格情報**: 自動化アカウント内の資格情報オブジェクトの名前を提供する必要があり、これが**VM内でRunbookを実行するために使用されます**。したがって、この場合、VMの**有効な資格情報を盗む**ことが可能です。

したがって、**ハイブリッドワーカー**で**Runbook**を実行することを選択できる場合、**System**として外部マシン内で**任意のコマンドを実行**することになります（良いピボット技術）。

さらに、ハイブリッドワーカーがAzureで他のマネージドアイデンティティと共に実行されている場合、Runbookは**RunbookのマネージドアイデンティティとVMのすべてのマネージドアイデンティティにメタデータサービスからアクセスできる**ようになります。

> [!TIP]
> **メタデータサービス**のURLは、Automationアカウントのマネージドアイデンティティトークンを取得するサービスとは異なるURL（**`http://169.254.169.254`**）であることを忘れないでください。

### 状態構成 (SC)

> [!WARNING]
> [ドキュメント](https://learn.microsoft.com/en-us/azure/automation/automation-dsc-overview)に示されているように、Azure Automation State Configurationは2027年9月30日に廃止され、[Azure Machine Configuration](https://learn.microsoft.com/en-us/azure/governance/machine-configuration/overview)に置き換えられます。

Automation Accountsは、**状態構成 (SC)**もサポートしており、これはVMの**状態**を**構成**および**維持**するのに役立つ機能です。**Windows**および**Linux**マシンにDSC構成を**作成**および**適用**することが可能です。

攻撃者の視点から見ると、これは**すべての構成されたVMで任意のPSコードを実行する**ことを可能にし、これらのVMのマネージドアイデンティティへの権限昇格を許可し、新しいネットワークへのピボットを可能にするため、興味深いものでした... また、構成には**機密情報**が含まれる可能性があります。

## 列挙
```bash
# List Automation Accounts
az automation account list --output table

# Get Automation Account details
# Check the network access in `privateEndpointConnections` and `publicNetworkAccess`
# Check the managed identities in `identity`
az automation account show --name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME>

# Get keys of automation account
## These are used for the DSC
az automation account list-keys --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME>

# Get schedules of automation account
az automation schedule list --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME>

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

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

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

# Get credential details
## Note that you will only be able to access the password from inside a Runbook
az rest --method GET \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/credentials/<credential-name>?api-version=2023-11-01"

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

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

# Get variables of automation account
## It's possible to get the value of unencrypted variables but not the encrypted ones
az rest --method GET \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/variables?api-version=2023-11-01"

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

# Get runbooks of an automation account
az automation runbook list --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME>

# Get runbook details
az automation runbook show --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME> --name <RUNBOOK-NAME>

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

# Get jobs of an automation account
az automation job list --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME>

# Get job details
az automation job show --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME> --name <JOB-NAME>

# Get job output
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"

# Get the Runbook content when the job was executed
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>/runbookContent?api-version=2023-11-01"

# Get webhooks inside an automation account
## It's possible to see to which runbook it belongs in the given data
## For security reasons it's not possible to see the URL of the webhook after creating it, here is a URL example: https://f931b47b-18c8-45a2-9d6d-0211545d8c02.webhook.eus.azure-automation.net/webhooks?token=dOdnxk6z7ugAxiuyUMKgPuDMav2Jw5EJediMdiN4jLo%3d
## Generating a webhook can be useful from a persistence perspective
az rest --method GET \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/webhooks?api-version=2018-06-30"

# Get the source control setting of an automation account (if any)
## inside the output it's possible to see if the autoSync is enabled, if the publishRunbook is enabled and the repo URL
az automation source-control list --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME>

# Get custom runtime environments
## Check in defaultPackages for custom ones, by default Python envs won't have anything here and PS1 envs will have "az" and "azure cli"
az automation runtime-environment list \
--resource-group <res-group>> \
--automation-account-name <account-name> \
--query "[?!(starts_with(description, 'System-generated'))]"

# Get State Configurations (SC) of an automation account
az automation dsc configuration list --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME>

# Get State Configuration details
az automation dsc configuration show --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME> --name <DSC-CONFIG-NAME>

# Get State Configuration content
az automation dsc configuration show-content --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME> --name <DSC-CONFIG-NAME>

# Get hybrid worker groups for an automation account
az automation hrwg list --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME>

# Get hybrid worker group details
az automation hrwg show --automation-account-name <AUTOMATION-ACCOUNT> --resource-group <RG-NAME> --name <HYBRID-WORKER-GROUP>

# Get more details about a hybrid worker group (like VMs inside it)
az rest --method GET --url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/hybridRunbookWorkerGroups/<hybrid-worker-group-name>/hybridRunbookWorkers?&api-version=2021-06-22"
```

```bash
# Check user right for automation
az extension add --upgrade -n automation
az automation account list # if it doesn't return anything the user is not a part of an Automation group

# Gets Azure Automation accounts in a resource group
Get-AzAutomationAccount

# List & get DSC configs
Get-AzAutomationAccount | Get-AzAutomationDscConfiguration
Get-AzAutomationAccount | Get-AzAutomationDscConfiguration | where {$_.name -match '<name>'} | Export-AzAutomationDscConfiguration -OutputFolder . -Debug
## Automation Accounts named SecurityBaselineConfigurationWS... are there by default (not interesting)

# List & get Run books code
Get-AzAutomationAccount | Get-AzAutomationRunbook
Get-AzAutomationAccount | Get-AzAutomationRunbook | Export-AzAutomationRunbook -OutputFolder /tmp

# List credentials & variables & others
Get-AzAutomationAccount | Get-AzAutomationCredential
Get-AzAutomationAccount | Get-AzAutomationVariable
Get-AzAutomationAccount | Get-AzAutomationConnection
Get-AzAutomationAccount | Get-AzAutomationCertificate
Get-AzAutomationAccount | Get-AzAutomationSchedule
Get-AzAutomationAccount | Get-AzAutomationModule
Get-AzAutomationAccount | Get-AzAutomationPython3Package
## Exfiltrate credentials & variables and the other info loading them in a Runbook and printing them

# List hybrid workers
Get-AzAutomationHybridWorkerGroup -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME>
```
## 権限昇格とポストエクスプロイト

{{#ref}}
../az-privilege-escalation/az-automation-accounts-privesc.md
{{#endref}}

## 永続性

{{#ref}}
../az-persistence/az-automation-accounts-persistence.md
{{#endref}}

## 参考文献

- [https://learn.microsoft.com/en-us/azure/automation/overview](https://learn.microsoft.com/en-us/azure/automation/overview)
- [https://learn.microsoft.com/en-us/azure/automation/automation-dsc-overview](https://learn.microsoft.com/en-us/azure/automation/automation-dsc-overview)
- [https://github.com/rootsecdev/Azure-Red-Team#runbook-automation](https://github.com/rootsecdev/Azure-Red-Team#runbook-automation)

{{#include ../../../banners/hacktricks-training.md}}
