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

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

この攻撃ベクターは、公開向けのPRワークフローが弱いwebhook制御で権限の高い CodeBuild プロジェクトに接続されている場合に発生します。

外部の攻撃者が CodeBuild に自分の pull request を実行させられると、通常はビルド内での**任意コード実行(build スクリプト、依存関係フック、テストスクリプト等)**が可能になり、その後シークレット、IAM クレデンシャル、あるいはソースプロバイダの資格情報へピボットできます。

Why this is dangerous

CodeBuild の webhook フィルタは regex パターンで評価されます(EVENT 以外のフィルタ)。ACTOR_ACCOUNT_ID フィルタでは、弱いパターンが意図より多くのユーザにマッチすることを意味します。 信頼できない PR が権限の高い AWS ロール権限や GitHub 資格情報を持つプロジェクトでビルドされると、完全なサプライチェーン妥協になり得ます。

Wiz の事例では実用的なチェーンが示されています:

  1. webhook の actor allowlist が アンカーされていない regex を使用していた。
  2. 攻撃者が信頼された ID の スーパー文字列 としてマッチする GitHub ID を登録した。
  3. 悪意ある PR が CodeBuild をトリガーした。
  4. ビルド内のコード実行を使ってメモリダンプを行い、ソースプロバイダの資格情報/トークンを回収した。

Misconfigurations that allow external PR code execution

以下は高リスクの設定ミスと、それぞれを攻撃者がどのように悪用するかです:

  1. EVENT filters allow untrusted triggers
  • 共通のリスクが高いイベント: PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED, PULL_REQUEST_REOPENED.
  • 権限の高いビルドに紐づくと危険になり得る他のイベント: PUSH, PULL_REQUEST_CLOSED, PULL_REQUEST_MERGED, RELEASED, PRERELEASED, WORKFLOW_JOB_QUEUED.
  • 悪い例: 権限の高いプロジェクトで EVENT="PUSH, PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED".
  • 良い例: PR コメント承認を使い、権限の高いプロジェクトではトリガーイベントを最小化する。
  • 悪用: 攻撃者が自分で管理するブランチに対して PR を開く/更新するか push し、そのコードが CodeBuild 内で実行される。
  1. ACTOR_ACCOUNT_ID regex is weak
  • 悪い例: アンカーされていないパターン 123456|7890123.
  • 良い例: 厳密一致するアンカー ^(123456|7890123)$.
  • 悪用: regex の過剰マッチにより、許可されていない GitHub ID が allowlist を通過する。
  1. Other regex filters are weak or missing
  • HEAD_REF
    • 悪い例: refs/heads/.*
    • 良い例: ^refs/heads/main$(または明示的な信頼リスト)
  • BASE_REF
    • 悪い例: .*
    • 良い例: ^refs/heads/main$
  • FILE_PATH
    • 悪い例: パス制限なし
    • 良い例: ^buildspec\\.yml$, ^\\.github/workflows/.*, (^|/)package(-lock)?\\.json$ のようにリスクの高いファイルを除外
  • COMMIT_MESSAGE
    • 悪い例: trusted のような緩いマッチで信頼マーカーを使う
    • 良い例: コミットメッセージを PR 実行の信頼境界として使用しない
  • REPOSITORY_NAME / ORGANIZATION_NAME
    • 悪い例: org/global webhook での .*
    • 良い例: リポジトリ/組織を厳密に一致させる
  • WORKFLOW_NAME
    • 悪い例: .*
    • 良い例: ワークフロー名を厳密に一致させる(または信頼制御として使用しない)
  • 悪用: 攻撃者は permissive な regex を満たすように ref/path/message/repo コンテキストを作成してビルドをトリガーする。
  1. excludeMatchedPattern is misused
  • このフラグを誤って設定すると、意図したロジックが反転することがある。
  • 悪い例: FILE_PATH '^buildspec\\.yml$'excludeMatchedPattern=false と設定して、実際には buildspec 編集をブロックする意図が失われている。
  • 良い例: 同じパターンを excludeMatchedPattern=true にして buildspec.yml に触れるビルドを拒否する。
  • 悪用: 防御側はリスクのあるイベント/パス/actor を拒否していると思っているが、実際には許可してしまっている。
  1. Multiple filterGroups create accidental bypasses
  • CodeBuild はグループを OR として評価する(1つのグループが通れば十分)。
  • 悪い例: 1つは厳格、もう1つは許容的なフォールバック(例: EVENT=PULL_REQUEST_UPDATED のみ)。
  • 良い例: actor/ref/path 制約を強制しないフォールバックグループは削除する。
  • 悪用: 攻撃者は最も弱いグループを満たすだけで良い。
  1. Comment approval gate disabled or too permissive
  • pullRequestBuildPolicy.requiresCommentApproval=DISABLED は最も安全性が低い。
  • 承認者ロールが広すぎると制御力が低下する。
  • 悪い例: requiresCommentApproval=DISABLED.
  • 良い例: ALL_PULL_REQUESTS または FORK_PULL_REQUESTS を使い、承認者ロールを最小限にする。
  • 悪用: fork / ドライブバイ PR が信頼されたメンテナ承認なしに自動実行される。
  1. No restrictive branch/path strategy for PR builds
  • HEAD_REF + BASE_REF + FILE_PATH による深い防御層が欠如している。
  • 悪い例: EVENT + ACTOR_ACCOUNT_ID のみで、ref/path 制御がない。
  • 良い例: 正確な ACTOR_ACCOUNT_ID + BASE_REF + HEAD_REF + FILE_PATH 制限を組み合わせる。
  • 悪用: 攻撃者が buildspec/CI/依存関係などのビルド入力を改変し、任意コマンド実行を得る。
  1. Public visibility + status URL exposure
  • ビルド/チェックの公開 URL は攻撃者のリコンと反復テストを容易にする。
  • 悪い例: projectVisibility=PUBLIC_READ で公開ビルドに機密ログ/設定が含まれる。
  • 良い例: 事業上の強い理由がない限りプロジェクトを非公開にし、ログ/アーティファクトをサニタイズする。
  • 悪用: 攻撃者はプロジェクトのパターンや挙動を発見し、ペイロードやバイパス手法を調整する。

