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 4 of 35
In Progress

[LAB] Getting Started with the AWS CLI

Christophe February 6, 2024
🧪Hands-On Lab

How to install the CLI

First things first, if you don’t already have the AWS CLI installed on your machine, you will need that. The steps to do so are straightforward so I recommend that you follow directions on this page depending on your OS:

If you’re not sure whether you have it installed already or not, you can type in:

aws --version

and you should see a result instead of an error. It will look something kind of like this:

aws-cli/2.13.21 ...redacted...

If yours doesn’t start with aws-cli/2... like mine, and instead has a 1, then it means you are using version 1. Not a huge deal, but it is recommended that you upgrade to the newer v2 and you can view migration steps on the same link as above.

How to configure the CLI with access keys

Once you have the CLI installed, you’re ready to configure it.

Let’s start by typing in:

aws configure

One nifty trick with the AWS CLI is that you can configure profiles in order to have multiple credentials saved at one time. If you leave off the --profile, then it will save as [default] profile. Otherwise, you can name the profile whatever you want, like this:

aws configure --profile cybrisfun

Whether you use this or not is totally up to you, but if you don’t have any other credentials already stored, then you don’t have to use a profile name.

Keep in mind that if you use --profile <value> then you will need to add that to every CLI call going forward whenever you want to use those credentials.

Press enter and you’ll be asked to fill in information:

AWS Access Key ID [****************W6MG]: AKIA...
AWS Secret Access Key [****************4Bun]: guI6...
Default region name [us-east-1]: us-east-1
Default output format [json]: json
Code language: CSS (css)

Finding profiles on your local machine

When we configure the AWS CLI, it stores your information in a config file and a credentials file. Let’s take a look.

Using your favorite editor (I’m using vim here but you don’t have to), you can open the file at this path:

vim ~/.aws/configCode language: JavaScript (javascript)

And you should see your profile, kind of like this:

region = us-east-1
output = jsonCode language: JavaScript (javascript)

This is how the CLI keeps track of your various profiles.

(If you’re using vim like I am and you’re not familiar, you can press :q to exit. If you accidentally made changes you don’t want to save and it won’t let you exit, you can type :q!)

Then, you can do the same thing but with this file:

vim ~/.aws/credentials
Code language: JavaScript (javascript)

I won’t show you mine, but it should look something like this:

aws_access_key_id = AKIA5...
aws_secret_access_key = guI6...
Code language: JavaScript (javascript)

You’re now ready to issue CLI commands!

Issuing CLI commands

I’ll talk more about how to issue commands at the end, but for now go ahead and type in this command:

❯ aws sts get-caller-identity

    "UserId": "AIDAT6ZKEI3ES3ICKMUQ7",
    "Account": "272281913033",
    "Arn": "arn:aws:iam::272281913033:user/cli-getting-started-Dana"
Code language: JavaScript (javascript)

If you used a profile when configuring your credentials, don’t forget to add it each time you issue commands or else you’ll get access denied (or use the wrong credentials if you had others already set):

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

This is essentially the “whoami” in AWS because it returns basic information about who you are based on the credentials used. Congrats! You’ve just issued your first CLI command successfully.

As you can see, we are authenticated as a user. When working in AWS, you will frequently use roles, and roles work a little bit differently, so let’s take a look at that now.

Next, run this command to list out our role ARN: (role name is case sensitive!)

❯ aws iam list-roles --query "Roles[?RoleName=='AWSCLIRole']"

        "Path": "/",
        "RoleName": "AWSCLIRole",
        "RoleId": "AROAT6ZKEI3EVEDDD3RBR",
        "Arn": "arn:aws:iam::272281913033:role/AWSCLIRole",
        "CreateDate": "2024-02-06T02:42:12+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                    "Effect": "Allow",
                    "Principal": {
                        "AWS": "arn:aws:iam::272281913033:root"
                    "Action": "sts:AssumeRole",
                    "Condition": {
                        "ArnEquals": {
                            "aws:PrincipalArn": "arn:aws:iam::272281913033:user/cli-getting-started-Dana"
        "Description": "Assumable role for Lab",
        "MaxSessionDuration": 3600
Code language: PHP (php)

This role has been pre-created by the lab for us, and our user has access to assume it. Copy/paste the Arn somewhere that you can reference because we’re going to need it.

This return includes information about the AssumeRolePolicyDocument which is what tells AWS who the role trusts to assume it, and we can see that we have a special condition to allow our user Dana. I won’t go into more detail right now since it can get fairly complicated, but that’s the gist of it. Let me know if you have questions in the comments below!

How to use roles with the AWS CLI

Roles are different from users because they don’t use long-term access keys. They use short term credentials.

There are a few ways you can do this, but I’m only going to show one in this because it’s a more convenient approach.

Now that we know the role ARN, go back to your config file. We’re going to edit this file, so I recommend using whatever text editor you’re comfortable with, not necessarily vim. It could even be Notepad if you want:

vim ~/.aws/config
Code language: JavaScript (javascript)

From there, you’ll see your existing profiles. Below those, we need to add a new profile like this:

[profile AWSCLIRole]
role_arn = arn:aws:iam::1122334455:role/AWSCLIRole
source_profile = default
Code language: JavaScript (javascript)

Note: Your role ARN will be different from mine and you must use yours that you got from the prior command. Don’t simply copy mine that you see here.

Note: If you used a --profile at the very beginning, you need to set that as the source_profile value instead of default.

Now, we can issue commands through the role, and the AWS CLI will automatically handle authentication to assume the role for that call by using the profile name:

❯ aws sts get-caller-identity --profile AWSCLIRole

    "UserId": "AROAT6ZKEI3EVEDDD3RBR:botocore-session-1707190457",
    "Account": "272281913033",
    "Arn": "arn:aws:sts::272281913033:assumed-role/AWSCLIRole/botocore-session-1707190457"
Code language: JavaScript (javascript)

You can see from this result that we are issuing commands as a role (:assumed-role/AWSCLIRole) and not as a user unlike earlier (which looked like this: ":user/cli-getting-started-Dana"), which means this worked! We can now use this AWS CLI profile in order to temporarily assume that role’s permissions instead of our user’s permissions.

This role has access to a file in Amazon S3 that we can only access by assuming it, and we can demonstrate that with:

❯ aws s3api list-buckets --profile AWSCLIRole     
    "Buckets": [
            "Name": "cybr-data-bucket-272281913033",
            "CreationDate": "2024-02-06T02:41:28+00:00"
Code language: PHP (php)

Versus if we try do to that with the --profile as our user:

❯ aws s3api list-buckets                     

An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
Code language: PHP (php)

We get an access denied, demonstrating that we are successfully switching between the IAM User and IAM Role from our CLI.

How to navigate the AWS CLI documentation

Before we wrap up this lab, I want to explain how we can leverage the AWS CLI documentation so that you can take your new skills and have fun exploring AWS in your own environments.

You will want to reference the v2 documentation which you can access here:

From there, you have a list of AWS services. Let’s search for sts, which stands for Security Token Service.

On that page, we will see the get-caller-identity call that we’ve been issuing throughout this lab. Click on that will take you to its manual page that explains in greater detail what this call does, how to issue it, and how it overall works.

You’ll notice a Synopsis section that looks like this:

[--cli-input-json | --cli-input-yaml]
[--generate-cli-skeleton <value>]
Code language: CSS (css)

Those are all of the options we can submit with the get-caller-identity call, and whenever the options are wrapped in brackets like this [--cli-input-json], it means that they are optional. Instead, if they’re not wrapped in brackets, that means they’re required options you must provide to successfully issue the command. There are none for this particular call, but keep that in mind.


Roles are super important in AWS as we’ll explain and show in a separate course dedicated to IAM Roles, but they will also be important in this course for a couple of the flags that you have to capture, so I wanted to make sure that we introduced them here first.

That’s it! Congratulations on getting started with the AWS CLI. You can now use your new skills and apply them in this course to learn more about IAM PrivEsc.


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.