John Carver's picture

For a long time I've known that the default installation of MySQL leaves behind a test database and several extraneous user permissions.  I've always tried to remember to remove these using phpMyAdmin, but sometimes it's easy to forget.  As a result of the recent HeartBleed incident, I've been taking a closer look at security.  One of the things I discovered is that MySQL has included a script, mysql_secure_installation, which removes the test database and secures the server for production.

# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MySQL to secure it, we'll need the current
password for the root user.  If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.

You already have a root password set, so you can safely answer 'n'.

Change the root password? [Y/n] n
 ... skipping.

By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MySQL comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
ERROR 1008 (HY000) at line 1: Can't drop database 'test'; database doesn't exist
 ... Failed!  Not critical, keep moving...
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...


All done!  If you've completed all of the above steps, your MySQL
installation should now be secure.

Thanks for using MySQL!

I recommend that all administrators run this script to make sure your MySQL installation is secure.  Unfortunately, the script is interactive and prompts for the root password, so it can't easily be included in the build process.  I tried analyzing the script and including the key parts in common/conf/mysql:

# cat common/conf/mysql

#!/bin/sh -e

set ${FAB_HOSTNAME:=backstage}

[ "$MYSQL_PASS" ] && /usr/lib/inithooks/bin/mysqlconf.py --pass="$MYSQL_PASS"

# start mysql server
/etc/init.d/mysql start

# secure mysql installation
mysql --defaults-extra-file=/etc/mysql/debian.cnf <<EOF
USE mysql;
# remove fabricating systems hostname from user table
DELETE FROM mysql.user WHERE Host = '$FAB_HOSTNAME';

# remove anonymous users
DELETE FROM mysql.user WHERE User='';

# remove remote root
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');

# remove test database
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';

# reload privilege tables
FLUSH PRIVILEGES;
EOF

# stop mysql server
/etc/init.d/mysql stop

At first I thought the modified script was not working, but after furthur tests, I realized the failure was due to a bug in my test procedure.  I'm testing using ProxMox virtual hosts.  I was just overwriting the test iso without changing the filename.  I forgot that if the VM has the iso attached, it keeps the file open so that overwriting does not actually replace the contents of the file.  I have to detach the iso and then reattach it every time the iso is changed.  I will conduct some additional tests and then submit a pull request.

Forum: 
Liraz Siri's picture

Hi John, I opened an issue on the tracker for this:

https://github.com/turnkeylinux/tracker/issues/239

I'm all for tightening the screws as long as we don't break anything or make the system harder to use out of the box - in which case it would be better to let users tighten the screws themselves rather than have to untighten them first.

If we are going to do this then the fistboot possible the safest way to go because we know it at least won't inadvertantly break the build process. Of course a firstboot script might still break something but that should be easier to test - just run the script after the system boots for the first time and test that everything still works.

I don't think we rely on the anonymous user for anything but you never know. Deleting the test database shouldn't do any harm (or good?). Removing remote root would add another layer of defense though we do bind MySQL to localhost anyhow (except in TurnKey MySQL).

Also, you're correct that TKLDev doesn't have pre-deb and post-deb scripts. All the configuration scripts are applied after the package specification is installed. To the best of my knowledge we've never run into a situation where that wasn't enough. I think we allowed pre-deb scripts in TKLPatch just because it was super easy to implement.

Anyhow it looks like you researched this issue thoroughly - well done! Including the relevant parts of the script in the common mysql conf file is potentially a good idea - assuming we know it doesn't break anything downstream. We need do to be careful not to accidentally break an assumption that other integrations might rely on. The tricky thing is that we won't really know for sure until we try this and rebuild all of the apps that use MySQL.

John Carver's picture

I was hoping I could edit my post before anyone read it, but it looks like you were composing a reply to my first version, while I was changing it to reflect new information.  At first I thought the script above run during the build process was ineffective because it ran too early.  I then tried moving it to firstboot and found it still didn't work, however it would if run manually.  When I examined the firstboot.d files and did not find the script where it should have been, I started thinking about what could be wrong with my test procedure.  Finally it dawned on me that Proxmox had the iso file open to attach it to the CD/DVD device.  Overwriting the iso file would have no effect until the file was closed and re-opened.  Kind of like having to flush a browser cache to see the latest version of a page.  Once I realized what happened, I went back and retested the script in conf/mysql and it does work as expected.  I've only tested the script on the ownCloud appliance.

Now that you've automated the build process with TKLdev, what are your plans for automating the testing process? 

Information is free, knowledge is acquired, but wisdom is earned.

Jeremy Davis's picture

If you are using TurnKey Linux (or Debian; or probably Ubuntu too) then it shouldn't be running as root. AFAIK on TurnKey (and Debian and prob Ubuntu) the process is started/stopped by a special MySQL user called "mysql". From my understanding the "mysql" user has elevated privileges WRT to MySQL (so it can do important things that you need your MySQL server to do, like write logs and start/stop the service etc) but doesn't have root privileges system wide...

Bottom line there should be nothing to do...

If you are on some other variety of Linux (or Windows) then you'll need to check relevant docs elsewhere...

Add new comment