AWS CodeBuild - Untrusted PR Webhook Bypass (CodeBreach-style)

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Questo vettore di attacco si presenta quando un workflow PR esposto pubblicamente è collegato a un progetto CodeBuild privilegiato con controlli webhook deboli.

Se un attacker esterno riesce a far eseguire a CodeBuild la loro pull request, di solito può ottenere l’esecuzione di codice arbitrario all’interno della build (script di build, hook delle dipendenze, script di test, ecc.), e poi pivotare verso secrets, credenziali IAM o credenziali del provider di sorgente.

Why this is dangerous

I filtro webhook di CodeBuild sono valutati con pattern regex (per i filtri diversi da EVENT). Nel filtro ACTOR_ACCOUNT_ID, questo significa che un pattern debole può corrispondere a piÚ utenti del previsto. Se PR non attendibili vengono costruite in un progetto che ha permessi role AWS privilegiati o credenziali GitHub, questo può diventare una compromissione completa della supply-chain.

Wiz ha mostrato una catena pratica dove:

  1. Una allowlist di actor del webhook usava una regex non ancorata.
  2. Un attacker ha registrato un ID GitHub che corrispondeva come superstringa di un ID trusted.
  3. Una PR malevola ha triggerato CodeBuild.
  4. L’esecuzione del codice nella build è stata usata per dumpare memoria e recuperare credenziali/token del provider di sorgente.

Misconfigurations that allow external PR code execution

Di seguito gli errori ad alto rischio e come gli attacker abusano di ciascuno:

  1. EVENT filters allow untrusted triggers
  • Eventi comunemente rischiosi: PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED, PULL_REQUEST_REOPENED.
  • Altri eventi che possono diventare pericolosi se collegati a build privilegiate: PUSH, PULL_REQUEST_CLOSED, PULL_REQUEST_MERGED, RELEASED, PRERELEASED, WORKFLOW_JOB_QUEUED.
  • Pericoloso: EVENT="PUSH, PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED" in un progetto privilegiato.
  • Consigliato: usare approvazione tramite commento su PR e minimizzare gli eventi di trigger per i progetti privilegiati.
  • Abuso: l’attacker apre/aggiorna una PR o push su un branch che controlla, e il proprio codice viene eseguito in CodeBuild.
  1. ACTOR_ACCOUNT_ID regex is weak
  • Pericoloso: pattern non ancorati come 123456|7890123.
  • Consigliato: ancorare con corrispondenza esatta ^(123456|7890123)$.
  • Abuso: l’over-match della regex permette a ID GitHub non autorizzati di passare le allowlist.
  1. Other regex filters are weak or missing
  • HEAD_REF
    • Pericoloso: refs/heads/.*
    • Consigliato: ^refs/heads/main$ (o una lista esplicita di branch trusted)
  • BASE_REF
    • Pericoloso: .*
    • Consigliato: ^refs/heads/main$
  • FILE_PATH
    • Pericoloso: nessuna restrizione sui percorsi
    • Consigliato: escludere file rischiosi come ^buildspec\\.yml$, ^\\.github/workflows/.*, (^|/)package(-lock)?\\.json$
  • COMMIT_MESSAGE
    • Pericoloso: fidarsi di un marcatore nel commit con match permissivo come trusted
    • Consigliato: non usare il commit message come confine di trust per l’esecuzione delle PR
  • REPOSITORY_NAME / ORGANIZATION_NAME
    • Pericoloso: .* in webhook a livello org/globale
    • Consigliato: corrispondenze esatte solo per repo/org
  • WORKFLOW_NAME
    • Pericoloso: .*
    • Consigliato: corrispondenze esatte del nome del workflow (o evitare di usare questo come meccanismo di trust)
  • Abuso: l’attacker costruisce ref/path/message/context del repo in modo da soddisfare una regex permissiva e triggerare le build.
  1. excludeMatchedPattern is misused
  • Impostare questo flag in modo errato può invertire la logica desiderata.
  • Pericoloso: FILE_PATH '^buildspec\\.yml$' con excludeMatchedPattern=false quando l’intento era bloccare modifiche a buildspec.
  • Consigliato: stesso pattern con excludeMatchedPattern=true per negare build che toccano buildspec.yml.
  • Abuso: i defender pensano di negare eventi/percorsi/actor rischiosi, ma in realtĂ  li consentono.
  1. Multiple filterGroups create accidental bypasses
  • CodeBuild valuta i gruppi come OR (basta che un gruppo passi).
  • Pericoloso: un gruppo rigido + un gruppo fallback permissivo (es., solo EVENT=PULL_REQUEST_UPDATED).
  • Consigliato: rimuovere gruppi fallback che non applicano vincoli su actor/ref/path.
  • Abuso: l’attacker ha bisogno solo di soddisfare il gruppo piĂš debole.
  1. Comment approval gate disabled or too permissive
  • pullRequestBuildPolicy.requiresCommentApproval=DISABLED è il meno sicuro.
  • Ruoli approvatori troppo estesi riducono il controllo.
  • Pericoloso: requiresCommentApproval=DISABLED.
  • Consigliato: ALL_PULL_REQUESTS o FORK_PULL_REQUESTS con ruoli approvatori ristretti.
  • Abuso: PR da fork/drive-by eseguono automaticamente senza approvazione di maintainer trusted.
  1. No restrictive branch/path strategy for PR builds
  • Mancanza di defense-in-depth con HEAD_REF + BASE_REF + FILE_PATH.
  • Pericoloso: solo EVENT + ACTOR_ACCOUNT_ID, senza controlli su ref/path.
  • Consigliato: combinare ACTOR_ACCOUNT_ID esatto + BASE_REF + HEAD_REF + restrizioni FILE_PATH.
  • Abuso: l’attacker modifica input di build (buildspec/CI/dipendenze) e ottiene esecuzione di comandi arbitrari.
  1. Public visibility + status URL exposure
  • URL di build/check pubblici facilitano il ricon e i test iterativi dell’attacker.
  • Pericoloso: projectVisibility=PUBLIC_READ con log/config sensibili in build pubbliche.
  • Consigliato: mantenere i progetti privati a meno di forti necessitĂ  business, e sanitizzare log/artifact.
  • Abuso: l’attacker scopre pattern/comportamento del progetto e poi affina payload e tentativi di bypass.

