Full Report
OpenID Connect (OIDC) is a common authorization service. Of course, AWS supports a way to authorize services outside of AWS to assume IAM roles using it. Besides this post, they have many other cases where the permissions of OIDC are incorrect and this leads to a privilege escalation. The service of focus this time is Gitlab The default trust policy for OIDC Gitlab authentication contains the principal (Gitlab.com), an action for AssumeRoleWithWebIdentity and an optional condition key of gitlab.com:sub. This is either a group, project or branch that is allowed to submit this. The reason there is a misconfiguration is the optional condition key - aka, fails open. The sub field on the JWT - who is permitted to assume the role - is not a required field. If this is not included, then there are a wide variety of ways to assume the role in AWS. The example policy used for the test does not include the sub at all but only the aud. To exploit this, an attacker needs to create a valid JWT for the sts:AssumeRoleWithWebIdentity invocation. Doing this only requires having an account on Gitlab, creating a project with CI and support for JWT generation. In the CI, we can simply output the GITLAB_OIDC_TOKEN and this will work for us. In AWS, we can then use the token with a call to sts:AssumeRoleWithWebIdentity to assume the role now. Generating a trust policy for Gitlab in the AWS console is created insecure by default, which is terrifying. In the case of Github Actions and Terraform Cloud, AWS made changes to require specific fields. Overall, a good and concise write up on a common AWS misconfiguration.
Analysis Summary
# Vulnerability: Misconfigured GitLab OIDC AWS IAM Trust Policy
## CVE Details
- **CVE ID**: N/A (Cloud Misconfiguration/Design Flaw)
- **CVSS Score**: 9.1 (Critical) - *Estimation based on similar OIDC bypass flaws*
- **CWE**: CWE-287: Improper Authentication; CWE-347: Improper Verification of Cryptographic Signature (specifically validation of claims)
## Affected Systems
- **Products**: AWS IAM (Identity and Access Management)
- **Versions**: Cloud Service (Current as of Feb 2025)
- **Configurations**:
- IAM Roles using `gitlab.com` as a Federated Web Identity provider.
- Roles lacking a `StringEquals` or `StringLike` condition for the `gitlab.com:sub` (subject) field.
- Roles created via the AWS Console's "Web identity" wizard for GitLab, which populates an insecure default policy.
## Vulnerability Description
AWS IAM roles can trust external OIDC providers like GitLab to allow automated workloads (CI/CD) to perform AWS actions. The vulnerability stems from a "fail-open" logic in the trust relationship.
GitLab’s OIDC implementation uses a shared Issuer URL for all users. If an AWS IAM Trust Policy only validates the `aud` (audience) or the provider name but fails to validate the `sub` (subject) or `repository_id` claims, AWS will permit **any** valid JWT issued by GitLab to assume the role. Since any user can create a free GitLab account and generate a valid JWT via GitLab CI, they can assume the misconfigured role from their own malicious repository.
## Exploitation
- **Status**: PoC available / Exploited in the wild (similar patterns seen in GitHub/Terraform OIDC history).
- **Complexity**: Low.
- **Attack Vector**: Network.
- **Prerequisites**: An attacker needs a standard GitLab account and a project with a `.gitlab-ci.yml` file to echo the `GITLAB_OIDC_TOKEN`.
## Impact
- **Confidentiality**: High (Access to all data permitted by the IAM Role).
- **Integrity**: High (Ability to modify/delete AWS resources).
- **Availability**: High (Ability to delete infrastructure or disrupt services).
## Remediation
### Patches
- **AWS Console**: Currently, the AWS Console provides a vulnerable template by default for GitLab. Users must manually harden the policy. (Note: AWS has previously patched this default behavior for GitHub and Terraform Cloud but has not yet done so for GitLab).
### Workarounds
- **Mandatory Trust Conditions**: Update all GitLab OIDC Trust Policies to include a mandatory check for the `sub` field.
json
"Condition": {
"StringEquals": {
"gitlab.com:sub": "project_path:your-org/your-project:ref_type:branch:ref:main"
}
}
- **Resource Control Policies (RCPs)**: Implement AWS Organizations RCPs to globally enforce that `sts:AssumeRoleWithWebIdentity` calls must contain specific organization-owned `sub` patterns.
## Detection
- **Indicators of Compromise**:
- CloudTrail logs showing `AssumeRoleWithWebIdentity` calls from unexpected GitLab projects or unknown `sub` identifiers.
- Identity provider usage where the `sub` claim doesn't match internal repository naming conventions.
- **Detection Methods**:
- **AWS Config**: Use custom rules to flag IAM roles where the trust policy principal is an OIDC provider but lacks a `sub` condition.
- **IAM Access Analyzer**: Review findings for roles that grant "Public" or "Cross-account" access via OIDC.
## References
- **Hacking The Cloud**: hxxps[://]hackingthe[.]cloud/aws/exploitation/Misconfigured_Resource-Based_Policies/exploiting_misconfigured_gitlab_oidc_aws_iam_roles/
- **GitLab Documentation**: hxxps[://]docs[.]gitlab[.]com/ee/ci/cloud_services/aws/
- **AWS RCP Examples**: hxxps[://]github[.]com/aws-samples/resource-control-policy-examples/blob/main/Limit-access-to-trusted-OIDC-identity-providers/Limit-access-to-trusted-OIDC-identity-providers[.]md