When we grant third-party services access to carry out tasks within our AWS accounts we leverage the capabilities of IAM Roles. The benefits of using IAM Roles over IAM Users directly is that we can provide access through temporary credentials that AWS automatically rotate for us, which reduces the risk of compromise.

What happens when assuming an IAM Role?

When a principal assumes an IAM Role it gives up the permissions it currently has and assumes the permissions associated with that IAM Role. At the point of assuming a role, AWS generates access keys that are valid for a specific period of time.

To achieve this the principal must have permissions to use the AWS Security Token Service (STS) with the sts:AssumeRole permission for the role in question. On the other side the IAM Role must allow the principal to assume the role via an attached or inline IAM Policy.

What is a confused deputy vulnerability?

When the process of assuming roles involves cross account permissions we’re allowing a third-party to access our AWS account to carry out specific tasks as a deputy, and for managed services the level of access provided can be significant. The vulnerability occurs when another AWS account owned by a bad actor is able to trick the third-party into providing access to our account, resulting in a confused deputy.

diagram depicting how a confused deputy attack is introduced and then exploited by a malicious actor

The steps of introducing the vulnerability and executing a confused deputy attack include:

  1. An IAM Role for the 3rd party to assume is created in our AWS account
  2. The ARN is provided to the 3rd party service
  3. The 3rd party service creates an IAM User to assume the IAM Role cross account
  4. The 3rd party service assumes the role to carry out its tasks as expected
  5. A hacker passes your IAM Role ARN to the 3rd party service
  6. The 3rd party service creates an IAM User for the hackers instance of the service to assume cross account
  7. The service accesses your account to carry out its tasks and feedback to the attackers dashboard in the 3rd party service

How to prevent confused deputy attacks

The solution for avoiding confused deputy attacks against your AWS accounts, and persisting the option to delegate access, is to ensure we utilise a trust policy on our IAM Roles and include an External ID. This External ID is provided by the third-party during setup and is often represented as a GUID, which is a unique identifier shared only between you and the third-party and it dictates who can assume the cross-account role. An example trust policy to prevent confused deputy:

{
 "Version": "2012-10-17",
 "Statement": {
   "Effect": "Allow",
   "Principal": {
     "AWS": "12345678910"
   },
   "Action": "sts:AssumeRole",
   "Condition": {
     "StringEquals": {
       "sts:ExternalId": "b8ee735e-0f96-4b44-96c2-166cdcce8dfc"
     }
   }
 }
}

The External ID is usually automatically generated at the point of setting up the integration, and supplied on requests thereafter by the third-party; the conditional only allows assumption of the role when there is a matching External ID. When an attacker attempts to provide your ARN to the third-party service they will have no knowledge of the External ID value and won’t be able to proceed.

It’s important to ensure all cross account access is only granted with the inclusion of a trust policy with a conditional based on an External ID.

Useful Resources