AWS CodeBuild - Contournement de webhook PR non fiable (CodeBreach-style)
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Ce vecteur d’attaque apparaît lorsqu’un workflow PR public est connecté à un projet CodeBuild privilégié avec des contrôles de webhook faibles.
Si un attaquant externe peut faire exécuter sa pull request par CodeBuild, il peut généralement obtenir une exécution de code arbitraire à l’intérieur du build (scripts de build, hooks de dépendances, scripts de test, etc.), puis pivoter vers des secrets, des credentials IAM, ou des credentials du fournisseur de source.
Pourquoi c’est dangereux
Les filtres de webhook CodeBuild sont évalués avec des patterns regex (pour les filtres non EVENT). Dans le filtre ACTOR_ACCOUNT_ID, cela signifie qu’un pattern faible peut correspondre à plus d’utilisateurs que prévu.
Si des PR non fiables sont bâties dans un projet qui dispose de permissions de rôle AWS privilégiées ou d’identifiants GitHub, cela peut devenir une compromission complète de la chaîne d’approvisionnement.
Wiz a montré une chaîne pratique où :
- Une allowlist d’acteurs du webhook utilisait une regex non ancrée.
- Un attaquant a enregistré un ID GitHub qui correspondait comme un superstring d’un ID de confiance.
- Une PR malveillante a déclenché CodeBuild.
- L’exécution du code du build a été utilisée pour dumper la mémoire et récupérer des credentials/tokens du fournisseur de source.
Mauvaises configurations permettant l’exécution de code de PR externes
Les erreurs à haut risque suivantes et la façon dont les attaquants les abusent :
EVENTfilters allow untrusted triggers
- Événements risqués courants :
PULL_REQUEST_CREATED,PULL_REQUEST_UPDATED,PULL_REQUEST_REOPENED. - Autres événements pouvant devenir dangereux si liés à des builds privilégiés :
PUSH,PULL_REQUEST_CLOSED,PULL_REQUEST_MERGED,RELEASED,PRERELEASED,WORKFLOW_JOB_QUEUED. - Bad:
EVENT="PUSH, PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED"dans un projet privilégié. - Better: utiliser une approbation par commentaire pour les PR et minimiser les événements déclencheurs pour les projets privilégiés.
- Abuse: l’attaquant ouvre/met à jour une PR ou pousse sur une branche qu’il contrôle, et son code s’exécute dans CodeBuild.
ACTOR_ACCOUNT_IDregex is weak
- Bad: patterns non ancrés comme
123456|7890123. - Better: ancrage exact
^(123456|7890123)$. - Abuse: un over-match de la regex permet à des IDs GitHub non autorisés de passer les allowlists.
- Other regex filters are weak or missing
HEAD_REF- Bad:
refs/heads/.* - Better:
^refs/heads/main$(ou une liste explicite de branches de confiance) BASE_REF- Bad:
.* - Better:
^refs/heads/main$ FILE_PATH- Bad: pas de restrictions de chemin
- Better: exclure les fichiers à risque comme
^buildspec\\.yml$,^\\.github/workflows/.*,(^|/)package(-lock)?\\.json$ COMMIT_MESSAGE- Bad: marqueur de confiance avec un match lâche comme
trusted - Better: ne pas utiliser le message de commit comme frontière de confiance pour l’exécution des PR
REPOSITORY_NAME/ORGANIZATION_NAME- Bad:
.*dans les webhooks org/globaux - Better: correspondances exactes repo/org uniquement
WORKFLOW_NAME- Bad:
.* - Better: correspondances exactes du nom du workflow uniquement (ou éviter cela comme contrôle de confiance)
- Abuse: l’attaquant construit un ref/chemin/message/contexte de repo pour satisfaire une regex permissive et déclencher des builds.
excludeMatchedPatternis misused
- Définir ce flag incorrectement peut inverser la logique voulue.
- Bad:
FILE_PATH '^buildspec\\.yml$'avecexcludeMatchedPattern=falsealors que l’intention était de bloquer les edits de buildspec. - Better: même pattern avec
excludeMatchedPattern=truepour refuser les builds touchantbuildspec.yml. - Abuse: les défenseurs pensent qu’ils refusent des événements/chemins/acteurs risqués, mais en réalité ils les autorisent.
- Multiple
filterGroupscreate accidental bypasses
- CodeBuild évalue les groupes comme un OR (un groupe passant suffit).
- Bad: un groupe strict + un groupe fallback permissif (par ex., seulement
EVENT=PULL_REQUEST_UPDATED). - Better: supprimer les groupes fallback qui n’appliquent pas de contraintes actor/ref/path.
- Abuse: l’attaquant n’a besoin que de satisfaire le groupe le plus faible.
- Comment approval gate disabled or too permissive
pullRequestBuildPolicy.requiresCommentApproval=DISABLEDest le moins sûr.- Des rôles d’approbateur trop larges réduisent le contrôle.
- Bad:
requiresCommentApproval=DISABLED. - Better:
ALL_PULL_REQUESTSouFORK_PULL_REQUESTSavec des rôles d’approbateurs minimaux. - Abuse: les PRs fork/drive-by s’exécutent automatiquement sans approbation d’un mainteneur de confiance.
- No restrictive branch/path strategy for PR builds
- Absence de défense en profondeur avec
HEAD_REF+BASE_REF+FILE_PATH. - Bad: seulement
EVENT+ACTOR_ACCOUNT_ID, pas de contrôles ref/path. - Better: combiner des restrictions exactes
ACTOR_ACCOUNT_ID+BASE_REF+HEAD_REF+FILE_PATH. - Abuse: l’attaquant modifie les entrées du build (buildspec/CI/dépendances) et obtient une exécution de commande arbitraire.
- Public visibility + status URL exposure
- Les URLs publiques des builds/checks facilitent la reconnaissance et les tests itératifs de l’attaquant.
- Bad:
projectVisibility=PUBLIC_READavec des logs/config sensibles dans des builds publics. - Better: garder les projets privés sauf besoin business fort, et assainir logs/artifacts.
- Abuse: l’attaquant découvre des patterns/comportements du projet, puis affine les payloads et les tentatives de contournement.
Token leakage from memory
Le write-up de Wiz explique que les credentials du fournisseur de source sont présents dans le contexte d’exécution du build et peuvent être volés après compromission du build (par exemple via un dump mémoire), permettant la prise de contrôle du repository si les scopes sont larges.
AWS a introduit des durcissements après la divulgation, mais la leçon principale reste : ne jamais exécuter du code de PR non fiable dans des contextes de build privilégiés et supposez que le code de build contrôlé par un attaquant tentera de voler des credentials.
Pour des techniques supplémentaires de vol de credentials dans CodeBuild, voir aussi :
Finding CodeBuild URLs in GitHub PRs
Si CodeBuild rapporte le statut sur GitHub, l’URL du build CodeBuild apparaît généralement dans :
- PR page -> Checks tab (ou la ligne de statut dans Conversation/Commits).
- Commit page -> section status/checks -> lien Details.
- PR commits list -> cliquer sur le contexte de check attaché à un commit.
Pour les projets publics, ce lien peut exposer des métadonnées/configuration du build à des utilisateurs non authentifiés.
Script : détecter les CodeBuild URLs dans une PR et tester si elles semblent publiques
```bash #!/usr/bin/env bash set -euo pipefailUsage:
./check_pr_codebuild_urls.sh <pr_number>
Requirements: gh, jq, curl
OWNER=“${1:?owner}” REPO=“${2:?repo}” PR=“${3:?pr_number}”
for bin in gh jq curl timeout; do command -v “$bin” >/dev/null || { echo “[!] Missing dependency: $bin” >&2; exit 1; } done
tmp_commits=“$(mktemp)” tmp_urls=“$(mktemp)” trap ‘rm -f “$tmp_commits” “$tmp_urls”’ EXIT
gh_api() { timeout 20s gh api “$@” 2>/dev/null || true }
Get all commit SHAs in the PR (bounded call to avoid hangs)
gh_api “repos/${OWNER}/${REPO}/pulls/${PR}/commits” –paginate –jq ‘.[].sha’ > “$tmp_commits” if [ ! -s “$tmp_commits” ]; then echo “[!] No commits found (or API call timed out/failed).” >&2 exit 1 fi
echo “[*] PR commits:” cat “$tmp_commits” echo
echo “[*] Searching commit statuses/check-runs for CodeBuild URLs…”
while IFS= read -r sha; do [ -z “$sha” ] && continue
Classic commit statuses (target_url)
gh_api “repos/${OWNER}/${REPO}/commits/${sha}/status”
–jq ‘.statuses[]? | .target_url // empty’ 2>/dev/null || true
GitHub Checks API (details_url)
gh_api “repos/${OWNER}/${REPO}/commits/${sha}/check-runs”
–jq ‘.check_runs[]? | .details_url // empty’ 2>/dev/null || true
done < “$tmp_commits” | sort -u > “$tmp_urls”
grep -Ei ‘codebuild|codebuild.aws.amazon.com|console.aws.amazon.com/.*/codebuild’ “$tmp_urls” || true
echo echo “[*] Public-access heuristic:” echo “ - If URL redirects to signin.aws.amazon.com -> likely not public“ echo “ - If URL is directly reachable (HTTP 200) without auth redirect -> potentially public“ echo
cb_urls=“$(grep -Ei ‘codebuild|codebuild.aws.amazon.com|console.aws.amazon.com/./codebuild’ “$tmp_urls” || true)“ if [ -z “$cb_urls” ]; then echo “[] No CodeBuild URLs found in PR statuses/check-runs.” exit 0 fi
while IFS= read -r url; do [ -z “$url” ] && continue final_url=“$(timeout 20s curl -4 -sS -L –connect-timeout 5 –max-time 20 -o /dev/null -w ‘%{url_effective}’ “$url” || true)“ code=“$(timeout 20s curl -4 -sS -L –connect-timeout 5 –max-time 20 -o /dev/null -w ‘%{http_code}’ “$url” || true)“
if echo “$final_url” | grep -qi ‘signin.aws.amazon.com’; then verdict=“NOT_PUBLIC_OR_AUTH_REQUIRED” elif [ “$code” = “200” ]; then verdict=“POTENTIALLY_PUBLIC” else verdict=“UNKNOWN_CHECK_MANUALLY” fi
printf ‘%s\t%s\t%s\n’ “$verdict” “$code” “$url” done <<< “$cb_urls”
Testé avec :
```bash
bash /tmp/check_pr_codebuild_urls.sh carlospolop codebuild-codebreach-ctf-lab 1
Liste de vérification rapide pour l’audit
# Enumerate projects
aws codebuild list-projects
# Inspect source/webhook configuration
aws codebuild batch-get-projects --names <project-name>
# Inspect global source credentials configured in account
aws codebuild list-source-credentials
Examinez chaque projet pour :
webhook.filterGroupscontenant des événements PR.- des patterns
ACTOR_ACCOUNT_IDqui ne sont pas ancrés avec^...$. pullRequestBuildPolicy.requiresCommentApprovalégal àDISABLED.- absence de restrictions de branche/chemin.
serviceRoleà privilèges élevés.- portée et réutilisation risquées des identifiants source.
Conseils de durcissement
- Exiger l’approbation par commentaire pour les builds PR (
ALL_PULL_REQUESTSouFORK_PULL_REQUESTS). - Si vous utilisez des allowlists d’acteurs, ancrez les regex et gardez-les exactes.
- Ajoutez des restrictions
FILE_PATHpour éviter des modifications non fiables debuildspec.ymlet des scripts CI. - Séparez les builds de release de confiance des builds PR non fiables en projets/rôles différents.
- Utilisez des tokens de fournisseur source à granularité fine et au moindre privilège (préférez des identités dédiées à faibles privilèges).
- Auditez en continu les filtres webhook et l’utilisation des identifiants source.
References
- Wiz: CodeBreach - AWS CodeBuild ACTOR_ID regex bypass and token theft
- AWS CodeBuild API - WebhookFilter
- AWS CLI - codebuild create-webhook
- AWS CodeBuild User Guide - Best practices for webhooks
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks Cloud

