Skip to content

Article by Nick Frichette.

Misconfigured Resource-Based Policies

Resource-based policies are an often overlooked part of AWS security that can have significant implications. A resource-based policy is a type of policy that is attached directly to an AWS resource that describes what actions can be performed on it and by whom.

For example, the following is a bucket policy (a type of resource-based policy) that would permit the tester user to list the contents of the super-public-fun-bucket S3 bucket.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowS3Listing",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:user/tester"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::super-public-fun-bucket"
        }
    ]
}

Resource-based policies make it easy to share AWS resources across AWS accounts. They also, as a result, make it easy to unintentionally share resources. The common example of this is misconfigured S3 buckets which leak sensitive information.

For a Penetration Tester or Red Teamer it is important to understand the intricacies of how resource-based policies work, and how they can be abused.

The “*” Principal and Risks

In a resource-based policy you must specify a “principal”. This is the entity who is allowed (or denied) the ability to perform the action. It is possible to specify “*” as a principal which means that all users will be able to act on it. This effectively makes the resource public and anyone can perform actions against it.

For a real world example of this, a telecommunications company had the following bucket policy set.

{
  "Sid": "AllowPublicRead",
  "Effect": "Allow",
  "Principal": {
    "AWS": "*"
  },
  "Action": [
    "s3:GetObject",
    "s3:PutObject"
  ],
  "Resource": "arn:aws:s3:::media.tellacom.com/taskrouter/*"
}

The bucket this policy was attached to was used to distribute a JavaScript SDK, which would be a valid use-case for a public S3 bucket. As can be seen from the Action statement, the policy permitted both s3:GetObject and s3:PutObject. This enabled an attacker to overwrite the JavaScript SDK sitting in the bucket with malicious code. This code was then distributed from the legitimate bucket.

While resource-based policy misconfigurations are often associated with leaking information (read), it is equally as dangerous that an adversary could modify (write to) the resource(s).

Note

Condition operators can be used to scope down the policy. For example, the principal can be set to “*” but the conditions can enforce which account can perform an action. It is important to thoroughly read the policy and understand the context before creating a finding for it.

More Than Just S3 Buckets

It is worth noting that there are many different AWS services/resources which make use of resource-based policies. Each service will have its own security implications based on what the principal is and what the actions are.

Note

Prowler, an AWS assessment tool, can be used to quickly audit resource policies in an AWS account. Be mindful that it cannot contextualize all condition operators, and how they affect the account’s security.

Resource-Based Policy Evaluation Logic

It is important to note that resource-based policies have a unique quirk when it comes to policy evaluation logic. From the documentation, “Depending on the type of principal, an Allow in a resource-based policy can result in a final decision of Allow, even if an implicit deny in an identity-based policy, permissions boundary, or session policy is present [within the same account]”.

Note

An implicit deny is when there is no specific Deny statement, but there is also no Allow statement in a policy. You can think of an implicit deny as the starting point of a policy. Everything is denied by default and access has to be granted.

An explicit deny is when there is a specific Deny statement in a policy.

More information can be found in the documentation for the difference between explicit and implicit denies.

This means that if there is an Allow in a resource policy, that entity can perform actions on the resource without an associated identity policy. Take the following SNS topic access policy (a form of resource-based policy) for example:

{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__default_statement_ID",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:user/tester"
      },
      "Action": [
        "SNS:GetTopicAttributes",
        "SNS:SetTopicAttributes"
      ],
      "Resource": "arn:aws:sns:us-east-1:111111111111:test_topic"
    }
  ]
}
This policy would permit the tester IAM user to perform sns:GetTopicAttributes and sns:SetTopicAttributes without the need for an Allow in the identity policies attached to the user.

Note

This behavior only applies to entities in the same AWS account. If the resource-based policy specified an IAM user in a different AWS account, that user would need to have an identity policy attached that allowed the action.

“Not” Policy Elements

Within the syntax for IAM policies in AWS exist three “Not” policy elements, NotPrincipal, NotAction, and NotResource. These elements have the inverse effect of their similarly named counterparts and, when paired with an Allow, can be a very serious misconfiguration.

Because of this, policies which include these elements should be strictly scrutinized for potential misconfigurations.

NotPrincipal

The NotPrincipal element is used to specify which entity is not a part of the policy. When paired with an Allow this means that all entities (including those outside of the account) will be permitted to perform actions against the resource.

For example, the following SNS access policy would permit any entity to perform sns:GetTopicAttributes except for the jim user.

{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__default_statement_ID",
      "Effect": "Allow",
      "NotPrincipal": {
        "AWS": "arn:aws:iam::111111111111:user/jim"
      },
      "Action": "SNS:GetTopicAttributes",
      "Resource": "arn:aws:sns:us-east-1:111111111111:test_topic"
    }
  ]
}

NotAction

The NotAction element is used to specify all actions except the specified one. When paired with an Allow this means that all actions except the ones specified will be permitted.

For example, the following SNS access policy would permit any entity the ability to perform all SNS actions except sns:Publish.

{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__default_statement_ID",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "NotAction": "SNS:Publish",
      "Resource": "arn:aws:sns:us-east-1:111111111111:test_topic"
    }
  ]
}

NotResource

The NotResource element is used to specify all resources except the specified one. When paired with an Allow this means that if the resource is incorrect, or mistyped, the statement will evaluate to true.

For example, the following SNS access policy for an SNS topic named first_topic would permit the user jim the ability to perform the sns:GetTopicAttributes action because the statement specifies a NotResource element of second_topic.

{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__default_statement_ID",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::222222222222:user/jim"
      },
      "Action": "SNS:GetTopicAttributes",
      "NotResource": "arn:aws:sns:us-east-1:111111111111:second_topic"
    }
  ]
}