AWS Penetration Testing – DynamoDB and RDS

AWS comes with several database technologies which its customers are quickly able to spin up. Databases can contain critical information such as reused passwords, which makes them a prime target for any penetration tester.

Introduction to DyanmoDB

Amazon DynamoDB is a fully managed, serverless, NoSQL database. DynamoDB offers a fast persistent Key-Value Datastore with built-in support for replication, autoscaling and on-demand backup among other features.

Given the wealth of information which can be stored within databases knowing how to enumerate DynamoDB can be a valuable skill for any AWS penetration tester. As with other AWS services, users can interact with DynamoDB using the AWS command line tool. DyanmoDB tables can be described, listed and queried to retrieve the contents.

terminal$ aws --profile arctil dynamodb --list-tables

terminal$ aws --profile arctil dynamodb describe-tables --table-name users

terminal$ aws --profile arctil dynamodb scan --table-name users --max-items 30

In Example #1, the DynamoDB tables have been listed, this reveals a single table named users. The users table has then been described to show any information relating to it. Lastly, the users table contents have been retrieved, this has been limited to 30 results.

In addition to retrieving multiple results, the table can also be queried using the following syntax.

terminal$ aws --profile arctil dynamodb query --table-name users --key-condition-expression "username = :value" --expression-attribute-values '{ ":value": { "S":"administrator" } }' --region us-east-1

It may appear as though a lot is going on in the previous example. However, it’s quite straightforward. Like normal, a profile has been specified, this was followed by the DynamoDB service and query option. The query option requires that the table name is provided along with the –key-condition-expression option, this states what the query condition will be.

To create the conditional, the –expresion-attribute-values option would need to be specified. This option takes JSON data with the desired values. The given JSON states, where the value of string “username” is equal to “administrator” then returns any results.

For additional information on the query functionality, you can refer to Amazon’s official documentation.

Introduction to AWS RDS

Amazon Relational Database Service or RDS is a service offered by Amazon Web Services. This enables users to set up and operate relational databases within the cloud. RDS supports many common database types including MySQL, MSSQL, Postgresql and Oracle. Being familiar with RDS can help penetration testers uncover a plethora of valuable information.

For demonstration purposes, this content will focus on the security and enumeration of a MySQL database but you’re fully encouraged to create your own AWS account and do some independent learning.

During the creation of a MySQL database, users are given some configuration options. One of these options allows for the database to be given a public hostname and enable remote connections. These options can be seen down below.

Yes: RDS assigns a public IP address to the database. Amazon EC2 instances and other resources outside of the VPC (Virtual Private Cloud) can connect to your database. Resources inside the VPC can also connect to the database. Choose one or more VPC security groups that specify which resources can connect to the database.

No: RDS doesn't assign a public IP address to the database. Only Amazon EC2 instances and other resources inside the VPC can connect to your database. Choose one or more VPC security groups that specify which resources can connect to the database.

By default, RDS turns assign a public IP address off during the setup of a MySQL database.

To list any databases within the RDS service, the user account would need the rds:describe privilege, this is a part of the policies AmazonRDSReadOnlyAccess and AmazonRDSFullAccess.

terminal$ aws --profile arctil rds describe-db-instances
    "DBInstances": [
            "DBInstanceIdentifier": "jessies-bookstore",
            "Engine": "mysql",
            "MasterUsername": "admin",
            "Endpoint": {
                "Address": "",
                "Port": 3306,
            "VpcSecurityGroups": [
                    "VpcSecurityGroupId": "sg-09c816c8b68120aba",
                    "Status": "active"
            "AvailabilityZone": "us-east-1c",
            "DBSubnetGroup": {
                "DBSubnetGroupDescription": "Created from the RDS Management Console",
            "EngineVersion": "8.0.33",
            "OptionGroupMemberships": [
                    "OptionGroupName": "default:mysql-8-0",
                    "Status": "in-sync"
            "PubliclyAccessible": true,
            "StorageEncrypted": true,
            "KmsKeyId": "arn:aws:kms:us-east-1:272835655117:key/po78sh2-5fuj-7u18-Ae25-870de320e21d",
            "DBInstanceArn": "arn:aws:rds:us-east-1:272835655117:db:jessies-bookstore",
            "IAMDatabaseAuthenticationEnabled": false,
            "NetworkType": "IPV4",

When describing a database there will generally be a large amount of information returned, for readability not all of this information is visible in the example above.

From the example, there is a single database currently set up, this is called jessies-bookstore. The found database is powered by MySQL version 8.0.33, this was created using the RDS console and has a username of admin. Additionally, it can also be seen that the discovered database is publicly accessible and is assigned to the sg-09c816c8b68120aba security group.

AWS states that any database passwords must be at least 8 characters long. Unfortunately, there is no way to find the password once set. Due to this limitation, the password would need to be known or changed to explore any database contents.

terminal$ aws --profile arcan3 rds modify-db-instance --db-instance-identifier jessies-bookstore --master-user-password password12 --apply-immediately

The example above will change the database password preventing any connected systems from being able to access it. This approach should not be used against production environments without explicit notice and permission.

For any external access, AWS security groups would need to be configured to allow for external traffic to access the assigned cloud resources.

Creating and assigning security groups

As security groups were covered when learning about EC2 this won’t be expanded up on too much again. However, as a quick refresher, security groups act as a virtual firewall for cloud resources. Users can specify what incoming and outgoing connections can be made.

Since external access isn’t always configured, a discovered database may not be accessible. However, further enumeration of privileges and policies may confirm that the current user can create security groups and assign them.

Using the following four commands a new security group is created with the name of LetMeIn. This group is then configured to allow all incoming and outgoing connections to port 3306. Lastly, the group is assigned to the database using the security group ID.

terminal$ aws --profile jessies-bookstore ec2 create-security-group --description "Lets me have access" --group-name "LetMeIn"

terminal$ aws --profile jessies-bookstore ec2 authorize-security-group-ingress --group-id LetMeIn --protocol tcp --port 3306 --cidr

terminal$ aws --profile jessies-bookstore ec2 authorize-security-group-egress --group-id LetMeIn --protocol tcp --port 3306 --cidr

terminal$ aws --profile jessies-bookstore rds modify-db-instance --db-instance-identifier jessies-bookstore --vpc-security-group-ids sg-26sh8k24aa1c9916 --region us-east-1

Assuming the database password has been located, it’ll now be possible to connect to the database remotely. Once authenticated, it’ll be all about checking any tables and their contents for valuable information. MySQL client usage is out of scope of this series but more information can be found by heading to the links below.

Up Next “Lambda”

Spread the love