Vulnerability Details
The formatter action is triggered on pull_request_target
events, which run with
the context of the base repository and is therefore allowed to mount secrets.
However, the formatter action specifically checks out the reference from the
Pull Request (which is attacker controlled code). This breaks the security
benefits of pull_request_target
and exposes secrets to the attack code. This
might be acceptable when the action does not allow for code exec. However, the
formatter action later runs the command:
mvn com.coveo:fmt-maven-plugin:format
Running mvn
with an attacker-controlled pom.xml file can lead to remote code
execution in the action.
Steps to replicate:
- Find a target repository with the formatter action. For example, https://github.com/googleapis/java-core/blob/master/.github/workflows/formatting.yaml.
- Fork the repository from a Github account without write access to the repo
- Inject malicious XML into the Maven pom.xml file
a. For example, modify the pom.xml to include a malicious pluginRepository
b. Create a backdoored version of
com.coveo:fmt-maven-plugin
and host this at your pluginRepository - Commit this pom.xml file, push to a branch in your fork
- Create a PR against the main googleapis/java-core repo
- Observe the formatter action runs against the PR and executes the backdoored plugin
To demonstrate, I have created a copy of the googleapis/java-core repo (not a fork) and configured my own fake secret in this repo. I then created a fork of this repo in a separate account and executed the steps above. I have provided a screenshot of the resulting exploit shown in the Github action log. After performing the attack, I converted both repositories to private repos. I can grant access to the repository or provide my backdoored plugin at Google’s request.
Initial pull request to repository:
Backdoored pom.xml file to use custom Maven repository:
Github action output showing ACCESS_TOKEN and malicious commits to master:
Malicious commit to master from attacker created action:
As shown above, the attacker tigres-builder created a malicious commit on master in the victim repo (amlweems/java-core) by simply making a PR against the repo.
Attack Scenario
Any Github user can compromise a service account and push code to all googleapis repositories.
Any Github user can make a PR against repositories in the googleapis
and
execute arbitrary code in the context of a pull_request_target event. Since
this event is trusted, Github mounts secrets (e.g. the Github token and, in
this case, the YOSHI_CODE_BOT_TOKEN
secret from the repo). As a result, the
attacker gains access to both of these secrets and could push code to the
target repository or compromise the https://github.com/yoshi-code-bot account.
Based on commit history, this account appears to have write access to to most
repositories in the googleapis
organization.
Timeline
- 2020-12-17: Issue reported to Google VRP
- 2020-12-21: Issue triaged
- 2020-12-23: Internal bug report filed
- 2021-01-08: Issue fixed
- 2021-02-25: VRP issued reward ($500)
Discussion on Impact
VRP at Jan 12, 2021 11:20AM:
As a part of our Vulnerability Reward Program, we decided that it does not meet
the bar for a financial reward, but we would like to acknowledge your
contribution to Google security in our Hall of Fame:
https://bughunter.withgoogle.com/rank/hm
Rationale for this decision:
YOSHI_CODE_BOT_TOKEN was the only secret exposed to pull_request_target and the
associated yoshi-code-bot user has very limited permissions. It can create pull
requests, but not push directly to any repository.
me at Jan 12, 2021 11:28AM:
Thanks for the reply!
While the YOSHI_CODE_BOT_TOKEN is the only secret, the Github token is also
exposed to any pull_request_target and it has write privileges to the
repository (since pull_request_target is enabled). The runner automatically
configures this token in the .git/config of the repo so that any git commands
"just work" and I demonstrated this in the screenshots in my initial report.
As a result, every repository with the formatter action could be modified by an
attacker.
VRP at Jan 14, 2021 05:36PM:
Thanks I've updated the product team and they'll take another look
me at Feb 9, 2021 02:04PM:
Hey, just wanted to check in and see if there was a response here. If it's
helpful, the screenshots in my original report show that it's possible to make
a commit with just the GITHUB_TOKEN, which is what was exposed in the case of
the googleapis repos.
VRP at Feb 10, 2021 04:23PM:
The product team has noted that this should be fixed.
me at Feb 19, 2021 10:04AM:
I've confirmed it is fixed. I'm asking that this be re-examined for impact and
bounty. As per above, the previous rationale was:
"YOSHI_CODE_BOT_TOKEN was the only secret exposed to pull_request_target and
the associated yoshi-code-bot user has very limited permissions. It can create
pull requests, but not push directly to any repository."
However, this is not the full picture. The GITHUB_TOKEN was also exposed,
giving the attacker write access to any affected repo (which included dozens of
repos in the googleapis org).