avatarTeri Radichel

Summarize

BoolIfExists for MFA — Just Say No

ACM.368 A better policy to require MFA for ALL actions

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

⚙️ Part of my series on Automating Cybersecurity Metrics. The Code.

🔒 Related Stories: AWS Security | DevOps | IAM | Governance

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

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

In the last post, I explained how I’m going to group scripts by different types of administrative users. The scripts will essentially be grouped by who is allowed to run them.

In this post I want to revisit my admin role and user templates, and user templates in general. The first user I created when I created my new AWS account was granted the AdministratorAccess policy.

Update: It looks like AWS has updated and clarified the documentation relate to this issue. Yay! It’s a lot better now on the primary page. However, the page with the IAM global context keys is still a bit misleading and not 100% clear in terms of how things work when the MFA key is not present.

Requiring MFA for any actions taken by a user

After working through these various multi-account deployment efforts I realized that I wanted to create a default admin account in each new account, starting with the rootadmin account.

I want some consistency in how these administrators are deployed so of course I’m going to use common templates for this purpose.

One of things I want to do is create a policy that only allows the administrator to perform actions with MFA, other than adding their MFA device to their own account.

Here’s the policy — but note my recommended changes below. I’m just adding this policy here in case AWS changes the original policy I’m writing about.

One problem with that policy — BoolIfExists

I have an issue with the code in that post — the BoolIfExists in the policy.

I’ve written about this before, but the documentation that explains why that exists seems to be misleading. From what I gleaned and tested (which doesn’t seem how it is described in the documentation), if you do not add BoolIfExists then you cannot use developer credentials without assuming a role, because you cannot use developer credentials directly with MFA. So in order to allow people to use developer credentials without MFA, you add BoolIfExists.

Just say no.

Developers can still use an AWS Access Key and Secret Key ID and the AWS CLI if you change IfBoolExists to Bool. The only thing is, they will have to assume a role first using MFA to perform actions instead of using their credentials directly.

And that should be what you want if you are trying to enforce MFA on actions, no?

You can restrict with MFA is the ability to assume a role if MFA is not present using the AWS CLI without usign BoolIfExists.

That is not clearly explained in the AWS documentation and all the examples I’ve seen include BoolIfExists.

You can configure your AWS CLI profile with a role and an MFA device and when you want to take actions using that role, you will be prompted for an MFA token.

Alternatively, you can pass in a token when assuming a role as I demonstrated in this post that passes an MFA to an EC2 instance that gets credentials from Secrets Manager and uses them in conjunction with the token to assume a role and run a job. If that works consistently I will be using that for deployments going forward.

How BoolIfExists allows risky requests

When you add BoolIfExists, you allow any requests that are made to AWS APIs that do not include the field MultiFactorAuthPresent.

Here’s what I can think of that might get through if you include BoolIfExists in your policy:

  • An AWS developer forgets to include the MulitFactorAuth present in a particular request by accident while developing an AWS service.
  • Any request with AWS developer credentials, if I understand why this is being added.
  • The way the above example is written, someone could pass in anything besides false to perform actions that are otherwise denied.

I don’t really want those gaps in my security, so what I am going to do is enforce MFA for every action and have users assume roles with the CLI in order to perform any actions in my accounts.

The sample policy in the above documentation denies actions if the value of MultiFactorAuthPresent equals false.

What if the value of MultiFactorAuthPresent equals ‘MorkFromOrk’?

This is too overly complicated with double negatives. It’s easy to get confused but if I passed in MorkFromOrk for the value of MultiFactorAuthPresent in a request the above logic would say:

MultiFactorAuthPresent exists and the value is not false, so don’t deny whatever action the principal is trying to perform. Whether or not the user can perform whatever action they are trying to perform depends on what else is in the policy. In my case, I want a policy that allows any action if MFA is present.

The policy should be checking for true, not allowing anything that is not false.

Here’s some new and improved logic, kind of. I’m going to further restrict actions in the next post. Also note this is an ADMIN account. Most people should not be logging in as admins with full access, so for the majority of users this is still a highly risky policy. (As I mentioned before, there’s an asteRISK in the policy which should be carefully considered.)

This statement allows any action if MFA is present and set to true:

{
   "Sid": "AllowAnyActionWithMFA",
   "Effect": "Allow",
   "Action": [
    "*"
   ],
   "Resource": "*",
   "Condition": {
    "Bool": {
     "aws:MultiFactorAuthPresent": "true"
    }
   }
  }

