Files
hacktricks-cloud/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/aws-codebuild-untrusted-pr-webhook-bypass.md
T

236 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AWS CodeBuild - Untrusted PR Webhook Bypass (CodeBreach-style)
{{#include ../../../../banners/hacktricks-training.md}}
Цей вектор атаки виникає, коли **публічний PR workflow** підключено до **привілейованого проекту CodeBuild** з ненадійними контролями webhook.
Якщо зовнішній атакуючий може змусити CodeBuild виконати їхній pull request, зазвичай це дає змогу отримати **довільне виконання коду всередині build** (скрипти збірки, hooks залежностей, тестові скрипти тощо), а далі перескочити на секрети, IAM credentials або credentials провайдера репозиторію.
## Чому це небезпечно
Фільтри webhook у CodeBuild оцінюються за допомогою regex-патернів (для фільтрів, що не `EVENT`). У фільтрі `ACTOR_ACCOUNT_ID` це означає, що слабкий патерн може співпадати з більшою кількістю користувачів, ніж передбачалося.
Якщо в проекті будуються ненадійні PR і цей проект має привілеї AWS role або credentials GitHub, це може перетворитися на повний compromise ланцюжка постачання.
Wiz продемонструвала практичний ланцюжок, де:
1. У allowlist для actor webhook використовувався **унанкорований regex**.
2. Атакуючий зареєстрував GitHub ID, який співпадав як **superstring** довіреного ID.
3. Зловмисний PR тригернув CodeBuild.
4. Виконання коду в build використали для дампу пам’яті та відновлення credentials/tokens провайдера сорсу.
## Misconfigurations that allow external PR code execution
Нижче наведені високоризикові помилки конфігурації та як їх зловживають:
1. **`EVENT` filters allow untrusted triggers**
- Поширені ризиковані events: `PULL_REQUEST_CREATED`, `PULL_REQUEST_UPDATED`, `PULL_REQUEST_REOPENED`.
- Інші events, які теж можуть стати небезпечними, якщо прив’язані до привілейованих збірок: `PUSH`, `PULL_REQUEST_CLOSED`, `PULL_REQUEST_MERGED`, `RELEASED`, `PRERELEASED`, `WORKFLOW_JOB_QUEUED`.
- Bad: `EVENT="PUSH, PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED"` в привілейованому проекті.
- Better: використовувати approval через PR comment і мінімізувати trigger events для привілейованих проектів.
- Abuse: атакуючий відкриває/оновлює PR або пушить у гілку під своїм контролем, і їхній код виконується в CodeBuild.
2. **`ACTOR_ACCOUNT_ID` regex is weak**
- Bad: неанкоровані патерни типу `123456|7890123`.
- Better: точне анкорування, наприклад `^(123456|7890123)$`.
- Abuse: regex over-match дозволяє неавторизованим GitHub ID проходити allowlist.
3. **Other regex filters are weak or missing**
- `HEAD_REF`
- Bad: `refs/heads/.*`
- Better: `^refs/heads/main$` (або явний список trusted гілок)
- `BASE_REF`
- Bad: `.*`
- Better: `^refs/heads/main$`
- `FILE_PATH`
- Bad: відсутні обмеження по шляху
- Better: виключати ризикові файли, наприклад `^buildspec\\.yml$`, `^\\.github/workflows/.*`, `(^|/)package(-lock)?\\.json$`
- `COMMIT_MESSAGE`
- Bad: довіряти маркеру з вільним матчем на кшталт `trusted`
- Better: не використовувати commit message як межу довіри для виконання PR
- `REPOSITORY_NAME` / `ORGANIZATION_NAME`
- Bad: `.*` в org/global webhooks
- Better: лише точні збіги для repo/org
- `WORKFLOW_NAME`
- Bad: `.*`
- Better: лише точні збіги по імені workflow (або уникати цього як механізму довіри)
- Abuse: атакуючий формує ref/path/message/repo контекст, який задовольняє дозволяючі regex і тригерить збірки.
4. **`excludeMatchedPattern` is misused**
- Неправильне встановлення цього прапора може інвертувати бажану логіку.
- Bad: `FILE_PATH '^buildspec\\.yml$'` з `excludeMatchedPattern=false`, коли намір був блокувати редагування buildspec.
- Better: той самий патерн з `excludeMatchedPattern=true` щоб заборонити збірки, що торкаються `buildspec.yml`.
- Abuse: захисники думають, що вони забороняють ризикові події/шляхи/акторів, але насправді дозволяють їх.
5. **Multiple `filterGroups` create accidental bypasses**
- CodeBuild оцінює групи як OR (достатньо однієї успішної групи).
- Bad: одна сувора група + одна лояльна fallback-група (наприклад, тільки `EVENT=PULL_REQUEST_UPDATED`).
- Better: прибрати fallback-групи, які не примушують обмеження по actor/ref/path.
- Abuse: атакуючому потрібно задовольнити лише найслабшу групу.
6. **Comment approval gate disabled or too permissive**
- `pullRequestBuildPolicy.requiresCommentApproval=DISABLED` найменш безпечний.
- Надто широкі ролі approver-ів зменшують контроль.
- Bad: `requiresCommentApproval=DISABLED`.
- Better: `ALL_PULL_REQUESTS` або `FORK_PULL_REQUESTS` з мінімальними ролями approver-ів.
- Abuse: fork/drive-by PR-и запускаються автоматично без схвалення trusted maintainers.
7. **No restrictive branch/path strategy for PR builds**
- Відсутність defense-in-depth з `HEAD_REF` + `BASE_REF` + `FILE_PATH`.
- Bad: тільки `EVENT` + `ACTOR_ACCOUNT_ID`, без контролю ref/path.
- Better: комбінувати точні `ACTOR_ACCOUNT_ID` + `BASE_REF` + `HEAD_REF` + `FILE_PATH` обмеження.
- Abuse: атакуючий змінює вхідні дані збірки (buildspec/CI/залежності) і отримує довільне виконання команд.
8. **Public visibility + status URL exposure**
- Публічні build/check URL полегшують reconnaissance і ітеративне тестування для атакуючого.
- Bad: `projectVisibility=PUBLIC_READ` з чутливими логами/конфігурацією у публічних збірках.
- Better: тримати проекти приватними, якщо немає вагомої бізнес-потреби, і санітизувати логи/артефакти.
- Abuse: атакуючий виявляє патерни/поведінку проекту, після чого підлаштовує payload-и та спроби обходу.
## Token leakage from memory
У write-up від Wiz пояснюється, що credentials провайдера сорсу присутні в build runtime context і їх можна вкрасти після compromise збірки (наприклад, через дамп пам’яті), що дозволяє takeover репозиторія, якщо scope-и надто широкі.
AWS впровадила жорсткіші заходи після розкриття, але головний урок залишається: **ніколи не виконувати код з ненадійних PR у привілейованих build-контекстах** і припускати, що код під контролем атакуючого спробує викрасти credentials.
Для додаткових технік викрадення credentials у CodeBuild також перевірте:
{{#ref}}
aws-codebuild-token-leakage.md
{{#endref}}
## Finding CodeBuild URLs in GitHub PRs
Якщо CodeBuild повертає статус коміту в GitHub, URL збірки CodeBuild зазвичай видно в:
1. **PR page** -> **Checks** tab (або рядок статусу в Conversation/Commits).
2. **Commit page** -> секція status/checks -> **Details** link.
3. **PR commits list** -> клікнути по check context, прив’язаному до коміту.
Для публічних проектів це посилання може виставляти metadata/config збірки для неавторизованих користувачів.
<details>
<summary>Скрипт: виявити CodeBuild URL-и в PR і перевірити, чи виглядають вони публічними</summary>
```bash
#!/usr/bin/env bash
set -euo pipefail
# Usage:
# ./check_pr_codebuild_urls.sh <owner> <repo> <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
```
</details>
## Швидкий чекліст аудиту
```bash
# 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.requiresCommentApproval`, рівне `DISABLED`.
- Відсутні обмеження гілок/шляхів.
- Високопривілейований `serviceRole`.
- Ризиковий обсяг прав та повторне використання облікових даних джерела.
## Рекомендації щодо підвищення захисту
1. Вимагати підтвердження коментарем для PR builds (`ALL_PULL_REQUESTS` або `FORK_PULL_REQUESTS`).
2. Якщо використовуєте actor allowlists, заякорюйте regex-и і робіть їх точними.
3. Додайте обмеження `FILE_PATH`, щоб уникнути небезпечних змін у `buildspec.yml` та CI scripts.
4. Відокремте довірені release builds від недовірених PR builds у різні проекти/ролі.
5. Використовуйте тонко-гранульні, найменш привілейовані source-provider tokens (надавайте перевагу виділеним низькопривілейованим ідентичностям).
6. Постійно перевіряйте webhook filters та використання source credentials.
## References
- [Wiz: CodeBreach - AWS CodeBuild ACTOR_ID regex bypass and token theft](https://www.wiz.io/blog/wiz-research-codebreach-vulnerability-aws-codebuild)
- [AWS CodeBuild API - WebhookFilter](https://docs.aws.amazon.com/codebuild/latest/APIReference/API_WebhookFilter.html)
- [AWS CLI - codebuild create-webhook](https://docs.aws.amazon.com/cli/latest/reference/codebuild/create-webhook.html)
- [AWS CodeBuild User Guide - Best practices for webhooks](https://docs.aws.amazon.com/codebuild/latest/userguide/webhooks.html)
{{#include ../../../../banners/hacktricks-training.md}}