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
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
当一个面向公众的 PR 工作流 连接到具有弱 webhook 控制的 特权 CodeBuild 项目 时,会出现这种攻击向量。
如果外部攻击者能让 CodeBuild 执行他们的 pull request,通常可以在构建过程中获得 任意代码执行(构建脚本、依赖钩子、测试脚本等),然后横向攻击以获取 secrets、IAM 凭证或源提供商凭证。
Why this is dangerous
CodeBuild 的 webhook 过滤器(对于非 EVENT 过滤器)使用 regex 模式进行评估。在 ACTOR_ACCOUNT_ID 过滤器中,这意味着弱模式可能匹配比预期更多的用户。
如果在具有特权 AWS 角色权限或 GitHub 凭证的项目中构建不受信任的 PR,这可能演变为完整的供应链妥协。
Wiz 展示了一个实际的链条,其中:
- 一个 webhook actor allowlist 使用了 未加锚点的 regex。
- 攻击者注册了一个 GitHub ID,作为受信任 ID 的 superstring 被匹配。
- 一个恶意 PR 触发了 CodeBuild。
- 构建中的代码执行被用来转储内存并恢复源提供商凭证/令牌。
Misconfigurations that allow external PR code execution
下面是高风险的错误以及攻击者如何滥用每一种:
EVENTfilters 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 中执行。
ACTOR_ACCOUNT_IDregex is weak
- 不良示例:像
123456|7890123这样的未锚定模式。 - 更好:使用精确匹配锚定
^(123456|7890123)$。 - 滥用:regex 过度匹配允许未授权的 GitHub ID 通过允许列表。
- 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/全局 webhook 中使用
.* - 更好:仅精确匹配仓库/组织
- 不良示例:在 org/全局 webhook 中使用
WORKFLOW_NAME- 不良示例:
.* - 更好:仅精确的 workflow 名称匹配(或避免将其作为信任控制)
- 不良示例:
- 滥用:攻击者构造 ref/路径/提交信息/仓库上下文以满足宽松的 regex 并触发构建。
excludeMatchedPatternis misused
- 错误设置此标志可能会将意图逻辑反转。
- 不良示例:使用
FILE_PATH '^buildspec\\.yml$'并将excludeMatchedPattern=false,而本意是阻止对 buildspec 的更改。 - 更好:对同一模式使用
excludeMatchedPattern=true来拒绝触及buildspec.yml的构建。 - 滥用:防御者以为他们阻止了高风险事件/路径/actor,实际上却允许了。
- Multiple
filterGroupscreate accidental bypasses
- CodeBuild 将组作为 OR 进行评估(通过任一组即可)。
- 不良示例:一个严格组 + 一个宽松的回退组(例如只有
EVENT=PULL_REQUEST_UPDATED)。 - 更好:移除不强制 actor/ref/path 约束的回退组。
- 滥用:攻击者只需满足最弱的组。
- Comment approval gate disabled or too permissive
pullRequestBuildPolicy.requiresCommentApproval=DISABLED是最不安全的。- 过于宽泛的批准者角色会降低控制力度。
- 不良示例:
requiresCommentApproval=DISABLED。 - 更好:使用
ALL_PULL_REQUESTS或FORK_PULL_REQUESTS并限制批准者角色。 - 滥用:fork/drive-by PR 自动运行,无需受信任维护者批准。
- 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/依赖)并获得任意命令执行。
- Public visibility + status URL exposure
- 公开的构建/检查 URL 提高了攻击者的侦察和迭代测试能力。
- 不良示例:
projectVisibility=PUBLIC_READ,且在公开构建中有敏感日志/配置。 - 更好:除非有强烈的业务需求,否则保持项目私有,并对日志/构件进行清理。
- 滥用:攻击者发现项目模式/行为,然后调整有效载荷和绕过尝试。
Token leakage from memory
Wiz 的报告解释了源提供商凭证存在于构建运行时上下文中,并且在构建被攻破后可以被窃取(例如通过 memory dumping),如果权限范围过大则可导致仓库接管。
AWS 在漏洞披露后引入了加固,但核心教训依然是:永远不要在特权构建上下文中执行不受信任的 PR 代码,并假定攻击者控制的构建代码会尝试窃取凭证。
For additional credential theft techniques in CodeBuild, also check:
Finding CodeBuild URLs in GitHub PRs
如果 CodeBuild 将提交状态报告回 GitHub,CodeBuild 构建 URL 通常出现在:
- PR 页面 -> Checks 选项卡(或 Conversation/Commits 中的状态行)。
- Commit 页面 -> 状态/检查部分 -> Details 链接。
- PR commits 列表 -> 点击附加在提交上的检查上下文。
对于公共项目,该链接可能会向未认证用户暴露构建元数据/配置。
脚本:在 PR 中检测 CodeBuild URL 并测试它们是否看起来是公开的
```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”
已在以下环境测试通过:
```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.filterGroupscontaining PR events.ACTOR_ACCOUNT_IDpatterns that are not anchored with^...$.pullRequestBuildPolicy.requiresCommentApprovalequal toDISABLED.- Missing branch/path restrictions.
- High-privilege
serviceRole. - Risky source credentials scope and reuse.
加固建议
- 要求 PR 构建的评论审批(
ALL_PULL_REQUESTS或FORK_PULL_REQUESTS)。 - If using actor allowlists,锚定正则并保持精确匹配。
- Add
FILE_PATHrestrictions to avoid untrusted edits tobuildspec.ymland CI scripts. - 将受信任的发布构建与不受信任的 PR 构建分离到不同的项目/角色。
- Use fine-grained, least-privileged source-provider tokens(prefer dedicated low-privilege identities)。
- 持续审计 webhook filters 和 source credential 的使用。
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
学习和实践 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
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
HackTricks Cloud

