MySQL After a Data Breach
Tags: mysql, database, security, tutorial
Published: 2022-11-12 09:00:00

<!-- wp:paragraph -->
<p>As we all know, data breaches occur all too often. After a data breach occurs, we are used to seeing security experts, company associates and other people advising us to change our passwords and safeguard our data by securing our infrastructure.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This is what the majority of developers do - we secure our infrastructure, maybe hire some information security consultants for advice on how to prevent data breaches in the future and forget about the data breach as time passes.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>But have we ever thought how would we secure MySQL in case such an event occurs? This is what we will try to do in this post.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>MySQL Security 101</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>As far as security in MySQL is concerned, we have a wide range of options to look at:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li><strong>The security of our MySQL installation</strong> - did we think about securing our MySQL nodes when we first installed MySQL on our server? If not, why?</li><li><strong>MySQL access control</strong> - how many users were entrusted with certain privileges? How many users had access to running administrative statements in the database? When was access granted? Was access revoked at some point in time?</li><li><strong>The usage of security plugins</strong> - did our MySQL installation use any security plugins available? What were they? Were they updated?</li><li><strong>General database security</strong> - did we enforce general database security practices? Did our users have the choice to use strong and secure passwords? Did we make an effort to secure our application against SQL injection? What storage engine did our database use? Why?</li><li><strong>Backups</strong> - did we have backups? Were they up to date? Did we test them?</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>These are the basic questions we need to answer if we want to understand how to secure MySQL - we will now look further into them.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>The Security of a MySQL Installation</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>If our information systems are suspected to have suffered a data breach, it's a good idea to re-install MySQL on our servers - it's also a good idea to start from securing the MySQL installation itself meaning that when we have re-installed MySQL on our server we should look at the following things:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Assign a password to the <code>root</code> MySQL user - this should seem obvious, but sometimes we forget the simplest things. Make sure that the password consists of uppercase, lowercase letters, numbers and special symbols.</li><li>Consider changing the location of the top-level directory of your MySQL installation - to do this, you can copy the existing database directory to a new location:<br><code>sudo rsync -a /var/lib/mysql /mount/volume-01</code>, then include the following lines in your <code>/var/lib/mysql/my.cnf</code> file:<br><code>socket=/mount/volume_01/mysql/mysql.sock</code><br><code>datadir=/mount/volume_01/mysql</code>. Change the directory according to your needs.</li><li>The <code>secure_file_priv</code> system variable sets the directory from which import and export operations are allowed to execute - if the operations will not originate from this directory, the file(s) will not be imported into the server.<br>In order to set the variable to your desired directory, navigate to the <code>/var/lib/mysql/my.cnf</code> file and change the value of the <code>secure_file_priv</code> variable to a different directory.</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>The basic MySQL security steps depicted above should help you to secure your MySQL installation, but that's only one part of MySQL's security. Now we will the other side of it - MySQL access control.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>MySQL Access Control</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In order to ensure proper MySQL access control, restrict the usage of certain statements only to certain users - weigh your options and only allow users access to statements that are necessary for them to perform their duties.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>For example, if a user should only read from the database, he should be only allowed the usage of <code>SELECT</code> statements - the choice of using multiple statements like <code>ALTER</code>, <code>UPDATE</code> and others might not be necessary.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Also consider revoking user access to certain statements - if you see that a certain user no longer needs to, for example, add indexes to the table, consider revoking his access to <code>ALTER</code> statements, etc.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>MySQL Security Plugins</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>MySQL includes several plugins that are able to strengthen its security capabilities. We will not be discussing all of them in this chapter, but some of them are:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><strong>Authentication plugins</strong> - MySQL has more than one such plugin - one of them is the SHA-256 pluggable authentication plugin which is built-in to the server and can be used by creating a user and specifying that it authenticates using the <code>sha256_password</code> plugin:<br><code>CREATE USER 'demo_user'@'localhost' IDENTIFIED WITH sha256_password;</code><br>Next, set the <code>old_passwords</code> variable to 2 (this will cause the <code>PASSWORD()</code> function to use the SHA-256 hashing algorithm):<br><code>SET old_passwords = 2;</code><br><code>SET PASSWORD FOR 'demo_user'@localhost = PASSWORD('demo_password');</code></li><li><strong>The password validation plugin</strong> - the <code>validate_password</code> plugin aims to improve security by enabling password strength testing.<br>In order to use the plugin, install <code>validate_password</code>, and, if needed, modify the value of <code>validate_password_policy</code> (the variable can be set to numeric or string values - <code>0</code>, <code>1</code> and <code>2</code> or the values of <code>LOW</code>, <code>MEDIUM</code> and <code>STRONG</code> respectively) - the policy setting <code>LOW</code> only tests password strength - by default, passwords must be at least 8 characters long. This length can be changed by modifying the variable <code>validate_password_length</code>, a <code>MEDIUM</code> policy setting adds certain conditions - passwords must contrain at least 1 numeric, lowercase, uppercase and special character. These values can also be changed by modifying the variables <code>validate_password_number_count</code>, <code>validate_password_mixed_case_count</code> and <code>validate_password_special_char_count</code>.<br>A <code>STRONG</code> password policy setting adds the condition that passwords that match or exceed the length of 4 characters must not match words in a dictionary file which can be specified by modifying the <code>validate_password_dictionary_file</code> variable.</li><li><strong>The MySQL enterprise firewall</strong> - as of MySQL Enterprise edition 5.6.24, MySQL also includes a MySQL Enterprise Firewall with a purpose of permitting or denying SQL statement execution according to a whitelist input validation. Each account registered with the firewall has its own whitelist of allowed statements - all other statements are blocked.</li><li><strong>The MySQL enterprise audit</strong> - the enterprise edition of MySQL also includes MySQL Enterprise Audit which is implemented using a plugin called <code>audit_log</code>. Enterprise audit uses the audit API in order to enable the monitoring and logging of queries executed on MySQL servers. The plugin produces a log file containing content that was derived looking at the activity of the server.</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>General Database Security</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>General database security, in the majority of cases, boils down to the usage of basic security measures for databases - we should use strong passwords for all of the accounts in use, developers should only allow people they trust to access data, prevent the database from being overloaded, avoid physical damage to the servers, avoid design flaws in software that deals with databases (SQL injection, for example, can be avoided by using prepared statements), also avoid data corruption or loss, etc.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Backups</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Data is an essential part of your website - as such, backing up your files and database should be a no-brainer. Data corrupts. Hard drives fail. There are all kinds of scenarios where you can lose data and if you do not back it up, you can be in deep trouble.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Backing up your files and database is an extremely important part of any security routine. There are multiple tools and services that are designed to automate this task (you can even make one yourself by creating a bash script), you can store data on cloud storage, drives etc. - storage space nowadays is so cheap that it makes sense to back up pretty much everything.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>And, in case a disaster does occur and your data gets wiped from the servers in production, it's extremely important to also test your backups and see if you can restore your data quickly and efficiently - performing backup testing should be an essential part of any backup routine.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Summary</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>To summarize, in order to protect your MySQL database after a data breach it is a good idea to re-install MySQL on your server and restrict user access shortly after. Keep in mind that your user accounts should use strong passwords (use uppercase, lowercase letters, numbers, and, if possible, symbols), consider using MySQL security plugins, be sure to enforce database security practices both in MySQL and in associated software configurations and take care of your backups. Back up all of your critical data, make sure your backups are up to date and always test them.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>If you have performed the steps outlined above, you should be well on your way to a better future for your MySQL database, however, securing your MySQL infrastructure is only one piece of the database puzzle: to keep your infrastructure safe, you should also consider <a href="https://breachdirectory.com/search" target="_blank" rel="noreferrer noopener">performing a scan through a list of various known data breaches that have been already leaked on the web</a> and then performing steps to secure yourself judging from that. Consider changing your passwords, enabling two-factor authentication, and keeping an eye out on various security-related blogs to learn more about the newest developments in the database space.</p>
<!-- /wp:paragraph -->