6 minutes
Pwned Labs - Plunder Public RDS Snapshots
Pnwed Labs - Plunder Public RDS Snapshots
Entry Point
AWS Account ID: 104506445608
Scenario
Huge Logistics, a global logistics leader, has enlisted your team’s expertise for an external security review of their cloud infrastructure. Starting with the provided AWS Account ID, your task is to uncover security flaws within their AWS environment and demonstrate the potential risks they pose. Every finding will bolster their defense against future threats.
Learning Outcomes
- Familiarity with the AWS RDS console
- Familiarity with the PostgreSQL cli
- An awareness of how this could be remediated and detected
Real World Context
Legions of databases are being inadvertently exposed on AWS due to the RDS (Relational Database Service) public snapshot feature. The Mitiga Research Team found that within a month, out of 2,783 RDS snapshots, 810 were consistently public, and 1,859 were public for one to two days. This public setting allows unauthorized access to potentially sensitive data, and threat actors can exploit this data for ransomware, extortion, or other malicious activities.
Attack
As we only have the account ID for the target AWS account, we will have to use our credentials for the enumeration and we have confirmed that these are working by running the command aws sts get-caller-identity
.
For enumeration of RDS Instance we have the option to search for snapshots from single RDS Database Instances or Clusters. We will first start with a Single RDS instance.
❯ aws rds describe-db-snapshots --snapshot-type public --include-public --region us-east-1 | grep 104506445608
We get no response, so we will modify the query to search for Cluster RDS Instances.
❯ aws rds describe-db-cluster-snapshots --snapshot-type public --include-public --region us-east-1 | grep 104506445608
"DBClusterSnapshotIdentifier": "arn:aws:rds:us-east-1:104506445608:cluster-snapshot:orders-private",
"DBClusterSnapshotArn": "arn:aws:rds:us-east-1:104506445608:cluster-snapshot:orders-private",
You can see that this reveals a RDS cluster snapshot name orders-private
. We will login to our AWS console and then navigate to RDS -> Snapshots -> Public and filter for “orders-private”
We click on the Snapshot name and we can see all the details about it, noting that the DB engine is aurora-postgresql
.
From the Actions drop-down, we will select
Restore Snapshot
We are then presented with a list of options which we will go through. For the DB Instances settings
, we will accept the defaults and under Settings
, enter any label for the Db Instance Identifier
Under Instance Configuration
, select Burstable classes (includes t classes) and then make sure that db.t3.medium is selected.
Under Connectivity
ensure that Public Access is set to No and choose the option to create a new Security Group which we will call snappy
We can leave the other settings as default and then click Restore DB Cluster
The restore process is underway and this would be a really good time to grab a coffee and stretch your legs as it will take some time.
Once the database cluster is restored and the status shows “Available”, we select pwnedlabs-cluster
and from the Actions
drop-down menu select Set up EC2 Connection
.
As we don’t have an EC2 already running, we will click Create EC2 Instance
We created our instance and then selected it from the drop-down menu and then select Continue
We review the setting and then select Set up
There is one small problem, we don’t know the Master Password for the Database! We can fix that by selecting the database clicking modify
We enter a new password and then select Continue
Confirm that the Apply immediately
radio button is selected and then click Modify DB Instance
and await for confirmation.
Now that we have reset the Master DB password, we need to get the endpoint details for the DB by clicking on the Database and making a note of the Endpoint details
We now connect to the EC2 client that we provisioned earlier and depending on the distribution that you chose you will need to install the the postgres client tools.
# RPM Distributions e.g. Amazon Linux
sudo yum install -y postgresql15.x86_64
# Debian based Distributions e.g. Ubuntu, Debian
sudo apt update && sudo apt install -y postgresql-client
Once we have installed the Postgresql Client, we can then connect to the the database.
[ec2-user@ip-172-31-2-135 ~]$ psql -h pwnedlabs.cfzdnjlbu5mp.us-east-1.rds.amazonaws.com -U postgres
Password for user postgres:
psql (15.7, server 14.11)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.
postgres=> \list
List of databases
Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges
-------------+----------+----------+-------------+-------------+------------+-----------------+-----------------------
cust_orders | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc |
rdsadmin | rdsadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | rdsadmin=CTc/rdsadmin+
| | | | | | | rdstopmgr=Tc/rdsadmin
template0 | rdsadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | =c/rdsadmin +
| | | | | | | rdsadmin=CTc/rdsadmin
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | =c/postgres +
| | | | | | | postgres=CTc/postgres
(5 rows)
postgres=> \c cust_orders
psql (15.7, server 14.11)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
You are now connected to database "cust_orders" as user "postgres".
cust_orders=> \dt
List of relations
Schema | Name | Type | Owner
--------+--------+-------+----------
public | flag | table | postgres
public | orders | table | postgres
(2 rows)
cust_orders=> select * from orders;
order_id | username | password | contract | credit
----------+------------------+--------------------+----------+------------------
5421 | cmckoy1 | sS9Ty#q9$eWt5 | 20 | 4024007170882670
5422 | icotesford2 | fU5v{\W@L | 4826 | 4929845244025480
5423 | ccrowley3 | uT0*4Weju2Y5y | 26 | 4916667994903810
5424 | aclapton4 | cP10#C7plSND? | 8142 | 4929058775447770
5425 | cgayther5 | mL8MqODFOb5 | 1272 | 4532144970022660
5426 | llekeux6 | "bJ0?>*""#.MWQyl\" | 147 | 4716938266108160
5430 | bsteckingse | lD0{MIoK | 566 | 4485183940482810
5431 | pbortonf | sJ2c_WT\JKd | 82 | 4485935491550410
5436 | cstacek | l850WJian | 2255 | 4716007731412910
5437 | mflawsl | 151iAEqKd | 28160 | 4539699812362260
5438 | jleindeckerm | 72zBpmsrS | 8266 | 4289820367687140
5439 | mfinann | PkRYmQnO4 | 77 | 4539087515570140
5440 | mbootep | FjyuISweP | 85617 | 4716750859124260
5441 | dbalogunq | IrOYK75ig | 673 | 4556528496965920
5442 | fgrishanovs | xIU7dPAbf | 35 | 4556546482969700
5443 | ubiasinit | YzvYaq0wl | 21 | 4716438044123840
5445 | leddowx | Mb0xSsw9e | 3362 | 4556913179072280
5446 | afoulisy | BaUR5EiGt | 3619 | 4929717439788210
We have successfully found PII information as well as the flag, but it is important to note that even though AWS provides ample warnings and even emails you about the dangers of having a public RDS snapshot, there are still a lot of them and if it is an option, no matter how bad, you can be sure that someone will choose it.