Severalnines Blog
The automation and management blog for open source databases

How to Secure MySQL/MariaDB Servers

Ashraf Sharif

After attacks on MongoDB databases, we have recently also seen that MySQL servers are being targeted by ransomware. This should not come as a surprise, given the increasing adoption of public and private clouds. Running a poorly configured database in the cloud can become a major liability.

In this blog post, we’ll share with you a number of tips on how to protect and secure your MySQL or MariaDB servers.

Understanding the Attack Vector

Quoting SCMagazine:
The attack starts with brute-forcing the root password for the MySQL database. Once logged in, the MySQL databases and tables are fetched. The attacker then creates a new table called ‘WARNING' that includes a contact email address, a bitcoin address and a payment demand.

Based on the article, the attack vector starts by guessing the MySQL root password via brute-force method. Brute-force attack consists of an attacker trying many passwords or passphrases with the hope of eventually guessing correctly. This means short passwords can usually be discovered quite quickly, but longer passwords may take days or months.

Brute-force is a common attack that would happen to any service. Unfortunately for MySQL (and many other DBMS), there is no out-of-the-box feature that detects and blocks brute-force attacks from specific addresses during user authentication. MySQL does capture authentication failures in the error log though.

Review your Password Policy

Reviewing the MySQL password policy is always the first step to protect your server. MySQL root password should be strong enough with combination of alphabets, numbers and symbols (which makes it harder to remember) and stored in a safe place. Change the password regularly, at least every calendar quarter. Based on the attack vector, this is the weakest point that hackers target. If you value your data, don’t overlook this part.

MySQL deployments performed by ClusterControl will always follow the vendor’s security best practices, for example there will be no wildcard host defined during GRANT and sensitive login credentials stored in the configuration file is permissible only to OS’s root user. We strongly recommend our users to specify a strong password during the deployment stage.

ClusterControl
Single Console for Your Entire Database Infrastructure
Find out what else is new in ClusterControl

Isolate the MySQL Server

In a standard production environment, database servers are usually located in a lower level tier. This layer should be protected and only accessible from the upper tier, such as application or load balancer. If the database is co-located with the application, you can even lockdown against non-local addresses and use MySQL socket file instead (less overhead and more secure).

Configuring the "bind-address" parameter is vital here. Take note that MySQL binding is limited to either none, one or all IP addresses (0.0.0.0) on the server. If you have no choice and need MySQL to listen to all network interfaces, restrict the access to the MySQL service from known good sources. Use a firewall application or security group to whitelist access only from hosts that need to access the database directly.

Sometimes, the MySQL server has to be exposed to a public network for integration purposes (e.g, monitoring, auditing, backup etc). That’s fine as long as you draw a border around it. Don’t let unwanted sources to “see” the MySQL server. You can bet how many people in the world know 3306 is the default port for MySQL service, and by simply performing a port scan against a network address, an attacker can create a list of exposed MySQL servers in the subnet in less than a minute. Advisedly, use a custom MySQL port by configuring the "port" parameter in the MySQL configuration file to minimize the exposure risk.

Review the User Policy

Limit certain users to hold the critical administration rights, especially GRANT, SUPER and PROCESS. You can also enable super_read_only if the server is a slave, only available on MySQL 5.7.8 and Percona Server 5.6.21 and later (sadly not with MariaDB). When enabled, the server will not allow any updates, beside updating the replication repositories if slave status logs are tables, even for the users that have SUPER privilege. Remove the default test database and any users with empty passwords to narrow the scope of penetration. This is one of the security checks performed by ClusterControl, implemented as a database advisor.

It’s also a good idea to restrict the number of connections permitted to a single account. You can do so by setting the max_user_connections variable in mysqld (default is 0, equal to unlimited) or use the resource control options in GRANT/CREATE USER/ALTER USER statements. The GRANT statement supports limiting the number of simultaneous connections to the server by an account, for example:

