AWS RDS is a managed relational database service that allows users to rapidly set up fully operational instances on the cloud and use them as data sources within applications. The AWS RDS is one of the more popular services that AWS provides and has been a favourite amongst customers for having a wider range of Engine types to pick from.
Apart from the obvious benefits that AWS RDS has over conventional on premise databases, you don’t need to manage the underlying infrastructure. RDS can easily be set up to perform backups and can be configured to remain private or become available over the Internet.
AWS RDS Engine configurations are applied via a resource called Parameter group. These parameter groups are engine specific and contain settings that are pre-configured by AWS.
During a review of a MySQL RDS Engine, it was noticed that the security setting that forces RDS to only accept encrypted connections from clients was set to null while being unmodifiable. This blogpost takes a closer look at the setting and what you can do about it.
AWS RDS and Transport Layer Security
When you create a RDS instance in AWS, a parameter group is also created, if one hasn’t already been created for the specific Engine type.
Parameter groups in AWS RDS
Different Engine types have different settings that define how the database is set up, what character set the DB will use, where the log file will be, whether unsecured clients can connect or not, where the DB binary data is stored etc. Depending on the database engine type, some of these settings may not be available or may have a different variable name.
However, since AWS RDS is a managed service, some of these settings may not be modifiable, especially the ones that change filesystem access or location of resources on the underlying AWS managed machine.
Database level configuration parameters in AWS RDS
One of the more security focused configurations is the setting that enforces transport layer security, essentially the setting that prevents clients from connecting unless the connection uses transport layer security.
Based on the kind of database engine, this setting is implemented via different variable names. For example, require_secure_transport in the case of MySQL, MariaDB and Aurora MySQL. However, the default value for this setting for ALL engine types within AWS RDS is either set to null or 0 which essentially disables this setting. What’s even worse is that, for the more commonly used MySQL and MariaDB RDS engine types, this setting cannot be enabled to ensure only secure clients connect.
Here’s a complete summary of all RDS Engine types in AWS.
Table across all AWS RDS Engine Types showing Transport Layer Security settings
What does this mean to attackers?
From an attacker point of view, this means that RDS does not enforce transport layer security allowing any client that can either disable transport layer security or does not support it all will be able to establish a successful connection.
We tried this with the mysql client with the following command, disabling transport layer security, and were able to connect successfully
mysql -u user -h aws-rds-host -p —ssl-mode=DISABLED
mysql client connecting to RDS over an uncrypted transport layer with ssl-mode disabled
While the connection was being established, we ran a Wireshark trace to see what we could see over the network. Wireshark shows us the packets that the MySQL client sent including the credentials, all handshake, data and commands being exchanged between client and server - showing that the connection did indeed occur over an unencrypted channel.
Wireshark showing transport layer is unencryptedAn attacker on a local network or an intermediary server, like an ISP, would be able to perform Man in the middle attacks and capture data, modify content or simply patch the request and response to invoke other functions. This also brings the requirement of “encryption of data in motion” to a grey area since the RDS can no longer enforce connection security with the client and it is upto the client to connect securely.
What does AWS say about this?
We reached out to AWS on 26th December 2021 over email and explained the issue. AWS acknowledged that they are aware of this and this setting is disabled by default per their design since there are various RDS configurations for customers including those that allow creation of database instances inside customers’ VPCs so that they are not publicly accessible.
The AWS Security team added that at present, enabling encryption may cause customers to adjust the configuration of their existing applications; thus, setting ‘require_secure_transport=ON’ as a service default may adversely impact some customers. Also, allowing customers to modify the ‘require_secure_transport’ parameter is on RDS’s roadmap but AWS could not say when this would be available for the general public.
How do you mitigate this and stay safe?
For most engine types, it is possible to enable this setting using the Parameter Groups resource type and by editing the values. For example, the following image shows the setting for rds.force_ssl being updated for the sqlserver-se-15 DB type.
Changing the RDS transport layer security parameter
As there is no way to currently modify the require_secure_transport option for the MySQL and MariaDB engine types, it is recommended that all clients connecting to these database instances must use secure connections. This is the default in all clients, however, this can easily be changed via command line or in code.
It is also a good security practice to keep the RDS inside a VPC away from the public Internet and to practice basic security hygiene like having strong passwords, keeping snapshots private and enabling encryption at rest for snapshots and the database itself.
We have published a Kloudle Academy article as well that talks about mitigations in more depth here - https://kloudle.com/academy/fixing-the-default-insecure-network-connection-option-for-rds-instances
When an AWS RDS instance is created, an appropriate parameter group is applied to the DB instance. These parameter groups contain settings for the database at the engine layer. During our research we discovered that the setting that enforces transport layer security is disabled on all database engine types with the ability to modify it also being absent for certain types of databases.
As AWS RDS cannot enforce clients to connect using a secure connection, it is possible for insecure clients to make a connection which could be attacked and data could be stolen or modified in transit. Although AWS RDS allows for the setting to be enabled on some engine types, in the case of MySQL and MariaDB there is no way to change the option at all. This makes enforcing client side security an even more important security measure.