avatarTeri Radichel

Summarize

Protecting KMS keys, S3 buckets and other resources from unintended exposure

ACM.34 Limiting the Confused Deputy Attack in Resource Policies

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

⚙️ Check out my series on Automating Cybersecurity Metrics. The Code.

🔒 Related Stories: AWS Security | KMS | S3

💻 Free Content on Jobs in Cybersecurity | ✉️ Sign up for the Email List

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In the last post we looked at how we can restrict which identities a user an assume by adding restrictions to an AWS IAM Policy.

We did that to prevent the confused deputy problem on AWS where an attacker might be able to leverage a role to obtain access to something they shouldn’t be able to access in an AWS account.

In subsequent posts we looked at how to fix the problem for trust policies and IAM policies. Now we need to take a look at the one remaining issue: resource policies.

The post above explains what we can do to protect resources in a resource policy fro this attack. Resource policies would apply to things like S3 buckets, Encryption Keys, Secrets, and other resources on AWS that allow you to apply a resource policy to them.

AWS says in their documentation to add the aws:SourceArn and aws:SourceAccount global condition context keys to limit access to the resources the policy protects. What are global condition context keys? I wrote about the different types of conditions you can add to an AWS Policy here:

Let’s take a look at the resources we have created so far that have resource policies: Our KMS key and Secrets Manager secret that holds our AWS credentials.

KMS Key Policy

Here’s our KMS key policy (possibly with a few thinks I haven’t written about yet to be discussed in future posts). We’re attempting to give each ARN that can assume this role only the permissions that it needs.

Note: In an upcoming post I will explain why the role that I want to encrypt the data and store it in Secrets Manager oddly needs “decrypt” permissions. This seems like a bug to me but it’s the only way it works for now.

As you can see above we already have conditions to only allow using this key with Secrets Manager for encryption and decryption, which I wrote about here:

Let’s think about what adding these two new global condition keys will do for our policy.

aws:SourceArn

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html

The source ARN works with service-to-service requests. What does that mean exactly? The AWS documentation could be more clear on this point. We can get a a bit better explanation from the KMS documentation:

https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-services.html

The ARN and account values are included in the authorization context only when a request comes to AWS KMS from another AWS service.

Does this apply in our case? I would think that Secrets Manager would be making a request to KMS when we add the KMS Key Id to a Secret in Secrets Manager. Secrets Manager uses the key to encrypt or decrypt the value it stores. I explained how condition keys look in the logs and compare the value in the condition to a value in a request in my prior post explaining condition keys.

Again, I’m jumping ahead a bit but I’ve already tested encrypting a value and storing it in secrets manager. It’s all handled by CloudFormation. I checked my CloudTrail logs and could not find any entries for Secrets Manager accessing KMS. But in order to know what to put in the aws:SourceArn condition I would need to know what ARN to supply for secrets manager. I would presumably be able to find that in the logs.

I wish the documentation was a bit more explicit with sample requests showing exactly which key in the request each condition is using and when it applies (for example, it only applies if you write a policy to give a service access, but not when AWS uses access behind the scenes due to the way the whole cloud platform works.)

Perhaps AWS considers the fact that a user or role is making the request to secrets manager and therefore calling the encrypt or decrypt permission, rather than AWS Secrets Manager. In that case, I would expect to see an entry in CloudTrail logs for the role I’m using to run the CloudFormation template showing that it encrypted the value. Oddly enough, I don’t see that in the logs either. I see an “decrypt” entry. I’ll show you that in an upcoming post.

It has something to do with this, but I question the implementation and logging in this scenario because the way it is implemented, you cannot segregate duties between those who can encrypt and who can decrypt, but I digress.

Secrets Manager integrates with AWS Key Management Service (AWS KMS) to encrypt every version of every secret value with a unique data key that is protected by an AWS KMS key. This integration protects your secrets under encryption keys that never leave AWS KMS unencrypted. It also enables you to set custom permissions on the KMS key and audit the operations that generate, encrypt, and decrypt the data keys that protect your secrets.

The bottom line is that I don’t think we have any service to service calls using this key as far as I can tell so I don’t think this particular condition key applies. I will continue to research and test this as the documentation is not explicitly clear but that is my current conclusion. My understanding of the documentation is that, in order for the condition key to apply, there would need to be a corresponding entry in the logs. I don’t see one.

Note that this condition does not apply to principals, and our policy already locks down the actions to specific principals.

aws:SourceAccount

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html

The aws:SourceAccount condition also seems to primarily apply to service to service calls. We’ve already determined that this doesn’t apply to our policy.

In addition, we have locked down all actions to principals which contain the account in the ARN, so actions are already restricted to a specific account.

Let’s take a look at what I currently have in this policy. I’m referencing the output from another template. I’m also creating an ARN using a pseudo parameter and a known username.

Why do I have two entries here? First, I used an output. Then I realized I need to add the old administrator name for some reason after I renamed the administrator from KmsKeyAdministrator to KmsAdministrator. Which is better?

What could go wrong with the output value? Since it’s passed in from an output in a related template, anyone who can change that output could grant access to modify the key. They could add any ARN to the output and it would get added to this key policy the next time it is deployed. That may or may not be OK depending on how well you have secured your IAM CloudFormation templates.

What about the concatenation of the current account ID? Let’s say your administrator exists in a different account. That’s not going to work. Additionally the hard-coded value will fail if the administrator name changes. For my current purposes, I’m planning to put the KMS administrator and keys in a separate account. I like the idea of locking own the ARN in the second option better so I’m going to use that. Of course, after I make that change, I’m going to retest all my code because that could break things.

So now I have this:

Our encrypt and decrypt ARNs are still passed in, but they have limited permissions and once our batch job roles are deployed we should be able to lock them down and prevent changes. Perhaps we could have a multi-factor process to change them. We’ll keep thinking about that as we go along in this series.

As explained earlier, we’re using the AWS::AccountId pseudo parameter to retrieve the current account ID. If I wanted to make this code work in anybody’s account I could have used wildcards in the ARN:

aws:iam::*:role/KmsAdministrator

That would allow anyone to create a KMSAdministrator in their own account and access the key potentially so we definitely don’t want to do that either.

Lots to ponder in this post and we’re not done thinking about and tweaking this KMS key policy and the related IAM Policies. Stay tuned for more on creating zero trust policies on AWS.

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2022

About Teri Radichel:
~~~~~~~~~~~~~~~~~~~~
⭐️ Author: Cybersecurity Books
⭐️ Presentations: Presentations by Teri Radichel
⭐️ Recognition: SANS Award, AWS Security Hero, IANS Faculty
⭐️ Certifications: SANS ~ GSE 240
⭐️ Education: BA Business, Master of Software Engineering, Master of Infosec
⭐️ Company: Penetration Tests, Assessments, Phone Consulting ~ 2nd Sight Lab
Need Help With Cybersecurity, Cloud, or Application Security?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
🔒 Request a penetration test or security assessment
🔒 Schedule a consulting call
🔒 Cybersecurity Speaker for Presentation
Follow for more stories like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
❤️ Sign Up my Medium Email List
❤️ Twitter: @teriradichel
❤️ LinkedIn: https://www.linkedin.com/in/teriradichel
❤️ Mastodon: @teriradichel@infosec.exchange
❤️ Facebook: 2nd Sight Lab
❤️ YouTube: @2ndsightlab
Confused Deputy
Service To Service
Kms
Resource Policy
Cloudsecurity
Recommended from ReadMedium
avatarMunidimple Muchalli
AWS GuardDuty

AWS Guard Duty

4 min read