Skip to content

Runner EC2 instances can read other instances' tokens (jitconfig and registration tokens) from SSM parameters

High
npalm published GHSA-w423-qwm2-w2jq Jul 1, 2024

Package

terraform philips-labs/terraform-aws-github-runner (terraform)

Affected versions

v0.8.1

Patched versions

v5.11.0

Description

Summary

Runner EC2 instances can read other instances' tokens (jitconfig and registration tokens) from SSM parameters.

Details

The runner-ssm-parameters IAM policy (https://github.com/philips-labs/terraform-aws-github-runner/blob/v5.10.4/modules/runners/policies/instance-ssm-parameters-policy.json#L9-L11) allows ssm:GetParameter on "Resource": "${arn_ssm_parameters_path_tokens}*". This is overly permissive and allows instances to read each others' jitconfig or registration tokens.

However, to exploit the overly permissive ssm:GetParameter permissions, we need to discover the instance ID of another instance because it occurs in the parameter name. One of the first things a runner does is delete its config after retrieving it. This is a slightly tricky race to win.

There are multiple places the instance ID is exposed, but ec2:DescribeVolumes is nice to use for an exploit because it appears before the victim instance has begun execution and the SSM should not yet be deleted.

Impact

The jitconfig or registration token can be stolen from concurrent workflows on the same runner, which can be used to register a new runner maliciously. The token can be exfiltrated and a runner created outside the AWS environment, or the malicious runner can be created inside the existing instance/runner. A runner's jitconfig is normally scoped down to a single repo, workflow and job. Stealing another runner's jitconfig allows lateral movement throughout the GitHub organization or repository and exposes the other runner's GITHUB_TOKEN, GitHub OIDC JWT ID token and any secrets.

The risk is that an attacker in with access to your org runners can steal a token and register a runner in the same org. When using a jitconfig this runner will run one job at most, for non JIT infinite which is a significant higher risk.

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
High
User interaction
None
Scope
Changed
Confidentiality
High
Integrity
None
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:L

CVE ID

No known CVE

Weaknesses

Credits