mysql> GRANT ALL PRIVILEGES ON db.* TO 'db_user'@'localhost' WITH MAX_USER_CONNECTIONS 2;
Create MySQL account with MAX_USER_CONNECTIONS resource control option using ClusterControl
Create MySQL account with MAX_USER_CONNECTIONS resource control option using ClusterControl

The default administrator username on the MySQL server is “root”. Hackers often attempt to gain access to its permissions. To make this task much harder, rename “root” to something else. MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8). It is possible to use a longer username for the super admin user by using the RENAME statement as shown below:

mysql> RENAME USER root TO new_super_administrator_username;

A side note for ClusterControl users, ClusterControl needs to know the MySQL root user and password to automate and manage the database server for you. By default, it will look for ‘root’. If you rename the root user to something else, specify “monitored_mysql_root_user={new_user}” inside cmon_X.cnf (where X is the cluster ID) and restart CMON service to apply the change.

Backup Policy

Even though the hackers stated that you would get your data back once the ransom is paid, this was usually not the case. Increasing the backup frequency would increase the possibility to restore your deleted data. For example, instead of a full backup once a week with daily incremental backup, you can schedule a full backup once a day with hourly incremental backup. You can do this easily with ClusterControl’s backup management feature, and restore your data if something goes wrong.

If you have binary logs (binlogs) enabled, that’s even better. You can create a full backup every day and backup the binary logs. Binlogs are important for point-in-time recovery and should be backed up regularly as part of your backup procedure. DBAs tend to miss this simple method, which is worth every cent. In case if you got hacked, you can always recover to the last point before it happened, provided the hackers did not purge the binary logs. Take note that binary logs purging is only possible when the attacker has SUPER privilege.

One more important thing is that the backup files must be restorable. Verify the backups every now and then, and avoid bad surprises when you need to restore.

Safeguard your Web/Application Server

Well, if you have isolated your MySQL servers, there are still chances for the attackers to access them via web or application server. By injecting a malicious script (e.g, Cross-Site Scripting, SQL injection) against the target website, one can get into the application directory, and have the ability to read the application files. These might contain sensitive information, for instance, the database login credentials. By looking at this, an attacker can simply log into the database, delete all tables and leave a “ransom” table inside. It doesn’t necessarily have to be a MySQL root user to ransom a victim.

There are thousands of ways to compromise a web server and you can’t really close the inbound port 80 or 443 for this purpose. Another layer of protection is required to safeguard your web server from HTTP-based injections. You can use Web Application Firewall (WAF) like Apache ModSecurity, NAXSI (WAF for nginx), WebKnight (WAF for IIS) or simply running your web servers in a secure Content Delivery Network (CDN) like CloudFlare, Akamai or Amazon CloudFront.

Always Keep Up-to-date

You have probably heard about the critical zero-day MySQL exploit, where a non-privileged user can escalate itself to super user? It sounds scary. Luckily, all known vendors has updated their repository to include a bug fix for this issue.

For production use, it’s highly recommended for you to install the MySQL/MariaDB packages from the vendor’s repository. Don’t rely on the default operating system repository, where the packages are usually outdated. If you are running in a cluster environment like Galera Cluster, or even MySQL Replication, you always have the choice to patch the system with minimal downtime. Make this into a routine and try to automate the upgrade procedure as much as possible.

ClusterControl supports minor version rolling upgrade (one node at a time) for MySQL/MariaDB with a single click. Major versions upgrade (e.g, from MySQL 5.6 to MySQL 5.7) commonly requires uninstallation of the existing packages and it is a risky task to automate. Careful planning and testing is necessary for such kind of upgrade.

Conclusion

Ransomware is an easy-money gold pot. We will probably see more security breaches in the future, and it is better to take action before something happens. Hackers are targeting many vulnerable servers out there, and very likely this attack will spread to other database technologies as well. Protecting your data is a constant challenge for database administrators. The real enemy is not the offender, but our attitude towards protecting our critical assets.