This statement allows only certain actions whether MFA is present or not:

 {
   "Sid": "AllowWithOrWithoutMFA",
   "Effect": "Allow",
   "Action": [
    "iam:CreateVirtualMFADevice",
    "iam:EnableMFADevice",
    "iam:GetUser",
    "iam:ListMFADevices",
    "iam:ListVirtualMFADevices",
    "iam:ResyncMFADevice",
    "sts:GetSessionToken"
   ],
   "Resource": "*"
  },

The other thing I don’t understand why is included in the policy below without MFA is GetSessionToken.

Here’s the explanation on the page:

To use the AWS CLI and AWS API, IAM users must first retrieve their MFA token using the AWS STS GetSessionToken operation and then use that token to authenticate the desired operation.

What? No. The user can assume a role with MFA as already demonstrated. That GetSessionToken action is actually incredibly risky?! What we need to add is a section to allow a user to assume a role but require MFA. I’m going to allow the account admin of any account I create to assume a role with MFA that has the same name as its user account name. The account admin name is going to be [account name]admin.

Here is the new and improved policy (but not done yet):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowViewAccountInfo",
            "Effect": "Allow",
            "Action": "iam:ListVirtualMFADevices",
            "Resource": "*"
        },
        {
            "Sid": "AllowManageOwnVirtualMFADevice",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::*:mfa/*"
        },
        {
            "Sid": "AllowManageOwnUserMFA",
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice",
                "iam:EnableMFADevice",
                "iam:GetUser",
                "iam:GetMFADevice",
                "iam:ListMFADevices",
                "iam:ResyncMFADevice"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowAnyActionWithMFA",
            "Effect": "Allow",
            "Action": [
                "*"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "true"
                }
            }
        }
    ]
}

I see another problem in the above policy. A user can create an MFA device for any user. Additionally, according to the above documentation, a user should never be allowed to delete their own MFA device. I’ll cover that in the next post where I discover even more issues with this policy.

Update: in my next post…I figure out that the aws:username doesn’t seem to be working at all. Stay tuned. Seems like some automated testing would help. I further updated these policies in later posts.

Let’s manually test this out to make sure it works as intended.

I create a user named TestAdmin and assign the above policy which I named TestAdmin and I created a role named TestAdmin with the following trust policy:

{
 "Version": "2012-10-17",
 "Statement": [
  {
   "Sid": "Statement1",
   "Effect": "Allow",
   "Principal": {
    "AWS": "arn:aws:iam::xxxxxxxxxxxx:user/TestAdmin"
   },
   "Action": "sts:AssumeRole",
   "Condition": {
    "Bool": {
     "aws:MultiFactorAuthPresent": [
      "true"
     ]
    }
   }
  }
 ]
}

I test logging in as my new user.

I randomly select S3 and click on Buckets. Access denied. Good.

Head over to IAM. Here’s what I see:

Click Add MFA. I want to add a hardware MFA device (a Yubikey):

Now although the permission I gave myself is for a virtual MFA device, apparently that also covers hardware MFA devices because that worked.

I log out and back in so the MFAAuthenticated value is set.

I choose switch roles in the console.

Using this policy, I am able to switch roles in the console with MFA required:

What about using the CLI? Can I assume a role with MFA?

Create a secret key and access key for the user.

Configure a profile with the credentials:

Try to perform an action like listing S3 buckets. Denied. No MFA.

Add a virtual MFA device for the user.

Configure the device. Get the ARN for the commands below.

Configure a role with MFA using the following commands. [Replace values in brackets.]

aws configure set role_arn [arn] --profile TestAdminRole
aws configure set source_profile TestAdmin --profile TestAdminRole
aws configure set mfa_serial [mfa ARN] --profile TestAdminRole
aws configure set region = [region] --profile TestAdminRole
aws configure set output = json --profile TestAdminRole

You can now run the S3 command with the TestAdminRole profile.

As you can see I can now run the S3 command with MFA required.

There is no need for the BoolIfExists command that I have found so far and I would say that the above policy in the documentation is severely flawed and risky. I have submitted feedback to AWS on this point multiple times and written other blog posts about it. I would recommend that you evaluate any code on any cloud provider’s website carefully because I have found errors in documentation like this on the GCP and Azure websites in the past as well, and in third-party cloud security product documentation.

Update: If you read this post, don’t stop here. I found additional issues in subsequent posts while testing. Hopefully these issues will be fixed so you can restrict creation of virtual MFA devices to specific users.

This policy in this post doesn’t work as I discovered by actually testing it.

Test your policies. Don’t just copy them off the AWS website.

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2023

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
AWS
Boolifexists
MFA
Iam
Security
Recommended from ReadMedium