diff --git a/lib/metasploit/framework/tcp/client.rb b/lib/metasploit/framework/tcp/client.rb index b7af8a675d..655f7b199d 100644 --- a/lib/metasploit/framework/tcp/client.rb +++ b/lib/metasploit/framework/tcp/client.rb @@ -83,6 +83,7 @@ module Metasploit nsock = Rex::Socket::Tcp.create( 'PeerHost' => opts['RHOST'] || rhost, + 'PeerHostname' => opts['SSLServerNameIndication'] || opts['VHOST'] || opts['RHOSTNAME'], 'PeerPort' => (opts['RPORT'] || rport).to_i, 'LocalHost' => opts['CHOST'] || chost || "0.0.0.0", 'LocalPort' => (opts['CPORT'] || cport || 0).to_i, diff --git a/lib/msf/core/exploit/remote/http_client.rb b/lib/msf/core/exploit/remote/http_client.rb index 2eef8e612c..faf6b8747e 100644 --- a/lib/msf/core/exploit/remote/http_client.rb +++ b/lib/msf/core/exploit/remote/http_client.rb @@ -47,7 +47,8 @@ module Exploit::Remote::HttpClient OptFloat.new('HttpClientTimeout', [false, 'HTTP connection and receive timeout']), OptBool.new('HttpTrace', [false, 'Show the raw HTTP requests and responses', false]), OptBool.new('HttpTraceHeadersOnly', [false, 'Show HTTP headers only in HttpTrace', false]), - OptString.new('HttpTraceColors', [false, 'HTTP request and response colors for HttpTrace (unset to disable)', 'red/blu']) + OptString.new('HttpTraceColors', [false, 'HTTP request and response colors for HttpTrace (unset to disable)', 'red/blu']), + OptString.new('SSLServerNameIndication', [ false, 'SSL/TLS Server Name Indication (SNI)', nil]), ], self.class ) @@ -91,7 +92,7 @@ module Exploit::Remote::HttpClient end def deregister_http_client_options - deregister_options('RHOST', 'RPORT', 'VHOST', 'SSL', 'Proxies') + deregister_options('RHOST', 'RPORT', 'VHOST', 'SSL', 'SSLServerNameIndication', 'Proxies') end # @@ -163,9 +164,12 @@ module Exploit::Remote::HttpClient comm: opts['comm'] ) + # Configure the HTTP client with the supplied parameter + vhost = opts['vhost'] || opts['rhost'] || self.vhost nclient.set_config( - 'vhost' => opts['vhost'] || opts['rhost'] || self.vhost(), + 'vhost' => vhost, + 'ssl_server_name_indication' => datastore['SSLServerNameIndication'] || vhost, 'agent' => datastore['UserAgent'], 'partial' => opts['partial'], 'uri_encode_mode' => datastore['HTTP::uri_encode_mode'], @@ -487,6 +491,7 @@ module Exploit::Remote::HttpClient opts['rhost'] = datastore['RHOST'] opts['vhost'] = opts['vhost'] || opts['rhost'] || self.vhost() + opts['ssl_server_name_indication'] = opts['vhost'] opts['rport'] = datastore['RPORT'] opts['SSL'] = ssl @@ -497,6 +502,7 @@ module Exploit::Remote::HttpClient opts['uri'] = location.path opts['rhost'] = location.host opts['vhost'] = location.host + opts['ssl_server_name_indication'] = opts['vhost'] opts['rport'] = location.port if location.scheme == 'https' diff --git a/lib/msf/core/exploit/remote/tcp.rb b/lib/msf/core/exploit/remote/tcp.rb index 51721520fa..e0992907e2 100644 --- a/lib/msf/core/exploit/remote/tcp.rb +++ b/lib/msf/core/exploit/remote/tcp.rb @@ -63,6 +63,7 @@ module Exploit::Remote::Tcp register_advanced_options( [ OptBool.new('SSL', [ false, 'Negotiate SSL/TLS for outgoing connections', false]), + OptString.new('SSLServerNameIndication', [ false, 'SSL/TLS Server Name Indication (SNI)', nil]), Opt::SSLVersion, OptEnum.new('SSLVerifyMode', [ false, 'SSL verification method', 'PEER', %W{CLIENT_ONCE FAIL_IF_NO_PEER_CERT NONE PEER}]), OptString.new('SSLCipher', [ false, 'String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"']), @@ -100,6 +101,7 @@ module Exploit::Remote::Tcp nsock = Rex::Socket::Tcp.create( 'PeerHost' => opts['RHOST'] || rhost, + 'PeerHostname' => opts['SSLServerNameIndication'] || opts['VHOST'] || opts['RHOSTNAME'], 'PeerPort' => (opts['RPORT'] || rport).to_i, 'LocalHost' => opts['CHOST'] || chost || "0.0.0.0", 'LocalPort' => (opts['CPORT'] || cport || 0).to_i, diff --git a/lib/msf/core/rhosts_walker.rb b/lib/msf/core/rhosts_walker.rb index 34f64ae3ca..a5596b4263 100644 --- a/lib/msf/core/rhosts_walker.rb +++ b/lib/msf/core/rhosts_walker.rb @@ -147,7 +147,7 @@ module Msf overrides = {} overrides['UNPARSED_RHOSTS'] = value overrides['RHOSTS'] = rhost[:address] - overrides['VHOST'] = rhost[:hostname] if datastore.options.include?('VHOST') && datastore['VHOST'].blank? + set_hostname(datastore, overrides, rhost[:hostname]) results << datastore.merge(overrides) end end @@ -170,6 +170,7 @@ module Msf result['RHOSTS'] = uri.hostname result['RPORT'] = (uri.port || 445) if datastore.options.include?('RPORT') + set_hostname(datastore, result, uri.hostname) # Handle users in the format: # user # domain;user @@ -207,8 +208,6 @@ module Msf def parse_http_uri(value, datastore) uri = ::Addressable::URI.parse(value) result = {} - # nil VHOST for now, this value will be calculated and overridden later - result['VHOST'] = nil result['RHOSTS'] = uri.hostname is_ssl = %w[ssl https].include?(uri.scheme) @@ -224,7 +223,9 @@ module Msf result['URI'] = target_uri if datastore.options.include?('URI') end - result['VHOST'] = uri.hostname unless Rex::Socket.is_ip_addr?(uri.hostname) + result['HttpQueryString'] = uri.query if datastore.options.include?('HttpQueryString') + + set_hostname(datastore, result, uri.hostname) set_username(datastore, result, uri.user) if uri.user set_password(datastore, result, uri.password) if uri.password @@ -250,6 +251,7 @@ module Msf result['DATABASE'] = uri.path[1..-1] end + set_hostname(datastore, result, uri.hostname) set_username(datastore, result, uri.user) if uri.user set_password(datastore, result, uri.password) if uri.password result @@ -272,6 +274,8 @@ module Msf if datastore.options.include?('DATABASE') && has_database_specified result['DATABASE'] = uri.path[1..-1] end + + set_hostname(datastore, result, uri.hostname) set_username(datastore, result, uri.user) if uri.user set_password(datastore, result, uri.password) if uri.password @@ -291,6 +295,7 @@ module Msf result['RHOSTS'] = uri.hostname result['RPORT'] = uri.port || 22 + set_hostname(datastore, result, uri.hostname) set_username(datastore, result, uri.user) if uri.user set_password(datastore, result, uri.password) if uri.password @@ -312,6 +317,7 @@ module Msf result['RPORT'] = uri.port end + set_hostname(datastore, result, uri.hostname) set_username(datastore, result, uri.user) if uri.user set_password(datastore, result, uri.password) if uri.password @@ -320,6 +326,12 @@ module Msf protected + def set_hostname(datastore, result, hostname) + hostname = Rex::Socket.is_ip_addr?(hostname) ? nil : hostname + result['RHOSTNAME'] = hostname if result['RHOSTNAME'].blank? + result['VHOST'] = hostname if datastore.options.include?('VHOST') && datastore['VHOST'].blank? + end + def set_username(datastore, result, username) # Preference setting application specific values first username_set = false diff --git a/lib/rex/proto/http/client.rb b/lib/rex/proto/http/client.rb index 17caf6c0f6..7c71d88af0 100644 --- a/lib/rex/proto/http/client.rb +++ b/lib/rex/proto/http/client.rb @@ -36,6 +36,7 @@ class Client self.config = Http::ClientRequest::DefaultConfig.merge({ 'read_max_data' => (1024*1024*1), 'vhost' => self.hostname, + 'ssl_server_name_indication' => self.hostname, }) self.config['agent'] ||= Rex::UserAgent.session_agent @@ -171,7 +172,8 @@ class Client timeout = (t.nil? or t == -1) ? 0 : t self.conn = Rex::Socket::Tcp.create( - 'PeerHost' => self.hostname, + 'PeerHost' => self.hostname, + 'PeerHostname' => self.config['ssl_server_name_indication'] || self.config['vhost'], 'PeerPort' => self.port.to_i, 'LocalHost' => self.local_host, 'LocalPort' => self.local_port, diff --git a/lib/rex/proto/http/client_request.rb b/lib/rex/proto/http/client_request.rb index de9be99b77..444952f033 100644 --- a/lib/rex/proto/http/client_request.rb +++ b/lib/rex/proto/http/client_request.rb @@ -36,6 +36,7 @@ class ClientRequest 'vars_form_data' => [], 'version' => '1.1', 'vhost' => nil, + 'ssl_server_name_indication' => nil, # # Evasion options diff --git a/modules/auxiliary/gather/impersonate_ssl.rb b/modules/auxiliary/gather/impersonate_ssl.rb index e07b733a3c..f0c71bf032 100644 --- a/modules/auxiliary/gather/impersonate_ssl.rb +++ b/modules/auxiliary/gather/impersonate_ssl.rb @@ -32,7 +32,7 @@ class MetasploitModule < Msf::Auxiliary register_options( [ Opt::RPORT(443), - OptString.new('SNI', [false, 'Server Name Indicator', nil]), + OptString.new('SSLServerNameIndication', [ false, 'SSL/TLS Server Name Indication (SNI)', nil]), OptEnum.new('OUT_FORMAT', [true, 'Output format', 'PEM', ['DER', 'PEM']]), OptString.new('EXPIRATION', [false, 'Date the new cert should expire (e.g. 06 May 2012, YESTERDAY or NOW)', nil]), OptPath.new('PRIVKEY', [false, 'Sign the cert with your own CA private key', nil]), @@ -58,8 +58,8 @@ class MetasploitModule < Msf::Auxiliary end def run - if !datastore['SNI'].nil? - sni = datastore['SNI'] + if !datastore['SSLServerNameIndication'].nil? + sni = datastore['SSLServerNameIndication'] print_status("Connecting to #{rhost}:#{rport} SNI:#{sni}") else sni = false diff --git a/modules/auxiliary/scanner/http/title.rb b/modules/auxiliary/scanner/http/title.rb index 1b78f1d1d3..3b01da056f 100644 --- a/modules/auxiliary/scanner/http/title.rb +++ b/modules/auxiliary/scanner/http/title.rb @@ -27,6 +27,14 @@ class MetasploitModule < Msf::Auxiliary OptBool.new('SHOW_TITLES', [ true, 'Show the titles on the console as they are grabbed', true ]), OptString.new('TARGETURI', [true, 'The base path', '/']) ]) + + register_advanced_options( + [ + OptString.new('HttpQueryString', [ false, 'The HTTP query string', nil ]), + OptBool.new('FollowRedirect', [ false, 'Follow a HTTP redirect', false ]), + OptInt.new('FollowRedirectDepth', [false, 'Follow HTTP redirect depth', 1]), + ] + ) end def run @@ -39,10 +47,17 @@ class MetasploitModule < Msf::Auxiliary def run_host(target_host) begin + http_opts = { + 'uri' => normalize_uri(target_uri.path), + 'query' => datastore['HttpQueryString'] + } + # Send a normal GET request - res = send_request_cgi( - 'uri' => normalize_uri(target_uri.path) - ) + if datastore['FollowRedirect'] + res = send_request_cgi!(http_opts, datastore['HttpClientTimeout'] || 20, datastore['FollowRedirectDepth']) + else + res = send_request_cgi(http_opts) + end # If no response, quit now if res.nil? diff --git a/spec/lib/msf/core/rhosts_walker_spec.rb b/spec/lib/msf/core/rhosts_walker_spec.rb index 40676032c8..c2f7075325 100644 --- a/spec/lib/msf/core/rhosts_walker_spec.rb +++ b/spec/lib/msf/core/rhosts_walker_spec.rb @@ -16,12 +16,13 @@ RSpec::Matchers.define :have_datastore_values do |expected| end def http_options_for(datastores) - http_keys = %w[RHOSTS RPORT VHOST SSL HttpUsername HttpPassword TARGETURI URI] + dynamic_keys = %w[RHOSTNAME] + http_keys = %w[RHOSTS RPORT VHOST SSL HttpUsername HttpPassword HttpQueryString TARGETURI URI] smb_keys = %w[RHOSTS RPORT SMBDomain SMBUser SMBPass SMBSHARE RPATH] mysql_keys = %w[RHOSTS RPORT USERNAME PASSWORD] postgres_keys = %w[RHOSTS RPORT USERNAME PASSWORD DATABASE] ssh_keys = %w[RHOSTS RPORT USERNAME PASSWORD] - required_keys = http_keys + smb_keys + mysql_keys + postgres_keys + ssh_keys + required_keys = dynamic_keys + http_keys + smb_keys + mysql_keys + postgres_keys + ssh_keys datastores.map do |datastore| # Workaround: Manually convert the datastore to a hash ourselves as `datastore.to_h` coerces all datatypes into strings # which prevents this test suite from validating types correctly. i.e. The tests need to ensure that RPORT is correctly @@ -99,7 +100,43 @@ RSpec.describe Msf::RhostsWalker do [ Msf::Opt::RHOSTS, Msf::Opt::RPORT(3000), - Msf::OptString.new('TARGETURI', [true, 'Path to application', '/default_app']) + Msf::OptString.new('TARGETURI', [true, 'Path to application', '/default_app']), + ] + ) + end + end + + mod = mod_klass.new + datastore = Msf::ModuleDataStore.new(mod) + allow(mod).to receive(:framework).and_return(nil) + mod.send(:datastore=, datastore) + datastore.import_options(mod.options) + mod + end + + let(:http_mod_with_query_string) do + mod_klass = Class.new(Msf::Auxiliary) do + include Msf::Exploit::Remote::HttpClient + + def initialize + super( + 'Name' => 'mock http module', + 'Description' => 'mock http module', + 'Author' => ['Unknown'], + 'License' => MSF_LICENSE + ) + + register_options( + [ + Msf::Opt::RHOSTS, + Msf::Opt::RPORT(3000), + Msf::OptString.new('TARGETURI', [true, 'Path to application', '/default_app']), + ] + ) + + register_advanced_options( + [ + Msf::OptString.new('HttpQueryString', [ false, 'The HTTP query string', nil ]) ] ) end @@ -397,7 +434,7 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates RHOSTS with a single ip' do aux_mod.datastore['RHOSTS'] = '127.0.0.1' expected = [ - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000 } + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000 } ] expect(each_host_for(aux_mod)).to have_datastore_values(expected) end @@ -405,9 +442,9 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates multiple RHOSTS separated by spaces' do aux_mod.datastore['RHOSTS'] = '127.0.0.1 127.0.0.2 127.0.0.3' expected = [ - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000 }, - { 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000 }, - { 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000 }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000 }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000 }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000 }, ] expect(each_host_for(aux_mod)).to have_datastore_values(expected) end @@ -415,10 +452,10 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates a single ipv4 address range' do aux_mod.datastore['RHOSTS'] = '127.0.0.0/30' expected = [ - { 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000 }, - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000 }, - { 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000 }, - { 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000 } + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000 }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000 }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000 }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000 } ] expect(each_host_for(aux_mod)).to have_datastore_values(expected) end @@ -427,8 +464,8 @@ RSpec.describe Msf::RhostsWalker do temp_file = create_tempfile("127.0.0.0\n127.0.0.1") aux_mod.datastore['RHOSTS'] = "file:#{temp_file}" expected = [ - { 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000 }, - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000 }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000 }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000 }, ] expect(each_host_for(aux_mod)).to have_datastore_values(expected) end @@ -436,7 +473,7 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates a single http value' do http_mod.datastore['RHOSTS'] = 'http://www.example.com/foo' expected = [ - { 'RHOSTS' => '233.252.0.0', 'RPORT' => 80, 'VHOST' => 'www.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' } + { 'RHOSTNAME' => 'www.example.com', 'RHOSTS' => '233.252.0.0', 'RPORT' => 80, 'VHOST' => 'www.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -445,8 +482,8 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates resolving a single http value to multiple ip addresses' do http_mod.datastore['RHOSTS'] = 'http://multiple_ips.example.com/foo' expected = [ - { 'RHOSTS' => '198.51.100.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' } + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -465,10 +502,10 @@ RSpec.describe Msf::RhostsWalker do ) http_mod.datastore['RHOSTS'] = 'http://example.com/ http://user@example.com/ http://user:password@example.com http://:@example.com' expected = [ - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'admin', 'HttpPassword' => 'admin', 'TARGETURI' => '/' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'admin', 'TARGETURI' => '/' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'admin', 'HttpPassword' => 'admin', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'admin', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -477,19 +514,31 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates a query string containing commas' do http_mod.datastore['RHOSTS'] = 'http://multiple_ips.example.com/foo?filter=a,b,c' expected = [ - { 'RHOSTS' => '198.51.100.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' } + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, ] + expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty end + it 'enumerates a query string containing commas and sets HttpQueryString if the datastore option is available' do + http_mod_with_query_string.datastore['RHOSTS'] = 'http://multiple_ips.example.com/foo?filter=a,b,c' + expected = [ + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo', 'HttpQueryString' => 'filter=a,b,c' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo', 'HttpQueryString' => 'filter=a,b,c' }, + ] + + expect(each_host_for(http_mod_with_query_string)).to have_datastore_values(expected) + expect(each_error_for(http_mod_with_query_string)).to be_empty + end + it 'handles values wrapped in quotes as atomic values' do http_mod.datastore['RHOSTS'] = '127.0.0.1 "http://user:this is a password@example.com" http://user:password@example.com' expected = [ - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'this is a password', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/default_app' } + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'this is a password', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/default_app' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -508,12 +557,12 @@ RSpec.describe Msf::RhostsWalker do ) http_mod.datastore['RHOSTS'] = '127.0.0.1 https://example.com "http://user:this is a password@example.com" http://user:password@example.com http://user:password@example.com/ http://user:password@example.com/path' expected = [ - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => 'admin', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 443, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => 'admin', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'this is a password', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/path' } + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => 'admin', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 443, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => 'admin', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'this is a password', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/path' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) @@ -534,11 +583,11 @@ RSpec.describe Msf::RhostsWalker do http_mod.datastore['RHOSTS'] = 'http://example.com/ http://example.com/ http://user@example.com/ http://user:password@example.com http://:@example.com' expected = [ - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => nil, 'HttpPassword' => nil, 'TARGETURI' => '/' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => nil, 'HttpPassword' => nil, 'TARGETURI' => '/' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => nil, 'TARGETURI' => '/' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => nil, 'HttpPassword' => nil, 'TARGETURI' => '/' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => nil, 'HttpPassword' => nil, 'TARGETURI' => '/' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => nil, 'TARGETURI' => '/' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'password', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -547,10 +596,10 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates a cidr scheme with a single http value' do http_mod.datastore['RHOSTS'] = 'cidr:/30:http://127.0.0.1:3000/foo/bar' expected = [ - { 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, - { 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, - { 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' } + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -559,10 +608,10 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates a cidr scheme with a domain' do http_mod.datastore['RHOSTS'] = 'cidr:/30:https://example.com:8080/foo/bar' expected = [ - { 'RHOSTS' => '192.0.2.0', 'RPORT' => 8080, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, - { 'RHOSTS' => '192.0.2.1', 'RPORT' => 8080, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 8080, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, - { 'RHOSTS' => '192.0.2.3', 'RPORT' => 8080, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.0', 'RPORT' => 8080, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.1', 'RPORT' => 8080, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 8080, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.3', 'RPORT' => 8080, 'VHOST' => 'example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo/bar' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -571,14 +620,14 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates a cidr scheme with a domain with multiple ip addresses' do http_mod.datastore['RHOSTS'] = 'cidr:/30:http://multiple_ips.example.com/foo' expected = [ - { 'RHOSTS' => '198.51.100.0', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '198.51.100.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '198.51.100.2', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '198.51.100.3', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.0', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.2', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.3', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' } + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.0', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.2', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.3', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.0', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.1', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.2', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.3', 'RPORT' => 80, 'VHOST' => 'multiple_ips.example.com', 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/foo' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -588,8 +637,8 @@ RSpec.describe Msf::RhostsWalker do temp_file = create_tempfile("https://www.example.com/\n127.0.0.1") http_mod.datastore['RHOSTS'] = "file:#{temp_file}" expected = [ - { 'RHOSTS' => '233.252.0.0', 'RPORT' => 443, 'VHOST' => 'www.example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } + { 'RHOSTNAME' => 'www.example.com', 'RHOSTS' => '233.252.0.0', 'RPORT' => 443, 'VHOST' => 'www.example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -599,14 +648,14 @@ RSpec.describe Msf::RhostsWalker do temp_file = create_tempfile("127.0.0.1\n233.252.0.0") http_mod.datastore['RHOSTS'] = "cidr:/30:file:#{temp_file}" expected = [ - { 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '233.252.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '233.252.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '233.252.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '233.252.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '233.252.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '233.252.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '233.252.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '233.252.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -615,15 +664,16 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates a cidr scheme with a file' do temp_file = create_tempfile("127.0.0.1\n233.252.0.0") http_mod.datastore['RHOSTS'] = "cidr:/30:file:#{temp_file}" + expected = [ - { 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '233.252.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '233.252.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '233.252.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '233.252.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '233.252.0.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '233.252.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '233.252.0.2', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '233.252.0.3', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -632,9 +682,9 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates multiple ipv6 urls' do http_mod.datastore['RHOSTS'] = 'http://[::]:8000/ http://[::ffff:7f00:1]:8000/ http://[::1]:8000/' expected = [ - { 'RHOSTS' => '::', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '::ffff:7f00:1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '::1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' } + { 'RHOSTNAME' => nil, 'RHOSTS' => '::', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '::ffff:7f00:1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '::1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -644,12 +694,12 @@ RSpec.describe Msf::RhostsWalker do temp_file = create_tempfile("http://[::]:8000/\nhttp://[::ffff:7f00:1]:8000/\nhttp://[::1]:8000/") http_mod.datastore['RHOSTS'] = "cidr:/127:file:#{temp_file}" expected = [ - { 'RHOSTS' => '::', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '::1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '::ffff:7f00:0', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '::ffff:7f00:1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '::', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '::1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' } + { 'RHOSTNAME' => nil, 'RHOSTS' => '::', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '::1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '::ffff:7f00:0', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '::ffff:7f00:1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '::', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '::1', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -658,8 +708,8 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates cidr scheme with a ipv6 scope' do http_mod.datastore['RHOSTS'] = 'cidr:%eth2/127:http://[::]:8000/' expected = [ - { 'RHOSTS' => '::%eth2', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '::1%eth2', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' } + { 'RHOSTNAME' => nil, 'RHOSTS' => '::%eth2', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '::1%eth2', 'RPORT' => 8000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' } ] expect(each_host_for(http_mod)).to have_datastore_values(expected) expect(each_error_for(http_mod)).to be_empty @@ -669,7 +719,7 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates smb schemes for scanners when no user or password are specified' do smb_scanner_mod.datastore['RHOSTS'] = 'smb://example.com/' expected = [ - { 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => '', 'SMBPass' => '' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => '', 'SMBPass' => '' } ] expect(each_host_for(smb_scanner_mod)).to have_datastore_values(expected) end @@ -687,10 +737,10 @@ RSpec.describe Msf::RhostsWalker do ) smb_scanner_mod.datastore['RHOSTS'] = 'smb://example.com/ smb://user@example.com/ smb://user:password@example.com smb://:@example.com' expected = [ - { 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'db2admin', 'SMBPass' => 'db2admin' }, - { 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => 'db2admin' }, - { 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => 'password' }, - { 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => '', 'SMBPass' => '' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'db2admin', 'SMBPass' => 'db2admin' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => 'db2admin' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => 'password' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => '', 'SMBPass' => '' } ] expect(each_host_for(smb_scanner_mod)).to have_datastore_values(expected) end @@ -698,7 +748,7 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates smb schemes for scanners when a user and password are specified' do smb_scanner_mod.datastore['RHOSTS'] = 'smb://user:pass@example.com/' expected = [ - { 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBPass' => 'pass', 'SMBUser' => 'user' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => '.', 'SMBPass' => 'pass', 'SMBUser' => 'user' } ] expect(each_host_for(smb_scanner_mod)).to have_datastore_values(expected) end @@ -706,7 +756,7 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates smb schemes for scanners when a domain, user and password are specified' do smb_scanner_mod.datastore['RHOSTS'] = 'smb://domain;user:pass@example.com/' expected = [ - { 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => 'domain', 'SMBPass' => 'pass', 'SMBUser' => 'user' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => 'domain', 'SMBPass' => 'pass', 'SMBUser' => 'user' } ] expect(each_host_for(smb_scanner_mod)).to have_datastore_values(expected) end @@ -714,7 +764,7 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates smb schemes for ' do smb_scanner_mod.datastore['RHOSTS'] = 'smb://domain;user:pass@example.com/' expected = [ - { 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => 'domain', 'SMBPass' => 'pass', 'SMBUser' => 'user' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'SSL' => false, 'SMBDomain' => 'domain', 'SMBPass' => 'pass', 'SMBUser' => 'user' } ] expect(each_host_for(smb_scanner_mod)).to have_datastore_values(expected) end @@ -722,10 +772,10 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates smb schemes for when the module has SMBSHARE and RPATHS available' do smb_share_mod.datastore['RHOSTS'] = 'smb://user@example.com smb://user@example.com/ smb://user@example.com/share_name smb://user@example.com/share_name/path/to/file.txt' expected = [ - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 445, 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => '', 'SMBSHARE' => 'default_share_value', 'RPATH' => nil }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 445, 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => '', 'SMBSHARE' => 'default_share_value', 'RPATH' => nil }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 445, 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => '', 'SMBSHARE' => 'share_name', 'RPATH' => '' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 445, 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => '', 'SMBSHARE' => 'share_name', 'RPATH' => 'path/to/file.txt' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 445, 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => '', 'SMBSHARE' => 'default_share_value', 'RPATH' => nil }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 445, 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => '', 'SMBSHARE' => 'default_share_value', 'RPATH' => nil }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 445, 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => '', 'SMBSHARE' => 'share_name', 'RPATH' => '' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 445, 'SSL' => false, 'SMBDomain' => '.', 'SMBUser' => 'user', 'SMBPass' => '', 'SMBSHARE' => 'share_name', 'RPATH' => 'path/to/file.txt' } ] expect(each_host_for(smb_share_mod)).to have_datastore_values(expected) end @@ -742,7 +792,7 @@ RSpec.describe Msf::RhostsWalker do it 'handles complex passwords' do http_mod.datastore['RHOSTS'] = '"http://user:a b c p4$$w0rd@123@!@example.com/"' expected = [ - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'a b c p4$$w0rd@123@!', 'TARGETURI' => '/' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 80, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'a b c p4$$w0rd@123@!', 'TARGETURI' => '/' } ] expect(each_error_for(http_mod)).to be_empty expect(each_host_for(http_mod)).to have_datastore_values(expected) @@ -753,9 +803,9 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates mysql schemes' do mysql_mod.datastore['RHOSTS'] = 'mysql://mysql:@example.com "mysql://user:a b c@example.com/" "mysql://user:a+b+c=@example.com:9001/database_name"' expected = [ - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 3306, 'SSL' => false, 'USERNAME' => 'mysql', 'PASSWORD' => '', 'DATABASE' => 'information_schema' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 3306, 'SSL' => false, 'USERNAME' => 'user', 'PASSWORD' => 'a b c', 'DATABASE' => 'information_schema' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 9001, 'SSL' => false, 'USERNAME' => 'user', 'PASSWORD' => 'a+b+c=', 'DATABASE' => 'database_name' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 3306, 'SSL' => false, 'USERNAME' => 'mysql', 'PASSWORD' => '', 'DATABASE' => 'information_schema' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 3306, 'SSL' => false, 'USERNAME' => 'user', 'PASSWORD' => 'a b c', 'DATABASE' => 'information_schema' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 9001, 'SSL' => false, 'USERNAME' => 'user', 'PASSWORD' => 'a+b+c=', 'DATABASE' => 'database_name' } ] expect(each_error_for(mysql_mod)).to be_empty expect(each_host_for(mysql_mod)).to have_datastore_values(expected) @@ -766,9 +816,9 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates postgres schemes' do postgres_mod.datastore['RHOSTS'] = 'postgres://postgres:@example.com "postgres://user:a b c@example.com/" "postgres://user:a b c@example.com:9001/database_name"' expected = [ - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 5432, 'USERNAME' => 'postgres', 'PASSWORD' => '', 'DATABASE' => 'template1' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 5432, 'USERNAME' => 'user', 'PASSWORD' => 'a b c', 'DATABASE' => 'template1' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 9001, 'USERNAME' => 'user', 'PASSWORD' => 'a b c', 'DATABASE' => 'database_name' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 5432, 'USERNAME' => 'postgres', 'PASSWORD' => '', 'DATABASE' => 'template1' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 5432, 'USERNAME' => 'user', 'PASSWORD' => 'a b c', 'DATABASE' => 'template1' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 9001, 'USERNAME' => 'user', 'PASSWORD' => 'a b c', 'DATABASE' => 'database_name' } ] expect(each_error_for(postgres_mod)).to be_empty expect(each_host_for(postgres_mod)).to have_datastore_values(expected) @@ -779,8 +829,8 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates tcp schemes' do ssh_mod.datastore['RHOSTS'] = '"tcp://user:a b c@example.com" "tcp://example.com:3000"' expected = [ - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 22, 'USERNAME' => 'user', 'PASSWORD' => 'a b c' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 3000, 'USERNAME' => nil, 'PASSWORD' => nil }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 22, 'USERNAME' => 'user', 'PASSWORD' => 'a b c' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 3000, 'USERNAME' => nil, 'PASSWORD' => nil }, ] expect(each_error_for(ssh_mod)).to be_empty expect(each_host_for(ssh_mod)).to have_datastore_values(expected) @@ -791,7 +841,7 @@ RSpec.describe Msf::RhostsWalker do it 'enumerates ssh schemes' do ssh_mod.datastore['RHOSTS'] = '"ssh://user:a b c@example.com/"' expected = [ - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 22, 'USERNAME' => 'user', 'PASSWORD' => 'a b c' } + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 22, 'USERNAME' => 'user', 'PASSWORD' => 'a b c' } ] expect(each_error_for(ssh_mod)).to be_empty expect(each_host_for(ssh_mod)).to have_datastore_values(expected) @@ -804,25 +854,25 @@ RSpec.describe Msf::RhostsWalker do temp_file_b = create_tempfile("https://www.example.com/\n127.0.0.1\ncidr:/31:http://127.0.0.1/tomcat/manager\nfile:#{temp_file_a}") http_mod.datastore['RHOSTS'] = "127.0.0.1 cidr:/31:http://192.0.2.0/tomcat/manager https://192.0.2.0:8080/manager/html file:#{temp_file_b}" expected = [ - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.0', 'RPORT' => 80, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/tomcat/manager' }, - { 'RHOSTS' => '192.0.2.1', 'RPORT' => 80, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/tomcat/manager' }, - { 'RHOSTS' => '192.0.2.0', 'RPORT' => 8080, 'VHOST' => nil, 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/manager/html' }, - { 'RHOSTS' => '233.252.0.0', 'RPORT' => 443, 'VHOST' => 'www.example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '127.0.0.0', 'RPORT' => 80, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/tomcat/manager' }, - { 'RHOSTS' => '127.0.0.1', 'RPORT' => 80, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/tomcat/manager' }, - { 'RHOSTS' => '192.0.2.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '127.0.0.5', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, - { 'RHOSTS' => '192.0.2.2', 'RPORT' => 9000, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '198.51.100.0', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '198.51.100.1', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '198.51.100.2', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '198.51.100.3', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.0', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.1', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.2', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, - { 'RHOSTS' => '203.0.113.3', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' } + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '192.0.2.0', 'RPORT' => 80, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/tomcat/manager' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '192.0.2.1', 'RPORT' => 80, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/tomcat/manager' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '192.0.2.0', 'RPORT' => 8080, 'VHOST' => nil, 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/manager/html' }, + { 'RHOSTNAME' => 'www.example.com', 'RHOSTS' => '233.252.0.0', 'RPORT' => 443, 'VHOST' => 'www.example.com', 'SSL' => true, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.0', 'RPORT' => 80, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/tomcat/manager' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.1', 'RPORT' => 80, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/tomcat/manager' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '192.0.2.0', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => nil, 'RHOSTS' => '127.0.0.5', 'RPORT' => 3000, 'VHOST' => nil, 'SSL' => false, 'HttpUsername' => '', 'HttpPassword' => '', 'TARGETURI' => '/default_app' }, + { 'RHOSTNAME' => 'example.com', 'RHOSTS' => '192.0.2.2', 'RPORT' => 9000, 'VHOST' => 'example.com', 'SSL' => false, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.0', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.1', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.2', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '198.51.100.3', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.0', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.1', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.2', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' }, + { 'RHOSTNAME' => 'multiple_ips.example.com', 'RHOSTS' => '203.0.113.3', 'RPORT' => 9000, 'VHOST' => 'multiple_ips.example.com', 'SSL' => true, 'HttpUsername' => 'user', 'HttpPassword' => 'pass', 'TARGETURI' => '/foo' } ] expect(each_error_for(http_mod)).to be_empty