您的位置:首页 > 数据库 > MySQL

【技术分享】CVE-2016-6662:Mysql远程代码执行/权限提升技术分析正式版(9/13 10:47更新)

2016-09-14 08:49 1101 查看
【技术分享】CVE-2016-6662:Mysql远程代码执行/权限提升技术分析正式版(9/13 10:47更新)





作者:苦逼司马(凌晨四点收到投稿,感谢作者连夜编辑技术分析)

稿费:800RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

引用
【技术分享】CVE-2016-6662-MySQL ‘malloc_lib’变量重写命令执行分析
http://bobao.360.cn/learning/detail/3026.html
【漏洞预警】Mysql代码执行漏洞,可本地提权(含exp,9/13 01点更新)
http://bobao.360.cn/learning/detail/3025.html

Discovered by: Dawid Golunski

http://legalhackers.com

dawid (at) legalhackers.com

CVE-2016-6662

Release date: 12.09.2016

Severity: Critical 

I. VULNERABILITY

MySQL <= 5.7.15 远程代码执行/权限提升 (0day)
5.6.33
5.5.52
克隆mysql的同样受影响, 包括:
MariaDB PerconaDB

II. INTRODUCTION

一个独立的研究组织发现多处严重的Mysql漏洞,此次通报的是其中比较严重的一个漏洞CVE-2016-6662,它允许攻击者远程注入恶意设置到被攻击服务器的Mysql配置文件(my.cnf)中,导致更加严重的后果。
该漏洞影响所有默认配置的Mysql版本分支(5.7、5.6、5.5),包括最新的版本,并可能被攻击者进行本地或者远程的利用。exp既可以通过网络连接或者利用类似phpmyadmin之类的web管理工具,以及SQL注入漏洞等。
SQL注入漏洞是在web应用中最常见的漏洞之一,在存在注入漏洞的情况下,攻击者可以配合CVE-2016-6662进行更加深入的入侵。如果被攻击服务器有运行受影响的mysql版本,攻击用该漏洞的EXP可以以root权限执行任意代码,从而完全控制被攻击服务器。
目前官方还没有提供针对该漏洞的补丁,即使服务器开启了SELinux安全模式,也会受到该漏洞Exp的影响。该通报后面提供一个该漏洞的Poc,演示攻击者如何实现远程代码执行。

III. DESCRIPTION

默认的Mysql安装包自带mysql_safe脚本,启动mysql服务器就可以观察到,例如,假如进行mysql全面更新。
Debian系统:

通过运行如下命令启动Mysql(用默认Debian仓库提供的软件包安装)

root@debian:~# service mysql start
或用如下方式启动:
root@debian:~# /etc/init.d/mysql start
Mysql服务的进程树看起来如下:
可以看出,mysqld_safe封装脚本是以root权限启动的,而主要的mysqld进程是用较低权限的mysql用户启动的。
mysqld_safe封装脚本有以下功能 :
它可以用来在启动服务之前加载共享库,库文件可以通过下面的参数进行设置:
--malloc-lib=LIB
这个参数也可以在mysqld的配置文件中指定(my.cnf中),在[mysqld]或者[mysqld_safe]部分。
如果攻击者能够将其恶意的库文件路径插入到配置文件中,就可以加载任意库,当mysql服务重启(手动、系统更新包更新、系统重启等)时,可以以root权限执行任意代码。
2003年公布的一个mysql 3.23.55之前版本的漏洞,允许攻击者利用一个简单的语句创建mysql配置文件:
SELECT * INFO OUTFILE '/var/lib/mysql/my.cnf'
这个漏洞被修复,利用outfile查询创建的文件默认是没办法覆盖现有文件的,这样可以保护现有的配置文件。该漏洞已经在mysql 3.23.55版本中修复,写入配置文件已经算不可能了。
然而POC证明,有可能利用Mysql的日志功能(默认方式安装的mysql)绕过当前的限制,来实现如下的目标: 1,注入恶意配置文件到现有的mysql配置文件中,前提是配置文件权限配置不当,配置文件所属用户是mysql用户,并且mysql用户有配置文件的可写权限; 2,在mysql数据目录中创建新的配置文件,通过默认方式安装mysql的话,mysql用户默认对此目录是有可写权限的,因此不需要依靠不当的权限配置。
3,通过默认方式安装的mysql,攻击者仅用select查询的file权限就可以访问日志功能(该功能通常只提供给mysql管理用户),因此攻击者可以在位置添加修改配置文件。


IV. PROOF OF CONCEPT

1,利用不正确的权限配置(配置文件所属mysql用户,mysql用户有可写权限)注入恶意配置到mysql的配置文件;
当mysqld_safe脚本执行时,mysql配置文件从所有支持的位置逐一加载和处理,确切的配置文件位置取决于mysql的版本。 例如,如上所述: http://dev.mysql.com/doc/refman/5.5/en/option-files.html mysql5.5的配置位置包括:
/etc/my.cnf 全局配置
/etc/mysql/my.cnf 全局配置
SYSCONFDIR/my.cnf 全局配置
$MYSQL_HOME/my.cnf 服务特定配置
默认额外文件,如果有~/my.cnf,用--defaults-extra-file参数来指定用户特定的配置。
目前有一种常见误解是mysql用户必须有mysql配置文件的所属权限,才能让服务正常工作。许多安装指南,甚至安全指南经常错误的建议用户给予mysql用户mysql配置文件或目录的所属权限。 例如: https://github.com/willfong/mariadb-backup/blob/master/README.md 提到:
用如下命令设置配置文件权限:

而在如下文章中提到:
http://www.devshed.com/c/a/mysql/security-issues-with-mysql/ "你应该保护全局配置文件/etc/my.cnf,如果存在的该文件,所属用户应该是mysql用户,并且mysql用户要有读写权限,但其它用户只需要只读权限"。
shell> chown mysql /etc/my.cnf"
如果mysql用户有mysql配置文件的所属权限,攻击可以追加恶意的配置项,如下所示:
攻击者可以运行下面的SQL查询:

然后配置文件将增加如下的部分:

这个配置将会让mysql启动失败,因为该文件中包含一些冗余的信息,然而最重要的部分是mysql配置文件包含了以下部分:
在mysqld守护进程启动之前,mysqldsafe将正确的读取共享库的路径,并把它添加到LDPRELOAD环境变量。然后预装库的fopen()函数在mysqld守护进程启动之前处理和清理配置文,为的是mysql能够正常启动。

2,在mysql数据目录中创建新的配置文件,通过默认方式安装mysql的话,mysql用户默认对此目录是有可写权限的,因此不需要依靠不当的权限配置。
mysqldsafe脚本的分析表明,在除上文中提到的配置文件位置之外,在mysql5.5、5.6版本中mysqldsafe在默认情况下还会从mysql的数据目录(/var/lib/mysql/my.cnf)加载配置文件,如下:

从mysql 5.7开始移除了这个功能,然而在很多配置中,任然是从如下位置加载配置文件:

/var/lib/mysql/.my.cnf
mysql用户是有mysql数据目录(/var/lib/mysql)写权限的:

因此,如果没有所属mysql用户的配置文件,攻击者可能仍然能够利用此漏洞在如下位置创建配置文件:

/var/lib/mysql/my.cnf /var/lib/mysql/.my.cnf
正如前文提到的,用file权限创建这样的文件:
SELECT '恶意配置内容' INTO OUTFILE '/var/lib/mysql/my.cnf'
是行不通的,因为通过这种方式创建的文件权限如下:
mysql在启动的时候会组织这种全部可写的配置,但是攻击者利用该漏洞可以绕过这个限制:

以上SQL创建一个具有必要权限(other用户没有读写权限)的可供mysql守护进程解析的配置文件:

这个文件包含的内容如下:
然而,依然存在一个问题,mysql会拒绝不以“[”符号开头的文件,会报错如下:
error: Found option without preceding group in config file: /var/lib/mysql/my.cnf at line: 1 Fatal error in defaults handling. Program aborted
不过深入的测试证明可以绕过此安全限制导致的错误,继续看下文。
值得大家注意的是,cve-2016-6662漏洞的报告者利用其它漏洞可以轻易的创建任意内容的/var/lib/mysql/my.cnf配置文件,并不需要file权限,只是报告者并未披露其它的漏洞。

3,通过默认方式安装的mysql,攻击者仅用select查询的file权限就可以访问日志功能(该功能通常只提供给mysql管理用户),因此攻击者可以在位置添加修改配置文件。
如果攻击者没有访问日志功能的管理权限,只有标准用户权限与另外的file权限,那么攻击者仍然可以获得写入修改配置文件的能力,可以利用一个恶意的触发器来实现:

利用类似的语句创建触发器
当表刷新的时候就会执行触发器,比如通过insert来让表刷新:
触发器的代码会以mysql root权限执行,从而让攻击者修改general_log设置,即使攻击者没有数据库管理员权限。

V. PROOF OF CONCEPT - 0day

下面是0ldSQLMySQLRCEexploit.py脚本要注入的共享库内容,当mysqld守护进程启动的时候,mysqldsafe会加载该恶意的共享库,然后会主动连接远程攻击者坚挺的6603端口,并给攻击者反弹一个root shell。
python脚本首先会创建修改mysql配置文件,加入如下内容:
[mysqld] malloclib=mysqlhookandroot_lib.so
然后当mysqld启动的时候,mysqld_safe会加载.so文件中的恶意内容,然后.so文件中的execvp()函数首先会清理掉mysql配置文件中插入的垃圾内容,只保留[mysqld]这个字段,以确保mysqld服务能正常启动,之后就会向攻击者反弹一个root
shell。在使用该文件的时候,需要调整一个接收shell的IP和端口,以及配置路径等。
使用如下命令进行编译:
mysqlhookandrootlib.c内容如下:

复现测试流程: 

1,创建一个测试用的数据库,并创建测试用户的账号和权限,如下:

2,将存在的mysql配置文件的所属用户修改成mysql用户,如下:

3,用attacker用户运行该exp,运行完毕重启mysql服务 首先,在.c文件中输入你的库路径; 接着,运行.py脚本。 如:
4,然后在定义的接收反弹shell的服务器用nc监听6033端口即可收到反弹的shell。

详细漏洞测试过程,是在ubuntu 14.04中测试的。

1,安装mysql-server ,mysql-client
sudo apt-get install mysql-server mysql-client
2,安装gcc
sudo apt-get  install  build-essential
3,安装exp脚本中用到的mysql connector,下载地址
http://cdn.mysql.com//Downloads/Connector-Python/mysql-connector-python1.2.3-1ubuntu12.04all.deb
4,创建测试用的数据库,以及需要账号及权限

注意上面这条中数据库名是用反引号括起来的。
5,编译mysqlhookandrootlib.c文件,编译之前,修改内容如下:




其中IP、端口是另外一台需要监听的服务器的,执行exp之后被攻击服务器会主动向上面的IP跟端口反弹一个root权限的shell。
my.cnf是我的测试环境中配置文件的默认位置。
编译命令:
6,修改/etc/mysql/my.cnf的所属用户及组



7,唯一鸡肋的地方是需要对ubuntu的apparmor相关的配置,不然exp执行的时候会报错误6,会提示
centos的话应该是需要关闭selinux,不过看漏洞介绍说不关闭这个的情况下也能利用,可能是描述有误吧。
修改方法:
修改成如图所示:



修改完成之后执行:
8,然后将编译好的.so文件以及.py文件放到同一个目录,执行如下命令:
执行成功后如图所示:






然后在之前设定的那个服务器上就会接收到root权限的shell,如图:




引用
【技术分享】CVE-2016-6662-MySQL ‘malloc_lib’变量重写命令执行分析
http://bobao.360.cn/learning/detail/3026.html
【漏洞预警】Mysql代码执行漏洞,可本地提权(含exp,9/13 01点更新)
http://bobao.360.cn/learning/detail/3025.html

本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html

参与讨论,请先 登录 |
注册 | 匿名评论
匿名
发布

用户评论



带头大哥的小弟 2016-09-13 18:38:41
回复 | 
点赞(0)

首先,要set global需要super权限其次如下:1、mysql> select @@version;+------------+| @@version |+------------+| 5.5.52-log |+------------+1 row in set (0.02 sec)2、mysql> set global general_log_file = '/etc/my.cnf';ERROR 1231 (42000): Variable 'general_log_file'
can't be set to the value of '/etc/my.cnf'3、-rw------- 1 mysql mysql 4676 Sep 11 02:18 /etc/my.cnf[root@pentest ~]# ps -ef |grep mysqlroot 24639 2544 0 02:19 pts/0 00:00:00 /bin/sh ./mysqld_safe --user=mysqlmysql 24894 24639 0 02:19 pts/0 00:00:01
/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/pentest.err --pid-file=/usr/local/mysql/data/pentest.pid --socket=/tmp/mysql.sock
--port=3306大家都怎么测的。



你丫才是黑阔 2016-09-13 18:29:19
回复 | 
点赞(0)

仅需要file权限?只有file权限的时候mysql 5.5.52 set global会提示无权限。



被吊打的小白 2016-09-13 14:07:01
回复 | 
点赞(0)

RBL



大表嫂 2016-09-13 13:25:15
回复 | 
点赞(1)

mysqld_safe并没有启动?ubuntu下默认apt-get一步安装mysqld_safe还是没有启动,是不是就不能利用了



我只是路过 2016-09-13 12:44:29
回复 | 
点赞(0)

有这种条件的时候直接加个user=root,重启还不报错,随后load file到crontab执行即可,如果有create权限,完全可以UDF。



冰锋刺客 2016-09-13 11:36:38
回复 | 
点赞(0)

这就厉害了 :-D
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