AWS CodeBuild - Untrusted PR Webhook Bypass (CodeBreach-style)
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Dieser Angriffsvektor tritt auf, wenn ein öffentlich zugänglicher PR-Workflow mit einem privilegierten CodeBuild-Projekt verbunden ist, das schwache Webhook-Kontrollen hat.
Wenn ein externer Angreifer CodeBuild dazu bringen kann, seine Pull Request auszuführen, kann er in der Regel eine beliebige Codeausführung im Build (Build-Skripte, Dependency-Hooks, Testskripte usw.) erreichen und anschließend auf Geheimnisse, IAM-Anmeldeinformationen oder Source-Provider-Anmeldeinformationen pivotieren.
Warum das gefährlich ist
CodeBuild-Webhooks werden für Nicht-EVENT-Filter mit Regex-Pattern ausgewertet. Im ACTOR_ACCOUNT_ID-Filter bedeutet das, dass ein schwaches Pattern mehr Benutzer matchen kann als beabsichtigt.
Wenn unvertrauenswürdige PRs in einem Projekt gebaut werden, das privilegierte AWS-Rollenberechtigungen oder GitHub-Zugangsdaten besitzt, kann dies zu einer vollständigen Supply-Chain-Kompromittierung führen.
Wiz zeigte eine praktische Angriffskette, bei der:
- Eine Webhook-Actor-Allowlist einen unverankerten Regex verwendete.
- Ein Angreifer eine GitHub-ID registrierte, die als Superstring einer vertrauenswürdigen ID matchte.
- Eine bösartige PR CodeBuild auslöste.
- Die Ausführung von Build-Code genutzt wurde, um Speicher auszudumpen und Source-Provider-Anmeldeinformationen/Token wiederherzustellen.
Fehlkonfigurationen, die externe PR-Codeausführung ermöglichen
Im Folgenden sind hochriskante Fehler und wie Angreifer jeden einzelnen ausnutzen:
EVENT-Filter erlauben nicht vertrauenswürdige Trigger
- Häufig riskante Events:
PULL_REQUEST_CREATED,PULL_REQUEST_UPDATED,PULL_REQUEST_REOPENED. - Andere Events, die gefährlich werden können, wenn sie mit privilegierten Builds verknüpft sind:
PUSH,PULL_REQUEST_CLOSED,PULL_REQUEST_MERGED,RELEASED,PRERELEASED,WORKFLOW_JOB_QUEUED. - Schlecht:
EVENT="PUSH, PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED"in einem privilegierten Projekt. - Besser: PR-Kommentar-Approval verwenden und Trigger-Events für privilegierte Projekte minimieren.
- Missbrauch: Angreifer öffnet/aktualisiert eine PR oder pusht in einen von ihnen kontrollierten Branch, und ihr Code wird in CodeBuild ausgeführt.
ACTOR_ACCOUNT_ID-Regex ist schwach
- Schlecht: unverankerte Muster wie
123456|7890123. - Besser: exakte Anchoring-Übereinstimmung
^(123456|7890123)$. - Missbrauch: Regex-Overmatch erlaubt nicht autorisierten GitHub-IDs, Allowlists zu passieren.
- Andere Regex-Filter sind schwach oder fehlen
HEAD_REF- Schlecht:
refs/heads/.* - Besser:
^refs/heads/main$(oder eine explizite Liste vertrauenswürdiger Branches) BASE_REF- Schlecht:
.* - Besser:
^refs/heads/main$ FILE_PATH- Schlecht: keine Pfad-Einschränkungen
- Besser: riskante Dateien ausschließen wie
^buildspec\\.yml$,^\\.github/workflows/.*,(^|/)package(-lock)?\\.json$ COMMIT_MESSAGE- Schlecht: Trust-Marker mit losem Match wie
trusted - Besser: Verwenden Sie die Commit-Nachricht nicht als Vertrauensgrenze für die Ausführung von PRs
REPOSITORY_NAME/ORGANIZATION_NAME- Schlecht:
.*in org/global Webhooks - Besser: nur exakte Repo/Org-Übereinstimmungen
WORKFLOW_NAME- Schlecht:
.* - Besser: nur exakte Workflow-Namen (oder dieses Feld nicht als Vertrauenskontrolle verwenden)
- Missbrauch: Angreifer konstruiert Ref/Path/Message/Repo-Kontext so, dass permissive Regexes erfüllt werden und Builds ausgelöst werden.
excludeMatchedPatternwird falsch verwendet
- Das Setzen dieses Flags kann bei falscher Nutzung die beabsichtigte Logik invertieren.
- Schlecht:
FILE_PATH '^buildspec\\.yml$'mitexcludeMatchedPattern=false, obwohl beabsichtigt war, buildspec-Änderungen zu blockieren. - Besser: dasselbe Pattern mit
excludeMatchedPattern=true, um Builds zu verweigern, diebuildspec.ymlbetreffen. - Missbrauch: Verteidiger denken, sie verweigern riskante Events/Pfade/Actor, aber sie erlauben sie tatsächlich.
- Mehrere
filterGroupserzeugen unbeabsichtigte Bypässe
- CodeBuild wertet Gruppen als OR aus (eine bestehende Gruppe reicht aus).
- Schlecht: eine strenge Gruppe + eine permissive Fallback-Gruppe (z. B. nur
EVENT=PULL_REQUEST_UPDATED). - Besser: entferne Fallback-Gruppen, die keine Actor-/Ref-/Path-Einschränkungen durchsetzen.
- Missbrauch: Der Angreifer muss nur die schwächste Gruppe erfüllen.
- Kommentar-Approval-Gate deaktiviert oder zu permissiv
pullRequestBuildPolicy.requiresCommentApproval=DISABLEDist am unsichersten.- Zu breit gefasste Approver-Rollen reduzieren die Kontrolle.
- Schlecht:
requiresCommentApproval=DISABLED. - Besser:
ALL_PULL_REQUESTSoderFORK_PULL_REQUESTSmit minimalen Approver-Rollen. - Missbrauch: Fork/Drive-by-PRs laufen automatisch ohne Approval eines vertrauenswürdigen Maintainers.
- Keine restriktive Branch-/Pfad-Strategie für PR-Builds
- Fehlende Defense-in-Depth mit
HEAD_REF+BASE_REF+FILE_PATH. - Schlecht: nur
EVENT+ACTOR_ACCOUNT_ID, keine Ref/Path-Kontrollen. - Besser: exakte
ACTOR_ACCOUNT_ID+BASE_REF+HEAD_REF+FILE_PATHEinschränkungen kombinieren. - Missbrauch: Angreifer verändert Build-Inputs (buildspec/CI/Dependencies) und erlangt beliebige Befehlsausführung.
- Öffentliche Sichtbarkeit + Offenlegung der Status-URL
- Öffentliche Build-/Check-URLs verbessern die Recon-Fähigkeit des Angreifers und erleichtern iteratives Testen.
- Schlecht:
projectVisibility=PUBLIC_READmit sensiblen Logs/Configs in öffentlichen Builds. - Besser: Projekte privat halten, sofern kein starker Business-Need besteht, und Logs/Artefakte bereinigen.
- Missbrauch: Angreifer entdeckt Projektmuster/-verhalten und verfeinert Payloads und Bypass-Versuche.
Token leakage from memory
Wiz’ Write-up erklärt, dass Source-Provider-Anmeldeinformationen im Build-Runtime-Kontext vorhanden sind und nach einer Build-Kompromittierung gestohlen werden können (zum Beispiel durch Memory-Dumping), was bei breiten Berechtigungen eine Übernahme des Repositories ermöglicht.
AWS führte nach der Offenlegung Härtungsmaßnahmen ein, aber die Kernlektion bleibt: Führe niemals unvertrauenswürdigen PR-Code in privilegierten Build-Kontexten aus und gehe davon aus, dass vom Angreifer kontrollierter Build-Code versuchen wird, Anmeldeinformationen zu stehlen.
Für zusätzliche Techniken zum Diebstahl von Anmeldeinformationen in CodeBuild siehe auch:
Finding CodeBuild URLs in GitHub PRs
Wenn CodeBuild den Commit-Status an GitHub zurückmeldet, erscheint die CodeBuild-Build-URL normalerweise in:
- PR page -> Checks tab (oder die Statuszeile in Conversation/Commits).
- Commit page -> Status/Checks-Bereich -> Details-Link.
- PR commits list -> klicke auf den Check-Kontext, der an einen Commit angehängt ist.
Bei öffentlichen Projekten kann dieser Link Build-Metadaten/-Konfigurationen für nicht authentifizierte Benutzer offenlegen.
Skript: CodeBuild-URLs in einer PR erkennen und testen, ob sie öffentlich aussehen
```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”
Getestet mit:
```bash
bash /tmp/check_pr_codebuild_urls.sh carlospolop codebuild-codebreach-ctf-lab 1
Schnelle Audit-Checkliste
# 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
Prüfe jedes Projekt auf:
webhook.filterGroupsdie PR-Ereignisse enthalten.ACTOR_ACCOUNT_ID-Muster, die nicht mit^...$verankert sind.pullRequestBuildPolicy.requiresCommentApprovalgleichDISABLED.- Fehlende Branch-/Pfad-Einschränkungen.
serviceRolemit hohen Rechten.- Riskanter Umfang und Wiederverwendung von source credentials.
Härtungsempfehlungen
- Erfordern Sie Kommentarfreigabe für PR-Builds (
ALL_PULL_REQUESTSoderFORK_PULL_REQUESTS). - Wenn actor allowlists verwendet werden, verankern Sie die Regexes und halten Sie sie exakt.
- Fügen Sie
FILE_PATH-Einschränkungen hinzu, um nicht vertrauenswürdige Änderungen anbuildspec.ymlund CI-Skripten zu verhindern. - Trennen Sie vertrauenswürdige Release-Builds von nicht vertrauenswürdigen PR-Builds in unterschiedliche Projekte/Rollen.
- Verwenden Sie fein granulare, least-privileged source-provider-Tokens (vorzugsweise dedizierte Identitäten mit geringen Rechten).
- Überprüfen Sie kontinuierlich Webhook-Filter und die Nutzung von source credentials.
Referenzen
- 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
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
HackTricks Cloud

