Confused Deputy Vulnerability in Amazon DataZone
The AssociateEnvironmentRole API lacked cross-account validation, letting an attacker assume roles in any AWS account that trusted the DataZone service principal. Reported August 2024, now fixed.
A vulnerability in Amazon DataZone could have allowed potential attackers to assume roles in AWS accounts by exploiting a confused deputy problem in DataZone environments. This issue, which has been resolved, would have potentially granted unauthorized access to sensitive data managed by DataZone, or any other AWS service accessible by an IAM role that trusts the DataZone service in the case of misconfigured or overprivileged roles.
This problem was reported to AWS Security on Aug 29th, 2024 and is already fixed. As per AWS, no customers were impacted.
Introduction
The confused deputy problem is a well-known issue in AWS environments. Extensive research has been conducted on this topic, most AWS services implement safeguards to mitigate this risk, and the documentation provides clear guidance on how to prevent it. Given this context, discovering such a vulnerability in a newer service like Amazon DataZone was unlikely.
For more information on the confused deputy problem in AWS, refer to the official AWS documentation.
What is Amazon DataZone?
Amazon DataZone is a data management service with lots of features, so in this blog we will focus on only the key aspects needed to understand this vulnerability. It doesn't store the data itself, but facilitates the cataloging, discovering, sharing, and governing of data stored across AWS, on-premises, and third-party sources. The service operates primarily with two main components: data producers and consumers. Data producers publish assets to the business data catalog. These assets can be AWS Glue tables, Amazon Redshift or custom data sources. Data consumers or subscribers can find, access, and consume assets in the data catalog.
As a data governance tool, DataZone may have visibility and provide access to an organization's most sensitive data stores. It's important to note that this access is not granted by default. A DataZone administrator or user with the right permissions must explicitly create and configure data sources. When the default blueprints are used, these permissions can be managed by AWS LakeFormation.
DataZone Data Portal
The DataZone data portal is outside the AWS Management Console, and is a browser-based web application where different users can catalog, discover, govern, share, and analyze data in a self-service fashion. The data portal authenticates users with IAM credentials or existing credentials from your identity provider through AWS IAM Identity Center. On each domain there is a hyperlink that opens a new tab with the data portal, and only works if the user has the permission to access it (datazone:GetIamPortalLoginUrl).
The activities and roles available to users with access to the portal and its projects can be reviewed at docs.aws.amazon.com/datazone.
Account Association
A key feature in this service is enabling collaboration across different AWS accounts, belonging to the same or different AWS organizations. From a DataZone domain, administrators can establish associations with any AWS account. Under the hood, DataZone uses AWS Resource Access Manager (RAM) to grant these external accounts access to DataZone APIs. There are two permission modes available:
- AWSRAMPermissionDefault: Provides basic API access.
- AWSRAMPermissionPortalReadWrite: Grants additional access to the DataZone portal.
Once the external AWS account accepts the invite, users in that account can access resources in the DataZone domain according to their permission mode.
Environments in DataZone
In the context of an Amazon DataZone project, environments are collections of configured resources (e.g., Amazon S3 buckets, AWS Glue databases, or Amazon Athena workgroups) with associated IAM principals who can operate on those resources. There are two types:
- Default environment blueprints (e.g., Default Data Lake, Default Data Warehouse). These use pre-configured blueprints provided by AWS, defining a set of AWS tools and services that project members can use when working with assets in the DataZone catalog.
- Custom environment blueprints. These allow for greater flexibility and integration with existing AWS resources. Administrators can customize DataZone project environments to use existing IAM roles and AWS services not available in default blueprints (e.g., AWS Glue ETL jobs or any analytics tool).
This is how a trust policy in an IAM role created by the Default Data Lake blueprint looks:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "glue.amazonaws.com" },
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": [
"datazone.amazonaws.com",
"auth.datazone.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole",
"sts:TagSession",
"sts:SetContext",
"sts:SetSourceIdentity"
]
},
{
"Effect": "Allow",
"Principal": { "Service": "lakeformation.amazonaws.com" },
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::187xxxxxxxxxx:role/service-role/AmazonDataZoneProvisioning-187xxxxxxxxx"
},
"Action": "sts:AssumeRole"
}
]
}
AWS documentation suggests this policy for custom environment roles:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": ["datazone.amazonaws.com"]
},
"Action": [
"sts:AssumeRole",
"sts:TagSession"
]
}
]
}
When users click on the environment's deep link (shown on the right), it opens a new browser tab where they are federated into the AWS console with the associated "User role". If this role belongs to a different AWS account than the user's current session, the AWS Console displays a warning requiring the user to log out first. This account-switching behavior is demonstrated in the proof of concept below.
The Vulnerability
The confused deputy problem occurs when a service (the deputy) with higher privileges can be tricked into performing actions it shouldn't. In AWS, this could potentially manifest as one service inappropriately assuming the role of another.
Previous research on this topic, such as that conducted by researchers at Datadog, has been particularly insightful. Their research revealed that while AppSync had built-in validations to prevent cross-account role associations, these protections could be bypassed through case sensitivity manipulation of API parameters. In DataZone's case, however, it was more straightforward: the service didn't apply any validation controls that would typically prevent associating external roles.
The ability to assume a role in an environment is an expected behavior in DataZone, as it allows authorized subscribers to access data securely and easily. However, the vulnerability arose from the possibility of using a custom environment and its API call AssociateEnvironmentRole to associate any arbitrary role ARN, even from AWS accounts that were not associated with the DataZone domain.
An attacker with knowledge of a role ARN in any existing AWS account that (a) trusts datazone.amazonaws.com, and (b) does not have IAM policy conditions preventing unauthorized AWS account principals from assuming it, could have exploited this vulnerability to assume the role and access whatever data that role is granted access to.
Steps to Reproduce
To illustrate this problem, these are the steps to create a custom environment where the vulnerability could be exploited:
Step 1: Create a DataZone domain.
aws datazone create-domain \
--domain-execution-role arn:aws:iam::187xxxxxxxx:role/service-role/AmazonDataZoneDomainExecution \
--name test_domain
Step 2: Once created, enable custom blueprints (Custom AWS Service).
aws datazone put-environment-blueprint-configuration \
--domain-identifier dzd_5rwijxxxxxxx \
--enabled-regions us-east-1 \
--environment-blueprint-identifier ca1cxxxxxx
Step 3: Create a custom environment using the AWS CLI.
aws datazone create-environment \
--domain-identifier dzd_d4hxxxxxxxx \
--environment-blueprint-identifier ca1cxxxxxx \
--environment-profile-identifier "" \
--name testcli \
--project-identifier 6swvxxxxx \
--environment-account-identifier 187xxxxxxxxxxx \
--environment-account-region us-east-1
Step 4: Create an environment action attached to the environment.
aws datazone create-environment-action \
--domain-identifier dzd_d4hxxxxxxxx \
--environment-identifier 3tuxxxxxxxxxx \
--name "Console login" \
--parameters '{"awsConsoleLink":{"uri": "https://console.aws.amazon.com/"}}'
Step 5: Associate the environment role. This is where the vulnerability was exploitable.
aws datazone associate-environment-role \
--domain-identifier dzd_d4hxxxxxxxx \
--environment-identifier 3tuxxxxxxxxxx \
--environment-role-arn arn:aws:iam::965xxxxxxxx:role/datazone_axxxxxxxx
The vulnerability was possible because of Step 5. While the console UI only showed roles from the current account, the AssociateEnvironmentRole API call lacked proper validation and allowed associating any arbitrary role ARN from any AWS account. If that role trusted datazone.amazonaws.com as a service principal, an attacker could bypass intended access controls and assume the role.
This is a demonstration of the behavior:
In a simplified version, this is what is happening:
The DataZone service and portal exist in an AWS Service Team account. When a domain is created it associates the AWS account that created it by default. In the more detailed flow, inferred from browser developer tools and CloudTrail events in both attacker and victim accounts, the getEnvironmentActionLink call pulls a sign-in token:
{
"actionLink": "QifP6cnUD_HIRHKufQEPJq6MgY_VBEoQm8mUxxxxxxxxxxxxxxxxx"
}
After that, there is a call to the federation endpoint:
https://signin.aws.amazon.com/federation?Action=login
&Destination=https%3A%2F%2Fconsole.aws.amazon.com%2F
&Issuer=
&SigninToken=QifP6cnUD_HIRHKufQEPJq6MgY_VBEoQm8mUxxxxxxxxxxxxxx
The actionLink in the response and SigninToken in the subsequent request match, therefore it's easy to assume the DataZone service calls assumeRole and getSigninToken on behalf of the caller to return a token that can be used to federate the access.
In the victim account, there is an AssumeRole call followed by a GetSigninToken. In both cases the IP address and user agents confirm the calls are coming from the DataZone service:
{
"eventVersion": "1.08",
"userIdentity": {
"type": "AWSService",
"invokedBy": "datazone.amazonaws.com"
},
"eventTime": "2024-xx-xxTxx:44:51Z",
"eventSource": "sts.amazonaws.com",
"eventName": "AssumeRole",
"awsRegion": "us-east-1",
"sourceIPAddress": "datazone.amazonaws.com",
"userAgent": "datazone.amazonaws.com"
}
{
"eventVersion": "1.09",
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROA6xxxxxxxx:0358f385-84c0-44e1-b968-xxxxxxxxx@4lnxxxxxx",
"arn": "arn:aws:sts::965xxxxxxx:assumed-role/AmazonDataZone_xxxxxxxx/...",
"accountId": "965xxxxxxxxx"
},
"eventTime": "2024-xx-xxTxx:xx:02Z",
"eventSource": "signin.amazonaws.com",
"eventName": "GetSigninToken",
"awsRegion": "us-east-1",
"sourceIPAddress": "3.95.x.x",
"userAgent": "Java/17.0.12",
"responseElements": {
"credentials": { "accessKeyId": "ASIAxxxxxxxxx" },
"GetSigninToken": "Success"
}
}
An API released in DataZone after I finished the research called GetEnvironmentCredentials would have simplified this further, as calling it returns the AccessKeyId, SecretAccessKey, and SessionToken necessary to assume the role in the victim account via CLI or SDK.
Note: The ability to assume a role from the deep link in an environment is expected behavior in DataZone. DataZone data consumers should be able to access tools in the environment, even from another account, as long as it is an associated AWS account. The issue was specifically the possibility of using a custom environment and AssociateEnvironmentRole to reference a role from an account that was never associated with the DataZone domain.
Scope and Impact
Affected AWS accounts: Any AWS account using, or that has used, DataZone and didn't clean the IAM roles.
The vulnerability affected two types of roles:
- DataZone custom environment roles. AWS documentation for creating custom environments didn't instruct customers to limit role assumption to trusted AWS accounts. Many organizations might not have created roles with proper restrictions to trusted accounts only.
- Roles created from default blueprints. These environments are created by a CloudFormation template deployed by the service. Unlike other DataZone service-created roles, the template role creation did not add an
aws:sourceAccountcondition to the trust policy.
The level of access on those AWS accounts depends on the IAM role configuration:
- DataZone custom environment roles: Depends on company practices for these roles. It is not possible to know the full extent of the issue as it could easily be an over-privileged role.
- Roles created from default blueprints: While the trust policy isn't locked down, the IAM policies of the roles are. There is still broad access to
List*andGet*calls in some services such as IAM, and a few other concerning permissions even after considering the permissions boundary applied. The data these roles can access may be sensitive, and by being able to list roles in an unrestricted manner, it may be possible to find another equally vulnerable role with higher privileges or access to other data stores.
While this vulnerability was serious, widespread exploitation was challenging:
- Role ARN guessing difficulty: An attacker would need to know or guess both the AWS account number and the role name. For default environment roles, this created a vast number of possibilities making brute-force attacks impractical. For custom environments, it depends on IAM role naming standards. But this is not acceptable risk for most companies when you consider: ex-employees, an employee pasting error logs in public forums, or a determined attacker.
- Role ARN guessing is difficult, but in the next blog I will discuss one method that could have been used to guess the AWS account part of the role ARN by using an AWS service (reported to AWS security, and no longer works).
For other roles used or created by the DataZone service: all default service roles are protected by the condition "aws:SourceAccount": "{{domain_account}}", which prevents an environment role in a random AWS account from assuming it. This suggests the service team was aware of this class of issue but for some reason didn't implement the same validation for environment roles.
Conclusion
This vulnerability in Amazon DataZone serves as a reminder that even in newer cloud services, classic security issues like the confused deputy problem can still occur. It underscores the importance of:
- Proper IAM role configuration, especially when dealing with cross-account or service principal access. Ensure
aws:SourceAccountandaws:SourceArnconditions are being used. - Regular security audits of cloud services and their associated roles. If the AWS console UI doesn't show or allow external roles, validate whether the API permits it.
- The need for cloud service providers to implement robust security measures by default.
For Amazon DataZone users:
- Ensure AWS accounts associated to a domain are properly vetted, and user memberships in projects are authorized.
- Regularly review and audit IAM roles and their trust relationships.
- Enforce least privilege access principles.
While AWS has fixed this particular issue, it serves as a lesson in the ongoing need for threat modeling and testing assumptions.
Vendor Notification Timeline
"The AWS DataZone team was able to validate the proof of concept you provided and confirmed there were no changes with the new API releases that would have impacted your PoC. The team completed the investigation and determined from your PoC, that a project member (third party) can associate any random AWS role to the environment in the project. But the third party still would not be able to assume this role, unless the role has allowed a DataZone Service Principal to trust it."
"The DataZone team made changes to correct the behavior with the AssociateEnvironmentRole and DisassociateEnvironmentRole APIs and deployed a fix globally. No documentation updates were made because this is correctly outlined in the DataZone create a custom environment documentation."
Reference: docs.aws.amazon.com/datazone/latest/userguide/create-custom-environment.html
