Not Just Buckets: Are You Aware of ALL Your Public Resources?
A misconfiguration of resource-based policies can inadvertently make resources public. Do you have such misconfigured policies present in your environment?
Join the DZone community and get the full member experience.
Join For FreePublic exposure to resources is a point of dread for many security practitioners. Public resources are low-hanging fruit for attackers seeking to access sensitive information or manipulate an activity -- or even deny the availability of mission-critical resources.
One well-known culprit for exposing resources is AWS built-in mechanisms. While misconfiguring them is a common and legitimate concern for security practitioners charged with protecting AWS environments, we often see another mechanism that may be even more misconfiguration-prone: resource-based policies.
We’ll touch briefly on built-in mechanisms but focus primarily on this lesser-known cause: the configuration intricacies of resource policies that can render resources as exposed and out in the open as a deer caught in headlights.
Proceed With Caution: Built-in Mechanisms
AWS offers built-in mechanisms for configuring certain resource types as public. One unique mechanism is Access Control Lists (ACLs) for S3 (Simple Storage Service) buckets -- a widely used and highly durable AWS storage service. The ACL mechanism can make specific actions publicly accessible to perform on a bucket.
All that is needed to grant public access when using ACLs is to allow permissions to the “Everyone” group. You can publicly enable the listing, the writing or overwriting of a bucket’s contents, and even the changing of the ACL itself.
Allowing permissions to the Everyone group is a practice to be discouraged. AWS warns users clearly when they attempt such a configuration. Also, to AWS’s credit, we can report that the ability to configure writing as public permission in an ACL or overwriting the ACL is not available via the console, only by using the cli. This limitation minimizes the chance that such sweeping permissions will be granted by mistake. AWS also offers effective mechanisms to outright deny ACLs from applying at the bucket and account levels.
Other AWS built-in mechanisms are also available, including RDS snapshot sharing and AMI EC2 image sharing, for configuring resource types different than buckets as public. Let’s look now at resource-based policies, which may be as risky as built-in mechanisms in exposing resources.
Resource-Based Policies Gone Wildcard
A resource-based policy is a mechanism available on several types of AWS resources that allows granting access directly to the resource. In contrast to an IAM policy, which can only grant permissions to the principals managed in the account, a resource-based policy allows granting access to principals outside the account. One specifies the principal used to give the permissions and... surprise, surprise: this can wind up being any AWS principal from any AWS account. Let’s see how.
A statement from a resource-based policy may look like this:
{
"Sid": "AllowAccessToExternalAccount",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT_ID>:root"
},
"Action": [
"<service>:<PermissionName>"
],
"Resource": "<RESOURCE_ARN>"
}
In this case, the “Principal” field is specified with a configuration that allows another account, via IAM policies, to grant access to the principals in it. Basic stuff, right? Yet, if misconfigured, a resource-based policy can give access to any principal.
In multiple real-world scenarios (including production environments), we’ve found resource-based policies with statements using the following definition for the “Principal” field:
"Principal":
{
"AWS": "*"
}
This wildcard configuration is convenient when a developer or DevOps engineer doesn’t know exactly which principal will need access to the resource. They may instinctively think the open-ended designation gives access to only principals in the resource's account, but this is not the case. The wildcard “*” means the statement applies to all principals the policy may apply to -- and a resource-based policy could apply to any AWS principal in any AWS account. So, the actual effect of this statement is to make the resource public for any actions the statement allows that aren’t denied elsewhere.
As Inigo Montoya might put it:
Matters are even worse when the “Action” field also uses a wildcard, allowing all principals to perform possible actions on the resource. It should also be noted that, in this case, the only way to deny access to perform the actions granted by the statement is with another statement on the resource-based policy with a condition denying the access. A Service Control Policy (SCP), for example, won’t be any help since SCPs apply only to principals in the account to which they are attached. By definition, an SCP doesn’t affect principals from external accounts.
Faulty Powers: Misconfigured Resource Policies
We detail below AWS resource types on which we found such an open-ended or otherwise faulty role or policy configuration and its potential impact in making the resource public. Remember that these instances are not theoretical; instead, they were detected in real-world environments configured by savvy infrastructure teams from well-respected organizations.
IAM Roles Exposed for Assuming
IAM Roles are an exciting resource type that we found configured for public exposure. An IAM Role is an AWS resource, and its “trust relationship” is a resource-based policy. Allowing sts: Assume Role to “AWS”: {“*”} would make the role potentially assumable by any principal.
This use case is interesting because an external principal allowed to assume an IAM Role would be able to use all the permissions in every policy attached to the role. Such a misconfiguration has massive potential fallout: it could well allow all external principals in an environment to have incredibly powerful permissions (up to the admin level).
Havoc on Image Permissions in ECR Repositories
AWS’s Elastic Container Registry (ECR) is a service that lets you “store, share and deploy your container software anywhere.” You create repositories to easily store and manage container images that you or anyone you share them with will pull later to deploy applications on containers -- using, for example, a Task Definition on AWS’s Elastic Container Service. ECRs offer other excellent features, such as scanning the stored container images for vulnerabilities -- and their API lets you streamline the management of images and version lifecycles as part of your deployment process.
ECR repositories are also an AWS resource. As you may have guessed, they support resource-based policies where we’ve seen misconfigurations. Let’s illustrate the problem: The following set of permissions is required to allow an identity to push an image to an ECR repository:
"Action":
[
"ecr:CompleteLayerUpload",
"ecr:UploadLayerPart",
"ecr:GetAuthorizationToken",
"ecr:InitiateLayerUpload",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage"
]
An identity granted these permissions may be able to push a new image to a repository with a specific tag; doing so effectively replaces a version currently used in an ECS task definition or that can be pulled for deployment using another tool. This configuration has a potentially severe impact. It could allow a malicious actor to run its software using the victim's permissions to the service deploying it.
Note that if you’ve set an immutable tag on a repository, it won’t be possible to push an image under an existing tag. However, a malicious actor with access to ecr:PutImageTagMutability could also change this configuration.
A malicious actor can also use ecr:DeleteRepository or ecr:BatchDeleteImages to remove the repository and interrupt its services. Finally, if the containers include sensitive information or logic, you don’t necessarily want to be public; even permission such as ecr:BatchGetImage (and ecr:GetAuthorizationToken for authentication), which allows pulling an image, could be pretty sensitive.
Service Denied and Decryption Through KMS Keys
In AWS, one manages access to customer-managed KMS keys using IAM policies and key policies (KMS’s resource-based policy), which could also take action on the key publicly available.
In our recent study on permissions combinations that could be used to execute a ransomware attack on misconfigured S3 buckets, we discussed using the kms:PutKeyPolicy permission to change the key policy set a customer-managed KMS key. With this simple action alone, a malicious actor can hijack and deny access to the key. Doing so can restrict the ability to use kms:Decrypt on the key -- effectively performing a Denial of Service attack on all the data encrypted using the key. This denial will not work in a cross-account scenario but allows permission to all principals within the account where the key is managed.
Another interesting permission is kms:CreateGrant, which could be used cross-account and provide any principal with permission to cryptographic actions, including kms:Decrypt on the key. The AWS documentation says: “The grantee principal can be an identity in a different AWS account.”
In other words, if this permission is made public on a key, pretty much anyone can use it for decryption.
Letting Others in on Your Secrets Manager Secrets
It’s no secret that AWS’s Secret Manager is great for securely holding sensitive strings that may be accessed by applications running on serverless resources and other compute functions. A Secrets Manager secret is an AWS resource that supports a resource-based policy. The resource can be made public in the method described above -- and by providing external identities with access to permissions such as secretsmanager:GetSecretValue, which is the sensitive information stored in secret. The sensitive information can be a database connection string, an API key, an access token, etc. The ease of unwittingly exposing a secret through this permission is an excellent example of why using encryption with a customer-managed KMS key on a secret is a sound idea: even if the secret is made public, access to it wouldn’t be granted without the additional access to use kms:Decrypt on the key used to encrypt it.
Disrupting and Accessing SQS Queues
AWS’s Simple Queue Service (SQS) is a fully managed MQ that you can, according to AWS, use to “send, store, and receive messages between software components.” It’s a great way to free developers from managing and operating such middleware at the expense of writing software. However, if access to specific permissions on a queue is compromised, the queue may be exposed to certain risks. For example, a malicious actor may be able to access sensitive data transferred on it by using sqs:ReceiveMessage, manipulate the queue’s activity by sending their messages using sqs:SendMessage, interrupt its activity, and cause malfunctions to your operation by deleting the queue altogether using sqs:DeleteQueue (note that this permission cannot be used cross-account) or purge the queue’s current contents using sqs:PurgeQueue.
Mucking up Communication on SNS Topics
AWS’s Simple Notification Service (SNS) is a tool that enables application-to-application or application-to-person communication on a publisher/subscriber model. The user creates topics (an AWS resource) and a subscription for each topic, including a description of a protocol and an endpoint, such as an email address, to which messages will arrive once published on the topic.
A malicious actor that gains access to sns:Subscribe can also access the information shared on the topic. By gaining access to sns:Publish, the malicious actor can broadcast information to subscribers of the topic. Using permissions such as sns:DeleteTopic or sns:Unsubscribe may disrupt the service activity. Even by using other read permissions of the pattern sns:List* or sns:Get*, a malicious actor can gather sensitive information about business activity supported by SNS.
Yet Another Public Attack Angle on S3 Buckets
Finally, a bucket can also be made public in the same way as mentioned in the use cases above by misconfiguring resource policies to (inadvertently) expose pretty much any permission imaginable to any external identity that may encounter it. Ill-defined resource policies can open a bucket to the public by allowing the listing and reading of its contents, overwriting, and deletion of the information on it. Remember: just because it’s not configured via an ACL doesn’t mean the bucket cannot be made public!
Conclusion
Understanding what resources in your cloud environment are publicly exposed is extremely important to mitigate unintended access to them. Incorporating visibility into all public resources in your environment is important for a cloud security product.
Public access to a resource can be configured using a built-in mechanism; however, where supported, resource-based policies are yet another critical mechanism that should be tracked to protect a cloud environment. Doing so enables you to detect and prevent unintended access to resources, especially by external identities to an account.
Effective tracking of resource-based policies and the access they grant can be tough when done manually. Automated, ongoing review of such configurations in your AWS environment is strongly recommended as a preferred approach.
Published at DZone with permission of Lior Zatlavi. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments