Specify peer hostname for ssl connections

This commit is contained in:
adfoster-r7 2022-04-25 21:07:14 +01:00
parent 8a3f2b9542
commit 739c0fcad1
No known key found for this signature in database
GPG Key ID: 3BD4FA3818818F04
9 changed files with 225 additions and 136 deletions

View File

@ -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,

View File

@ -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'

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -36,6 +36,7 @@ class ClientRequest
'vars_form_data' => [],
'version' => '1.1',
'vhost' => nil,
'ssl_server_name_indication' => nil,
#
# Evasion options

View File

@ -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

View File

@ -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?

View File

@ -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