Token leakage from memory

Wiz の報告は、ソースプロバイダの資格情報がビルド実行時のランタイムコンテキストに存在し、ビルド侵害後に(例えばメモリダンプを経て)盗まれる可能性があることを説明しています。スコープが広い場合、これはリポジトリ乗っ取りを可能にします。

AWS はこの公開後にハードニングを行いましたが、核心的な教訓は変わりません: 権限の高いビルドコンテキストで信頼できない PR コードを決して実行してはいけない、そして攻撃者支配下のビルドコードは資格情報窃取を試みると仮定すべきです。

追加の CodeBuild における資格情報窃取手法については、次も参照してください:

AWS Codebuild - Token Leakage

Finding CodeBuild URLs in GitHub PRs

CodeBuild がコミットステータスを GitHub に返す場合、CodeBuild のビルド URL は通常次の場所に表示されます:

  1. PR page -> Checks タブ(または Conversation/Commits のステータス行)。
  2. Commit page -> status/checks セクション -> Details リンク。
  3. PR commits list -> コミットに付随するチェックコンテキストをクリック。

公開プロジェクトでは、このリンクが未認証ユーザにビルドのメタデータ/設定を露出することがあります。

スクリプト: PR 内の CodeBuild URL を検出し、公開されているかどうかをテストする ```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”

動作確認済み:
```bash
bash /tmp/check_pr_codebuild_urls.sh carlospolop codebuild-codebreach-ctf-lab 1

クイック監査チェックリスト

# 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

各プロジェクトで次を確認してください:

  • webhook.filterGroups が PR イベントを含んでいるか。
  • ACTOR_ACCOUNT_ID のパターンが ^...$ でアンカーされていないもの。
  • pullRequestBuildPolicy.requiresCommentApprovalDISABLED に設定されているもの。
  • ブランチ/パス制限が設定されていないもの。
  • 高権限の serviceRole
  • 危険なソース認証情報のスコープや再利用。

ハードニングガイダンス

  1. PR ビルドに対してコメント承認を必須にする(ALL_PULL_REQUESTS または FORK_PULL_REQUESTS)。
  2. actor allowlist を使用する場合、正規表現をアンカーし(^…$)、正確に保つ。
  3. buildspec.yml や CI スクリプトへの信頼できない編集を避けるため、FILE_PATH 制限を追加する。
  4. 信頼できるリリースビルドと信頼できない PR ビルドを別々のプロジェクト/ロールに分離する。
  5. 細粒度で最小権限のソースプロバイダトークンを使用する(専用の低権限アイデンティティを優先)。
  6. webhook フィルタとソース認証情報の使用状況を継続的に監査する。

参考資料

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする