Pillage Exposed RDS Instances

A walkthrough demonstrating how to exfiltrate data from a public RDS instance.

CTF Source: Pwned Labs

Overview

In this walkthrough, we're provided with a public RDS endpoint and asked to do a security assessment.

Pre-Requisites

  • Install awscli: (brew/apt) install awscli

  • Install nmap: (brew/apt) install nmap

  • Install seclists: (brew/apt) install seclists

  • Install mysql cli: apt install mariadb-client-core

Walkthrough

Discovering RDS

Given an RDS endpoint, we’re going to perform a port scan to identify potential database instances running.

nmap -Pn -p3306,5432,1433,1521 exposed.cw9ow1llpfvz.eu-north-1.rds.amazonaws.com

Nmap scan report for exposed.cw9ow1llpfvz.eu-north-1.rds.amazonaws.com (16.171.94.68)
Host is up (0.16s latency).
rDNS record for 16.171.94.68: ec2-16-171-94-68.eu-north-1.compute.amazonaws.com

PORT     STATE    SERVICE
1433/tcp filtered ms-sql-s
1521/tcp filtered oracle
3306/tcp open     mysql
5432/tcp filtered postgresql

Nmap done: 1 IP address (1 host up) scanned in 2.78 seconds

Now that we know of an open port let’s run some more tests with nmap.

nmap -Pn -sV -p3306 --script=mysql-info exposed.cw9ow1llpfvz.eu-north-1.rds.amazonaws.com

Brute-Forcing MySQL

Now that we know the version of MySQL is ⁠8.0.32⁠, we can view the documentation and discover that unless the configuration was updated, the default username is: ⁠root⁠ and it may not have a password. Let’s try to connect.

  • ⁠-h⁠ connect to a remote host, without this it will attempt to connect to a local mysql db

  • ⁠-u⁠ specify the username

  • ⁠--skip-password⁠ attempt authentication without a password

Bonus, there’s also an nmap script that will do the same as above --script=mysql-empty-password⁠ and also check for ⁠anonymous user.

No dice. Not to worry, we can attempt to brute-force the password.

Let’s first ensure we have a good password list e.g., ⁠mysql-betterdefaultpasslist.txt

  • If you have Seclists installed, we can find this here ⁠ls -lh /usr/share/seclists/Passwords/Default-Credentials/ | grep mysql

We’re going to use the nmap script mysql-brute. Looking over the documentation we know our creds file needs to be formatted a certain way,

a file containing username and password pairs delimited by '/'

Our file is currently delimited by ⁠: so let’s fix that.

We’ll copy this creds file to our local directory so we don’t butcher the original.

cp /usr/share/seclists/Passwords/Default-Credentials/mysql-betterdefaultpasslist.txt .

Then we’ll use ⁠sed⁠ to change the ⁠:⁠ to a ⁠/

Now we can confirm the changes.

We’re ready to run our brute-force attack!⁠

  • brute.delay=10 this increases the timeout, the default is set to 0 which may cause the script to fail to find any results

It looks like we found valid creds! ⁠dbuser:123⁠. Let’s attempt to connect to MySQL with these.

Nice. We’re in! Let’s see what data there is.

Exfiltrating Data

Show the databases

Select the database ⁠user_info⁠ and view its tables

Read the flag

Read plaintext users data

Wrap-Up

In this scenario, we were tasked with identifying security concerns on an AWS RDS instance and we discovered a few issues:

  1. Database public exposure

    • The instance was publicly exposed and there are few use cases where this is needed

    • Recommendation:

      • Turn off public access if possible

      • If public access is required, consider restricting access via Security Groups to only approved IP addresses

      • Consider utilizing AWS IAM for database authentication or integrating with AWS Secrets Manager for password authentication

  2. Database authentication

  3. Data security

    • The ⁠user_info⁠ data in the MySQL database was not encrypted

    • Recommendation:

Last updated

Was this helpful?