A common way to allow third-party SaaS solutions to access AWS accounts is via OpenID Connect (OIDC) integrations. These integrations require specific conditions in the AWS IAM trust policy, and if those conditions do not exist, they may allow undesired actors to access the AWS account. Researchers have identified and published information about four of these vendor integration mistakes that customers can make. This blog post collects those specific examples into a discussion of the general problem and expands the scope to include all vendors who have public documentation on this integration.
The first one: GitHub Actions
In 2023, multiple sets of researchers (1, 2, 3, 4) identified that some companies had not included a “sub” condition in their IAM role trust policy which allowed any GitHub user to create a GitHub Action which could assume the victim’s IAM role. Here is an example of a correct role trust policy that includes the required sub condition:
If the "sub" condition in the above policy was missing, and an attacker knew about the IAM role that was missing it, then the attacker could create a GitHub Action in their own GitHub repo that could assume that IAM role. The "sub" condition restricts who can assume this role to only those GitHub Actions coming from a specific repo and branch.
A couple of things were done by AWS which have mostly eradicated this problem. There may be some old configurations that still have this issue, but you can no longer make an IAM role trust policy that trusts GitHub Actions and does not have the necessary “sub” condition in the policy. I wrote about my involvement with this in previously: A security community success story of mitigating a misconfiguration.
...Then more were found
After this problem was found with the integration to GitHub Actions, the same concept was also found to impact the integrations of Terraform Cloud, Microsoft Defender, and Gitlab. The general problem is that if a customer does not include certain conditions which restrict who can access the AWS IAM role, then an attacker can sign up for an account with one of these services and access the customer’s AWS IAM role.
Required conditions
Instead of continuing in this cycle of learning about new OIDC providers and the mistakes that could be made with them every few months, we decided to look at all the provider integrations that can be made with AWS via OIDC. We did this based on those with public documentation we could find, to identify the critical condition required. We found more than twenty vendors that offer OIDC integrations with AWS and reviewed their documentation.
You might initially think that you just need to ensure you have a “sub” condition in all your OIDC integrations, but the Microsoft Defender issue is interesting because the required condition to avoid this issue is on the “sts:RoleSessionName” value as documented here. Similarly, a vendor named DoIT uses “aws:RequestTag/DoitEnvironment” instead of “sub” as documented here.
Some vendor integrations only use an “aud”, and do not use a “sub” condition or any other condition. For example, Crafting Sandboxes (documented here) and Teleport (documented here). Some vendors do mention an “aud” value, but it is the same value for all customers, and thus does not appear to be needed, such as GitHub (and many others) using an “aud” value of “sts.amazonaws.com”. Other vendor integrations only document a need for a “sub” condition, such as Gitlab (docs) and Bitbucket (docs).
Many of these integrations have customer specific values in the OIDC provider URLs (the part in the “Federated” element of the json policy) or audience values (the part in the “aud” element), or both, that restrict access to a specific customer, so there may be multiple pieces beyond the “sub” condition that is important. In those cases, not having a “sub” condition may not present as large of a risk because an attacker would need to have initial access into the customer to potentially abuse this further. These situations have less risk, but additional conditions should still be used when available.
You need to be very careful when you look at these values. Sometimes they look like random values that you might assume are unique to your customer, but they are not! For example, in the Microsoft Defender integration, EVERY customer uses an OIDC provider URL of sts.windows.net/33e01921-4d64-4f8c-a055-5bdaffd5e33d/ and audience value of api://1462b192-27f7-4cb9-8523-0f4ecb54b47e. Similarly, env0 uses an “aud” value of hoMiq9PdkRh9LUvVpH4wIErWg50VSG1b for all customers (documented here).
Some vendor integrations are run from domains owned by customers which can make it difficult to identify what the integration is. Some AWS customers may also create their own internal OIDC providers, so it is not possible to have an exhaustive list of what every possible vendor integration is. Finally, some providers do not have any public documentation to better understand whether there may be additional recommended conditions.
Sometimes the “aud” condition is not very useful (for example with Github Actions it is always “sts.amazonaws.com”), but a general rule is you should ensure that you have both an “aud” condition and a “sub” condition for all your OIDC integrations, and to investigate the documentation if this is not the case. They may only require one, or they may require a condition other than the “sub” condition.
AWS Access Analyzer has the following policy checks related to OIDC integration that include:
For the different vendors that provide OIDC integrations with AWS, we created detections to look for those integrations that were missing the desired conditions.
Vendor Recommendations
The following table shows a number of vendors we’re aware of, with public documentation, and what conditions are recommended in the OIDC integrations. This is provided to show the variance in these integrations. Please refer to the vendor documentation or their support for confirmation and official guidance.
A ✅ indicates that a value is recommended (and is unique per customer), while a ❌ indicates that the documentation does not have a recommendation for that element. A string in the aud column such as “sts.amazonaws.com” indicates that the same string value is being recommended to all customers, as opposed to being a customer specific value. The “Other?” column mentions other conditional elements that are being recommended.
AWS has four built-in identity providers. These have unique condition requirements as follows (documented here):
cognito-identity.amazonaws.com: Conditions “aud”, “amr”, “sub” and “oaud”.
www.amazon.com: Conditions “app_id”, “sub”, and “user_id”.
graph.facebook.com: Conditions “app_id” and “id”.
accounts.google.com: Conditions “aud”, “sub”, and “oaud”.
It is also common to see OIDC identity providers associated with EKS, as documented here. These should have “aud” and “sub” conditions. The “aud” condition is always set to check for the value “sts.amazonaws.com”. We have seen this is commonly left out, and although we do not know of a security concern with leaving this out for this integration, we believe it is best to align with the documentation for this service and use the condition check for it.
Is having the condition enough?
Even if an integration has the necessary conditions, the condition may not be as correct as it could be. For example, with GitHub Actions, the “sub” condition will include the GitHub organization, repo, and branch, so someone could use a StringLike on the “sub” condition to allow any repo and branch in the organization, which may be more open than it should be.
Going in the other direction of being even more secure, some vendors, such as Bitbucket and Buildkite, go a step further by also recommending that customers restrict access to a set of source IP addresses (documented here and here).
Conclusion
AWS OIDC integrations are a secure way of granting access to an AWS account, but customers sometimes misconfigure them. Many of these integrations have special manual steps to add additional conditions to the policies which customers may miss, resulting in insecure integrations. You should ensure all your OIDC integrations have both an “aud” and “sub”, and investigate any exceptions as there are vendors that work differently.
Dive into the complexities of AWS IAM credentials and uncover how defenders can stay ahead with in-depth knowledge of SDK behaviors and service-specific mechanisms.
Wiz Threat Research investigates misconfigurations in Spring Boot Actuator’s endpoints that can leak environment variables, passwords, and API keys, and even lead to remote code execution.
Get a personalized demo
Ready to see Wiz in action?
“Best User Experience I have ever seen, provides full visibility to cloud workloads.”
David EstlickCISO
“Wiz provides a single pane of glass to see what is going on in our cloud environments.”
Adam FletcherChief Security Officer
“We know that if Wiz identifies something as critical, it actually is.”
Greg PoniatowskiHead of Threat and Vulnerability Management