Token leakage from memory

La write-up di Wiz spiega che le credenziali del provider di sorgente sono presenti nel contesto di runtime della build e possono essere rubate dopo una compromissione della build (per esempio tramite memory dumping), permettendo il takeover del repository se gli scope sono ampi.

AWS ha introdotto hardening dopo la disclosure, ma la lezione principale rimane: non eseguire codice di PR non attendibili in contesti di build privilegiati e assumere che codice controllato dall’attacker tenterà di rubare credenziali.

Per tecniche aggiuntive di credential theft in CodeBuild, consulta anche:

AWS Codebuild - Token Leakage

Finding CodeBuild URLs in GitHub PRs

Se CodeBuild riporta lo stato back a GitHub, l’URL della build di CodeBuild di solito appare in:

  1. PR page -> Checks tab (o la linea di stato in Conversation/Commits).
  2. Commit page -> sezione status/checks -> link Details.
  3. PR commits list -> cliccare il contesto di check allegato a un commit.

Per progetti pubblici, questo link può esporre metadata/configurazione della build ad utenti non autenticati.

Script: rileva URL CodeBuild in una PR e verifica se appaiono pubblici ```bash #!/usr/bin/env bash set -euo pipefail

Usage:

./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”

Testato con:
```bash
bash /tmp/check_pr_codebuild_urls.sh carlospolop codebuild-codebreach-ctf-lab 1

Checklist rapida di 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

Controlla ogni progetto per:

  • webhook.filterGroups containing PR events.
  • ACTOR_ACCOUNT_ID patterns that are not anchored with ^...$.
  • pullRequestBuildPolicy.requiresCommentApproval equal to DISABLED.
  • Assenza di restrizioni su branch/percorso.
  • serviceRole ad alto privilegio.
  • Ambito e riuso rischiosi delle source credentials.

Linee guida di hardening

  1. Richiedi approvazione via commento per le build PR (ALL_PULL_REQUESTS o FORK_PULL_REQUESTS).
  2. Se usi allowlist di actor, ancora le regex e mantienile esatte.
  3. Aggiungi restrizioni FILE_PATH per evitare modifiche non attendibili a buildspec.yml e script CI.
  4. Separa le build di release affidabili dalle build PR non affidabili in progetti/ruoli separati.
  5. Usa token del source-provider a granularitĂ  fine e con privilegi minimi (preferisci identitĂ  dedicate a basso privilegio).
  6. Monitora continuamente i filtri webhook e l’uso delle credenziali sorgenti.

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks