Exposing Security Observability Gaps in AWS Native Security Tooling
AWS offers a range of native security tools designed to manage and secure cloud environments. But how effective are they at detecting publicly exposable resources? The go-to tool for this task is AWS IAM Access Analyzer. You might wonder why this blog post isn't titled "Gap Assessment of IAM Access Analyzer." The reason is that IAM Access Analyzer's scope extends beyond just user permissions, which is a common misconception.
Common Misconception
IAM Access Analyzer is often misunderstood as being primarily focused on enforcing the Principle of Least Privilege (PoLP). While it does play a role in supporting PoLP, its main function is to identify resources shared with external entities, making it the only native AWS service with significant coverage in this area. This is emphasized in the announcement post introducing IAM Access Analyzer, with the first bullet point in the documentation further elaborates on its primary purpose.
I have seen this misconception brought up by cloud operations and security professionals alike. For reviewing IAM policies attached to IAM entities like users and roles, I personally wouldn't recommend relying on IAM Access Analyzer. There are better and more effective approaches such as manual review of infrastructure as code, security reviews, and adopting a shift-left approach. While these strategies may not address unused permissions retrospectively, being proactive is often a more effective use of time for resource-constrained teams than engaging in reactive efforts.
Coverage
Now that we have cleared up some common misconceptions, let's dive into what IAM Access Analyzer can do! Initially AWS IAM Access Analyzer only supported five services and now its coverage includes much more:
- Amazon Simple Storage Service buckets
- Amazon Simple Storage Service directory buckets
- AWS Identity and Access Management roles
- AWS Key Management Service keys
- AWS Lambda functions and layers
- Amazon Simple Queue Service queues
- AWS Secrets Manager secrets
- Amazon Simple Notification Service topics
- Amazon Elastic Block Store volume snapshots
- Amazon Relational Database Service DB snapshots
- Amazon Relational Database Service DB cluster snapshots
- Amazon Elastic Container Registry repositories
- Amazon Elastic File System file systems
- Amazon DynamoDB streams
- Amazon DynamoDB tables
Gaps
After reading the documentation and reviewing where potential gaps might exist in its coverage, I decided to assess how effective IAM Access Analyzer is at its own game. I found it to be incredibly effective at doing what it is designed and documented to do. However, even five years after its release, there are still some critical gaps that should be addressed or supported.
One could argue that services like ECR Public Gallery or Public AMIs shouldn't be included since they don't resemble IAM resource policies. However, I would counter that by pointing to services like RDS Snapshots and Lambda Functions, which it currently supports. The IAM Access Analyzer team might consider rebranding the tool to better reflect both its common misconception and its actual coverage.
- IAM Access Analyzer effectively detects publicly exposed resources in 65% of the evaluated services.
- Since there is no well maintained definitive list of publicly exposed AWS services, I only included fundamental services for now. Read along until the end if you disagree.
- It does exactly what it claims, with no "snake oil" discovered as part of this research.
- Alerts are triggered only when a service, such as AWS Secrets Manager, is truly public with secretsmanager:GetSecret and its KMS key is public with kms:Decrypt, thanks to automated reasoning.
Note: Enumeration is a scale of 1-5 that was arbitrarily decided by me in terms of ability for attackers to identify the exposed assets. Resources like public EC2 AMIs provide a public directory for anyone to search through which would make it a one, two would be for easily discoverable assets but not publicly listed in AWS, and five would require difficult enumeration techniques to uncover. Policy column is for if it supports a raw json resource policy or abstracted permissions like a checkbox to make public.
Deep Dive
As part of reviewing IAM Access Analyzer, I created a public resource for each of these services and reviewed their coverage. I did so as AWS may not always advertise or document all features within a service, though I did not find that to be the case, and sometimes services are quietly shut down without notice.
All resources created during this exercise was created through dogfooding as part of building out my product. Which thankfully made it so much easier for me to quickly create/destroy vulnerable resources at will.
Below are mostly my raw notes, rephrased using ChatGPT, from what I learned throughout this exercise. Keep in mind it may contain my initial assumptions and gaps in my approach as part of the research. However, you should find some interesting tidbits I uncovered along the way.
- AWS Making Similar Mistakes
- AWS Glue
- AWS Secrets Manager
- AWS Elemental MediaStore
- AWS SES
- AWS CloudWatch Logs
- AWS CLI BUG
1.AWS Making Similar Mistakes
Spending countless hours inside AWS documentation led me to discover a common misconfiguration in AWS-owned assets. I won't go into details, but know that it's never too late to get into AWS Security research. This example illustrates that even the best of us can make mistakes, which may go unnoticed for years. Unfortunately, I won't delve into the specifics of this finding, but it’s important to note that these types of mistakes are common and a leading cause of breaches in the industry.
2.AWS Glue
My first comment is on how poorly the documentation directs users to allow all Glue resources to another AWS account using arn:aws:glue:us-east-1:grantor-account-id:*. While the documentation initially suggests specifying just the catalog and a specific database, it quickly resorts to wildcards across the entire Glue service.
I was unable to ascertain the greatest potential impact, but at a minimum, an attacker would be able to retrieve database and table information. This would include column names, data types, data sources (such as S3), and partitions, giving them a clear idea of what data is stored in your data lakes.
Example Policy
Conclusion
Since Glue clearly uses resource policies and is a fundamental AWS service, there is no excuse for why it is not currently supported by IAM Access Analyzer.
3.AWS Secrets Manager
Upon creating a public AWS Secrets Manager secret, I realized I never received an alert. Did I just find a gap in an advertised capability? Then I discovered: "You can't access a secret from a different AWS account if you encrypt the secret with the default KMS service key." This makes sense since AWS-managed keys within your account can only be accessed from within it, and their policies cannot be modified. Since all Secrets Manager secrets must be encrypted with either an AWS-managed key or a customer-managed KMS key, there is no way to make a secret public without a public KMS key.
I then experimented with creating a KMS key for the Secrets Manager resource, knowing that IAM Access Analyzer would detect it. With this particular resource, you get two alerts for the price of one impact. Another thing I found while debugging is that AWS does not allow public resource policies to be created in the console. It seems AWS is aware that "console cowboys" can pose a greater risk, though blind commits are not necessarily better.
Interestingly, if I added additional actions such as secretsmanager:DescribeSecret to the policy applied using the aws-go-sdk-v2, AWS would accept the policy but not update it. The reason for this is unclear, possibly due to poor error handling, but I'll leave that research for another day.
Conclusion
For a Secrets Manager secret to be public, it requires a public KMS key with the kms:Decrypt action for the principal * and a resource policy associated with the Secrets Manager secret allowing secretsmanager:GetSecretValue. You will not receive an alert just for the latter because, technically, it is not public. This could be an undocumented behavior where a Secrets Manager secret could be public without the owner knowing, waiting for the day a public KMS key is attached to it. When that happens, you will receive alerts for both in quick succession—a good approach.
Note:
IAM Access Analyzer only detects a public Secrets Manager secret if the KMS key is also public, which is a reasonable approach to avoid false positives. However, I wonder if other AWS actions besides secretsmanager:GetSecretValue could be retrieved without triggering an alert.
4.AWS Elemental MediaStore
Since this service is relatively obscure, I'll start by explaining what it is. AWS Elemental MediaStore is a storage service optimized for media, helping you achieve the performance, consistency, and low latency required to deliver live streaming video or media content. The service is relatively bare-bones, allowing you to create containers and modify objects within them. Now, let's get back to the research.
Unlike AWS Secrets Manager, AWS MediaStore allows you to be the "console cowboy" you've always wanted to be, letting you set public access JSON policies directly in the console—which, frankly, is expected. However, different approaches for different services can add confusion as to what is possible for console users. One thing I noticed is that when adding actions to the resource policy, you get the friendly message ValidationException: Invalid Container Policy: The following action names are invalid: "mediastore:DescribeContainer", letting you know which actions can be applied to a resource policy. These error messages are often cryptic, and other services may blindly allow unsupported actions, which complicates a researcher's job. I'm thankful that MediaStore provided clear guidance.
Regarding the impact of exposure, MediaStore URLs are unique, such as https://unvnxyya6cay2b.data.mediastore.us-east-1.amazonaws.com/test/srlogo.png, the certificate used for MediaStore is a wildcard cert *.us-east-1.es.amazonaws.com, and there is no apparent way to externally list the objects in a container. If you found this endpoint with a public resource policy, you would be stuck trying to brute-force objects within it.
Conclusion
Since AWS MediaStore supports resource-based policies, IAM Access Analyzer has no excuse for not supporting it yet. However, since MediaStore is a relatively obscure service, it is understandable that this support might be backlogged.
5.Simple Email Service
This service is ubiquitous across the industry and comes with the added risk of email security nuances. Resource-based policies are widely used and adopted for SES identities, especially for sending emails across accounts. It is well-known that an SES identity can be made public.
Setting the policy to public is straightforward and easy but comes with a caveat. To send an email from that identity, say *@example.com, you would need to verify the email/domain you are sending to. For example, if an attacker wants to send an email from hr@example.com to employee@example.com, they would need to get employee@ to click the verify email address link. While this could be challenging, some phishing solutions automatically click links, potentially verifying the email without user interaction.
Conclusion
AWS IAM Access Analyzer should certainly support public and cross-account delegations to SES identities. I hope it's on the roadmap!
6.AWS CloudWatch Logs
AWS CloudWatch Logs was the only service that truly stumped me. No matter what I did regarding resource policies, I was unable to come up with a proof of concept that demonstrated an impactful and viable approach, making it theoretical as far as I'm concerned. I expect to be proven incorrect someday, and I'm sure there is a way, but I was unable to identify it during my research.
Why did I struggle?
- The PutResourcePolicy API documentation clearly outlines that it is intended for AWS services to put log events into an account, not for retrieving logs. However, this API call does allow you to specify Principal as * for any action.
- The AWS SDK (aws-go-sdkv2) does not permit specifying an ARN in PutLogEventsInput, meaning there's no cross-account logging capability using the AWS API.
- All attempts to retrieve logs failed with the error is not authorized to perform: logs:GetLogEvents on resource: arn:aws:logs:us-east-1:111111111111:log-group:my-public-log-group:log-stream:public-log-stream because no resource-based policy allows the logs:GetLogEvents action, regardless of the resource policy.
- After reading the documentation, it appears that the PutDestinationPolicy and PutResourcePolicy API calls are almost synonymous.
- I also found that you can use the --name flag with the ARN of the resource instead of its name using the AWS CLI, though I never attempted this as the API would likely prevent me from doing so.
- After a few hours of research, I realized it's okay not to know everything and decided not to dig any further.
7.AWS CLI Bug
The aws logs delete-resource-policy command is an exception in the AWS CLI. When the required policyName parameter is not specified, instead of displaying the usual error message (aws: error: the following arguments are required:), it simply returns an error: An error occurred (InvalidParameterException) when calling the DeleteResourcePolicy operation: 1 validation error detected: Value null at 'policyName' failed to satisfy constraint: Member must not be null. This might be a minor bug in the AWS CLI, but it's not a significant concern.
Expected Output Example
If you fail to specify the required parameters, AWS will notify you:
Potential Bug
Deploying IAM Access Analyzer
Deploying IAM Access Analyzer is simple and straightforward, especially with AWS Organizations. You can quickly deploy it across all your accounts in each region in a jiffy. Additionally, you can manage ignore rules through Infrastructure as Code (IaC), which is an outstanding way of managing filter rules! There is really no excuse not to have it enabled today.
Pricing
AWS IAM Access Analyzer is one of the most affordable AWS security services, even at scale. I applaud AWS for not trying to price people out of the product. So why am I talking about pricing then? AWS Trusted Advisor provides some findings that go a bit deeper than IAM Access Analyzer, but unfortunately, I was unable to review it.
Support Tax
A common issue in the security industry is SSO tax, where vendors gate security features. While this approach may seem like a fair way to provide pricing tiers, it also strongly discourages a fundamental core security requirement for many. This can lead to teams avoiding implementing common security controls on products simply to avoid expensive license fees. You might be wondering why I'm talking about that here.
Let me introduce you to the AWS Support Tax. To get started, I would need to pay $100/month as a small bootstrapped business. If you're familiar with AWS Support pricing for enterprises, it gets much more expensive. I was approved for $1,000 from AWS Activate, so I would like to thank AWS for that, as every little bit helps. However, as a small security business, I'm going to spend that money where it counts.
I would also like to add that Trusted Advisor is not like other security services and is primarily used by console users, but that's a topic for another day. I just couldn't write about Access Analyzer without mentioning it.
Conclusion
AWS IAM Access Analyzer excels in focusing on impactful publicly accessible resources, allowing you to avoid the noise that commonly plagues enterprise security products. It includes coverage of about 65% of publicly exposable AWS services I was willing to investigate. IAM Access Analyzer is a valuable asset for securing your AWS environment, though some gaps still exist.
- AWS IAM Access Analyzer does an excellent job of automated reasoning for publicly exposed services, only alerting for impactful policies.
- It is easy to deploy, inexpensive to maintain, and simple to manage. There is no excuse not to deploy it in your environment.
- I am giving it a coverage score of 65%, which provides most organizations with the coverage they need with gaps you should be aware of.
- It is never too late to find common misconfigurations in exposed assets, as I was able to identify one in a AWS owned asset during this research.
- You can sometimes use the --name flag in the AWS CLI with the ARN of the resource.
- Some AWS resources prevent you from applying public resource based policies in the console.
- AWS resource policies vary greatly between services in which some will reject actions that are not supported in resource policies while others accept them without error.
- SummitRoute/aws_exposable_resources is no longer maintained, and I strongly welcome SecurityRunners/cloud-exposure-catalog as a hopeful replacement. It is in early development and I welcome any pull request!
Also please do not hesitate to reach out! I am a small bootstrapped security startup, I will listen to just about anyone who wants to talk cloud security or security chaos engineering.