GitHub Actions
允许的不安全命令
有一些已弃用的 set-env
和 add-path
工作流命令,可以通过将 ACTIONS_ALLOW_UNSECURE_COMMANDS
环境变量设置为 true
来显式启用。
set-env
通过以下工作流命令设置环境变量::set-env name=<NAME>::<VALUE>
add-path
通过以下工作流命令更新PATH
环境变量::add-path::<VALUE>
根据环境变量的使用情况,在最坏的情况下,这可能允许攻击者更改路径并运行非预期的命令,导致任意命令执行。例如,考虑以下工作流:
name: 易受攻击的工作流
on:
pull_request_target
env:
# 1. 启用不安全命令
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
ENVIRONMENT_NAME: prod
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# 2. 打印 github 上下文
- run: |
print("""${{ toJSON(github) }}""")
shell: python
- name: 创建新的 PR 部署
uses: actions/github-script@v5
with:
# 3. 创建部署
script: |
return await github.rest.repos.createDeployment({
...context.repo,
ref: context.payload.pull_request.head.sha,
auto_merge: false,
required_contexts: [],
environment: "${{ env.ENVIRONMENT_NAME }}",
transient_environment: false,
production_environment: false,
});
github-token: ${{ secrets.GITHUB_TOKEN }}
上述工作流通过在 env
部分将 ACTIONS_ALLOW_UNSECURE_COMMANDS
设置为 true
来启用不安全命令。可以看到,deploy
作业的第一步将 github
上下文打印到工作流日志中。由于 github
上下文中的部分变量是用户控制的,可能滥用不安全命令来设置任意环境变量。例如,攻击者可以使用拉取请求描述来传递以下payload,当打印 github
上下文时,这将重置 ENVIRONMENT_NAME
:
\n::set-env name=ENVIRONMENT_NAME::", <YOUR_JS_CODE>//\n
现在让我们看看上述payload的工作原理:

由于 payload 使用了 ::set-env name=ENVIRONMENT_NAME::
命令,它将把环境变量 ENVIRONMENT_NAME
重置为 ", <YOUR_JS_CODE>//
。因此,在 github-script
中,environment
将被设置为 ", <YOUR_JS_CODE>//
而不是 prod
。然后,攻击者可以通过精心设计的 YOUR_JS_CODE
注入任意 JavaScript 代码。
参考资料
脚本注入
GitHub Actions 允许您使用各种shell在运行器上执行命令。这些shell包括 bash
、pwsh
、powershell
和 python
。然而,在某些情况下,GitHub Actions 会将用户控制的输入直接传递给shell命令,这可能导致命令注入。
例如,考虑以下易受攻击的工作流:
name: 易受攻击的工作流
on:
pull_request_target
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: 获取 PR 编号
id: pr-number
run: |
echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV
- name: 注入命令
run: |
# 用户控制的输入
PR_NUMBER=${{ env.PR_NUMBER }}
# 直接传递给 shell
echo "Processing PR #$PR_NUMBER"
# 易受攻击的命令执行
./deploy.sh --pr $PR_NUMBER
在上述示例中,攻击者可以通过将恶意payload注入到PR标题或描述中来执行任意命令。例如,如果攻击者创建一个标题为 1; rm -rf /
的PR,这将导致执行 rm -rf /
命令。
为了防止此类攻击,应该:
验证和清理所有用户控制的输入
使用安全的参数传递方法
避免直接将用户输入传递给shell命令
参考资料
权限提升
GitHub Actions 运行器默认具有与仓库相同的权限。在某些情况下,这可能导致权限提升,特别是当工作流使用敏感的 secrets.GITHUB_TOKEN
时。
考虑以下示例:
name: 易受攻击的工作流
on:
pull_request_target
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: 创建 PR 部署
uses: actions/github-script@v5
with:
script: |
// 攻击者可以修改此代码
return await github.rest.repos.createDeployment({
...context.repo,
ref: context.payload.pull_request.head.sha,
auto_merge: false,
required_contexts: [],
environment: "production",
transient_environment: false,
production_environment: false,
});
github-token: ${{ secrets.GITHUB_TOKEN }}
在上述示例中,攻击者可以通过修改 github-script
来创建生产环境的部署,即使原始工作流只打算用于测试环境。
参考资料
最后更新于