Merge branch 'goliath' into add_https

GSoC/Meterpreter_Web_Console
Matthew Kienow 2018-01-23 18:59:59 -05:00
commit 2ffd627c56
No known key found for this signature in database
GPG Key ID: 40787F8B1EAC6E41
41 changed files with 166 additions and 173 deletions

View File

@ -1,8 +1,6 @@
require 'singleton'
require 'open3' require 'open3'
require 'rex/ui' require 'rex/ui'
require 'rex/logging' require 'rex/logging'
require 'msf/core/db_manager'
require 'metasploit/framework/data_service/remote/http/core' require 'metasploit/framework/data_service/remote/http/core'
require 'metasploit/framework/data_service/proxy/data_proxy_auto_loader' require 'metasploit/framework/data_service/proxy/data_proxy_auto_loader'
@ -14,11 +12,17 @@ module Metasploit
module Framework module Framework
module DataService module DataService
class DataProxy class DataProxy
include Singleton
include DataProxyAutoLoader include DataProxyAutoLoader
attr_reader :usable attr_reader :usable
def initialize(opts = {})
@data_services = {}
@data_service_id = 0
@usable = false
setup(opts)
end
# #
# Returns current error state # Returns current error state
# #
@ -47,34 +51,6 @@ class DataProxy
return false return false
end end
#
# Initializes the data service to be used - primarily on startup
#
def init(framework, opts)
@mutex.synchronize {
if (@initialized)
return
end
begin
if (opts['DisableDatabase'])
@error = 'disabled'
return
elsif (opts['DatabaseRemoteProcess'])
run_remote_db_process(opts)
else
run_local_db_process(framework, opts)
end
@usable = true
@initialized = true
rescue Exception => e
puts "Unable to initialize a dataservice #{e.message}"
return
end
}
end
# #
# Registers a data service with the proxy and immediately # Registers a data service with the proxy and immediately
# set as primary if online # set as primary if online
@ -130,6 +106,14 @@ class DataProxy
end end
end end
def respond_to?(method_name, include_private=false)
unless @data_service.nil?
return @data_service.respond_to?(method_name, include_private)
end
false
end
# #
# Attempt to shutdown the local db process if it exists # Attempt to shutdown the local db process if it exists
# #
@ -144,10 +128,6 @@ class DataProxy
end end
end end
#########
protected
#########
def get_data_service def get_data_service
raise 'No registered data_service' unless @data_service raise 'No registered data_service' unless @data_service
return @data_service return @data_service
@ -157,12 +137,21 @@ class DataProxy
private private
####### #######
def initialize def setup(opts)
@data_services = {} begin
@data_service_id = 0 db_manager = opts.delete(:db_manager)
@usable = false if !db_manager.nil?
@initialized = false register_data_service(db_manager, true)
@mutex = Mutex.new() @usable = true
elsif opts['DatabaseRemoteProcess']
run_remote_db_process(opts)
@usable = true
else
@error = 'disabled'
end
rescue Exception => e
puts "Unable to initialize a dataservice #{e.message}"
end
end end
def validate(data_service) def validate(data_service)
@ -182,15 +171,6 @@ class DataProxy
end end
def run_local_db_process(framework, opts)
puts 'Initializing local db process'
db_manager = Msf::DBManager.new(framework)
if (db_manager.usable and not opts['SkipDatabaseInit'])
register_data_service(db_manager, true)
db_manager.init_db(opts)
end
end
def run_remote_db_process(opts) def run_remote_db_process(opts)
# started with no signal to prevent ctrl-c from taking out db # started with no signal to prevent ctrl-c from taking out db
db_script = File.join( Msf::Config.install_root, "msfdb -ns") db_script = File.join( Msf::Config.install_root, "msfdb -ns")

View File

@ -2,6 +2,7 @@ require 'metasploit/framework/data_service'
require 'metasploit/framework/data_service/remote/http/data_service_auto_loader' require 'metasploit/framework/data_service/remote/http/data_service_auto_loader'
require 'net/http' require 'net/http'
require 'net/https' require 'net/https'
require 'uri'
# #
# Parent data service for managing metasploit data in/on a separate process/machine over HTTP(s) # Parent data service for managing metasploit data in/on a separate process/machine over HTTP(s)
@ -13,7 +14,7 @@ class RemoteHTTPDataService
include Metasploit::Framework::DataService include Metasploit::Framework::DataService
include DataServiceAutoLoader include DataServiceAutoLoader
ONLINE_TEST_URL = "/api/1/msf/online" ONLINE_TEST_URL = "/api/v1/online"
EXEC_ASYNC = { :exec_async => true } EXEC_ASYNC = { :exec_async => true }
GET_REQUEST = 'GET' GET_REQUEST = 'GET'
POST_REQUEST = 'POST' POST_REQUEST = 'POST'
@ -30,71 +31,94 @@ class RemoteHTTPDataService
end end
# #
# POST data and don't wait for the endpoint to process the data before getting a response # POST data to the HTTP endpoint and don't wait for the endpoint to process the data before getting a response
# #
def post_data_async(path, data_hash) # @param path - The URI path to send the request
make_request(POST_REQUEST, path, data_hash.merge(EXEC_ASYNC)) # @param data_hash - A hash representation of the object to be posted. Cannot be nil or empty.
# @param query - A hash representation of the URI query data. Key-value pairs will be URL-encoded.
#
# @return A wrapped response (ResponseWrapper), see below.
#
def post_data_async(path, data_hash, query = nil)
make_request(POST_REQUEST, path, data_hash.merge(EXEC_ASYNC), query)
end end
# #
# POST data to the HTTP endpoint # POST data to the HTTP endpoint
# #
# @param path - The URI path to send the request
# @param data_hash - A hash representation of the object to be posted. Cannot be nil or empty. # @param data_hash - A hash representation of the object to be posted. Cannot be nil or empty.
# @param path - The URI path to post to # @param query - A hash representation of the URI query data. Key-value pairs will be URL-encoded.
# #
# @return A wrapped response (ResponseWrapper), see below. # @return A wrapped response (ResponseWrapper), see below.
# #
def post_data(path, data_hash) def post_data(path, data_hash, query = nil)
make_request(POST_REQUEST, path, data_hash) make_request(POST_REQUEST, path, data_hash, query)
end end
# #
# GET data from the HTTP endpoint # GET data from the HTTP endpoint
# #
# @param path - The URI path to post to # @param path - The URI path to send the request
# @param data_hash - A hash representation of the object to be posted. Can be nil or empty. # @param data_hash - A hash representation of the object to be included. Can be nil or empty.
# @param query - A hash representation of the URI query data. Key-value pairs will be URL-encoded.
# #
# @return A wrapped response (ResponseWrapper), see below. # @return A wrapped response (ResponseWrapper), see below.
# #
def get_data(path, data_hash = nil) def get_data(path, data_hash = nil, query = nil)
make_request(GET_REQUEST, path, data_hash) make_request(GET_REQUEST, path, data_hash, query)
end end
# #
# Send DELETE request to delete the specified resource from the HTTP endpoint # Send DELETE request to delete the specified resource from the HTTP endpoint
# #
# @param path - The URI path to send the delete # @param path - The URI path to send the request
# @param data_hash - A hash representation of the object to be deleted. Cannot be nil or empty. # @param data_hash - A hash representation of the object to be deleted. Cannot be nil or empty.
# @param query - A hash representation of the URI query data. Key-value pairs will be URL-encoded.
# #
# @return A wrapped response (ResponseWrapper), see below. # @return A wrapped response (ResponseWrapper), see below.
# #
def delete_data(path, data_hash) def delete_data(path, data_hash, query = nil)
make_request(DELETE_REQUEST, path, data_hash) make_request(DELETE_REQUEST, path, data_hash, query)
end end
def make_request(request_type, path, data_hash = nil) #
# Make the specified request_type
#
# @param request_type - A string representation of the HTTP method
# @param path - The URI path to send the request
# @param data_hash - A hash representation of the object to be included in the request. Cannot be nil or empty.
# @param query - A hash representation of the URI query data. Key-value pairs will be URL-encoded.
#
# @return A wrapped response (ResponseWrapper)
#
def make_request(request_type, path, data_hash = nil, query = nil)
begin begin
puts "#{Time.now} - HTTP #{request_type} request to #{path} with #{data_hash ? data_hash : "nil"}" query_str = (!query.nil? && !query.empty?) ? URI.encode_www_form(query) : nil
uri = URI::HTTP::build({path: path, query: query_str})
puts "#{Time.now} - HTTP #{request_type} request to #{uri.request_uri} with #{data_hash ? data_hash : "nil"}"
client = @client_pool.pop() client = @client_pool.pop()
case request_type case request_type
when GET_REQUEST when GET_REQUEST
request = Net::HTTP::Get.new(path) request = Net::HTTP::Get.new(uri.request_uri)
when POST_REQUEST when POST_REQUEST
request = Net::HTTP::Post.new(path) request = Net::HTTP::Post.new(uri.request_uri)
when DELETE_REQUEST when DELETE_REQUEST
request = Net::HTTP::Delete.new(path) request = Net::HTTP::Delete.new(uri.request_uri)
else else
raise Exception, 'A request_type must be specified' raise Exception, 'A request_type must be specified'
end end
built_request = build_request(request, data_hash) built_request = build_request(request, data_hash)
response = client.request(built_request) response = client.request(built_request)
if response.code == "200" case response
# puts 'request sent successfully' when Net::HTTPOK
return SuccessResponse.new(response) # puts 'request sent successfully'
else return SuccessResponse.new(response)
puts "HTTP #{request_type} request: #{path} failed with code: #{response.code} message: #{response.body}" else
return FailedResponse.new(response) puts "HTTP #{request_type} request: #{uri.request_uri} failed with code: #{response.code} message: #{response.body}"
return FailedResponse.new(response)
end end
rescue EOFError => e rescue EOFError => e
puts "ERROR: No data was returned from the server." puts "ERROR: No data was returned from the server."
@ -147,9 +171,7 @@ class RemoteHTTPDataService
end end
def set_header(key, value) def set_header(key, value)
if (@headers.nil?) @headers = Hash.new() if @headers.nil?
@headers = Hash.new()
end
@headers[key] = value @headers[key] = value
end end
@ -199,24 +221,20 @@ class RemoteHTTPDataService
def append_workspace(data_hash) def append_workspace(data_hash)
workspace = data_hash[:workspace] workspace = data_hash[:workspace]
unless (workspace) workspace = data_hash.delete(:wspace) unless workspace
workspace = data_hash.delete(:wspace)
end
if (workspace && (workspace.is_a?(OpenStruct) || workspace.is_a?(::Mdm::Workspace))) if workspace && (workspace.is_a?(OpenStruct) || workspace.is_a?(::Mdm::Workspace))
data_hash[:workspace] = workspace.name data_hash[:workspace] = workspace.name
end end
if (workspace.nil?) data_hash[:workspace] = current_workspace_name if workspace.nil?
data_hash[:workspace] = current_workspace_name
end
data_hash data_hash
end end
def build_request(request, data_hash) def build_request(request, data_hash)
request.content_type = 'application/json' request.content_type = 'application/json'
if (!data_hash.nil? && !data_hash.empty?) if !data_hash.nil? && !data_hash.empty?
data_hash.each do |k,v| data_hash.each do |k,v|
if v.is_a?(Msf::Session) if v.is_a?(Msf::Session)
puts "#{Time.now} - DEBUG: Dropping Msf::Session object before converting to JSON." puts "#{Time.now} - DEBUG: Dropping Msf::Session object before converting to JSON."
@ -230,7 +248,7 @@ class RemoteHTTPDataService
request.body = json_body request.body = json_body
end end
if (!@headers.nil? && !@headers.empty?) if !@headers.nil? && !@headers.empty?
@headers.each do |key, value| @headers.each do |key, value|
request[key] = value request[key] = value
end end

View File

@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
module RemoteCredentialDataService module RemoteCredentialDataService
include ResponseDataHelper include ResponseDataHelper
CREDENTIAL_API_PATH = '/api/1/msf/credential' CREDENTIAL_API_PATH = '/api/v1/credentials'
# "MDM_CLASS" is a little misleading since it is not in that repo but trying to keep naming consistent across DataServices # "MDM_CLASS" is a little misleading since it is not in that repo but trying to keep naming consistent across DataServices
CREDENTIAL_MDM_CLASS = 'Metasploit::Credential::Core' CREDENTIAL_MDM_CLASS = 'Metasploit::Credential::Core'

View File

@ -1,5 +1,5 @@
module RemoteEventDataService module RemoteEventDataService
EVENT_API_PATH = '/api/1/msf/event' EVENT_API_PATH = '/api/v1/events'
def report_event(opts) def report_event(opts)
self.post_data_async(EVENT_API_PATH, opts) self.post_data_async(EVENT_API_PATH, opts)

View File

@ -1,5 +1,5 @@
module RemoteExploitDataService module RemoteExploitDataService
EXPLOIT_API_PATH = '/api/1/msf/exploit' EXPLOIT_API_PATH = '/api/v1/exploits'
def report_exploit_attempt(host, opts) def report_exploit_attempt(host, opts)
opts[:host] = host opts[:host] = host

View File

@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
module RemoteHostDataService module RemoteHostDataService
include ResponseDataHelper include ResponseDataHelper
HOST_API_PATH = '/api/1/msf/host' HOST_API_PATH = '/api/v1/hosts'
HOST_SEARCH_PATH = HOST_API_PATH + "/search" HOST_SEARCH_PATH = HOST_API_PATH + "/search"
HOST_MDM_CLASS = 'Mdm::Host' HOST_MDM_CLASS = 'Mdm::Host'

View File

@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
module RemoteLootDataService module RemoteLootDataService
include ResponseDataHelper include ResponseDataHelper
LOOT_API_PATH = '/api/1/msf/loot' LOOT_API_PATH = '/api/v1/loots'
LOOT_MDM_CLASS = 'Mdm::Loot' LOOT_MDM_CLASS = 'Mdm::Loot'
def loot(opts = {}) def loot(opts = {})

View File

@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
module RemoteNmapDataService module RemoteNmapDataService
include ResponseDataHelper include ResponseDataHelper
NMAP_PATH = '/api/1/msf/nmap' NMAP_PATH = '/api/v1/nmaps'
def import_nmap_xml_file(opts) def import_nmap_xml_file(opts)
filename = opts[:filename] filename = opts[:filename]

View File

@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
module RemoteNoteDataService module RemoteNoteDataService
include ResponseDataHelper include ResponseDataHelper
NOTE_API_PATH = '/api/1/msf/note' NOTE_API_PATH = '/api/v1/notes'
def report_note(opts) def report_note(opts)
self.post_data_async(NOTE_API_PATH, opts) self.post_data_async(NOTE_API_PATH, opts)

View File

@ -1,5 +1,5 @@
module RemoteServiceDataService module RemoteServiceDataService
SERVICE_API_PATH = '/api/1/msf/service' SERVICE_API_PATH = '/api/v1/services'
def report_service(opts) def report_service(opts)
self.post_data_async(SERVICE_API_PATH, opts) self.post_data_async(SERVICE_API_PATH, opts)

View File

@ -1,6 +1,6 @@
module RemoteSessionDataService module RemoteSessionDataService
SESSION_API_PATH = '/api/1/msf/session' SESSION_API_PATH = '/api/v1/sessions'
SESSION_MDM_CLASS = 'Mdm::Session' SESSION_MDM_CLASS = 'Mdm::Session'
def report_session(opts) def report_session(opts)

View File

@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
module RemoteSessionEventDataService module RemoteSessionEventDataService
include ResponseDataHelper include ResponseDataHelper
SESSION_EVENT_API_PATH = '/api/1/msf/session_event' SESSION_EVENT_API_PATH = '/api/v1/session-events'
SESSION_EVENT_MDM_CLASS = 'Mdm::SessionEvent' SESSION_EVENT_MDM_CLASS = 'Mdm::SessionEvent'
def session_events(opts = {}) def session_events(opts = {})

View File

@ -1,6 +1,6 @@
module RemoteVulnDataService module RemoteVulnDataService
VULN_API_PATH = '/api/1/msf/vuln' VULN_API_PATH = '/api/v1/vulns'
def report_vuln(opts) def report_vuln(opts)
self.post_data_async(VULN_API_PATH, opts) self.post_data_async(VULN_API_PATH, opts)
end end

View File

@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
module RemoteWebDataService module RemoteWebDataService
include ResponseDataHelper include ResponseDataHelper
WEB_API_PATH = '/api/1/msf/web' WEB_API_PATH = '/api/v1/webs'
def report_web_site(opts) def report_web_site(opts)
self.post_data_async(WEB_API_PATH, opts) self.post_data_async(WEB_API_PATH, opts)

View File

@ -3,8 +3,9 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
module RemoteWorkspaceDataService module RemoteWorkspaceDataService
include ResponseDataHelper include ResponseDataHelper
WORKSPACE_COUNTS_API_PATH = '/api/1/msf/workspace/counts' # TODO: should counts be a flag in query data for the workspaces resource?
WORKSPACE_API_PATH = '/api/1/msf/workspace' WORKSPACE_COUNTS_API_PATH = '/api/v1/workspaces/counts'
WORKSPACE_API_PATH = '/api/v1/workspaces'
WORKSPACE_MDM_CLASS = 'Mdm::Workspace' WORKSPACE_MDM_CLASS = 'Mdm::Workspace'
DEFAULT_WORKSPACE_NAME = 'default' DEFAULT_WORKSPACE_NAME = 'default'
@ -38,7 +39,7 @@ module RemoteWorkspaceDataService
end end
def workspace_associations_counts() def workspace_associations_counts()
json_to_mdm_object(self.get_data(WORKSPACE_API_PATH, []), WORKSPACE_MDM_CLASS, []) json_to_mdm_object(self.get_data(WORKSPACE_COUNTS_API_PATH, []), WORKSPACE_MDM_CLASS, [])
end end
######### #########

View File

@ -18,7 +18,7 @@ module Msf::DBManager::Connection
migrate migrate
# Set the default workspace # Set the default workspace
framework.db.workspace = framework.db.default_workspace self.workspace = self.default_workspace
rescue ::Exception => exception rescue ::Exception => exception
self.error = exception self.error = exception
elog("DB.connect threw an exception: #{exception}") elog("DB.connect threw an exception: #{exception}")

View File

@ -56,7 +56,7 @@ module Msf::DBManager::Host
# Exactly like report_host but waits for the database to create a host and returns it. # Exactly like report_host but waits for the database to create a host and returns it.
def find_or_create_host(opts) def find_or_create_host(opts)
host = get_host(opts) host = get_host(opts.clone)
return host unless host.nil? return host unless host.nil?
report_host(opts) report_host(opts)

View File

@ -1,7 +1,7 @@
module CredentialServlet module CredentialServlet
def self.api_path def self.api_path
'/api/1/msf/credential' '/api/v1/credentials'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module EventServlet module EventServlet
def self.api_path def self.api_path
'/api/1/msf/event' '/api/v1/events'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module ExploitServlet module ExploitServlet
def self.api_path def self.api_path
'/api/1/msf/exploit' '/api/v1/exploits'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module HostServlet module HostServlet
def self.api_path def self.api_path
'/api/1/msf/host' '/api/v1/hosts'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module LootServlet module LootServlet
def self.api_path def self.api_path
'/api/1/msf/loot' '/api/v1/loots'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module NmapServlet module NmapServlet
def self.api_path def self.api_path
'/api/1/msf/nmap' '/api/v1/nmaps'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module NoteServlet module NoteServlet
def self.api_path def self.api_path
'/api/1/msf/note' '/api/v1/notes'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module OnlineTestServlet module OnlineTestServlet
def self.api_path def self.api_path
'/api/1/msf/online' '/api/v1/online'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module ServiceServlet module ServiceServlet
def self.api_path def self.api_path
'/api/1/msf/service' '/api/v1/services'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module SessionEventServlet module SessionEventServlet
def self.api_path def self.api_path
'/api/1/msf/session_event' '/api/v1/session-events'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,6 +1,6 @@
module SessionServlet module SessionServlet
def self.api_path def self.api_path
'/api/1/msf/session' '/api/v1/sessions'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module VulnServlet module VulnServlet
def self.api_path def self.api_path
'/api/1/msf/vuln' '/api/v1/vulns'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module WebServlet module WebServlet
def self.api_path def self.api_path
'/api/1/msf/web' '/api/v1/webs'
end end
def self.registered(app) def self.registered(app)

View File

@ -1,7 +1,7 @@
module WorkspaceServlet module WorkspaceServlet
def self.api_path def self.api_path
'/api/1/msf/workspace' '/api/v1/workspaces'
end end
def self.registered(app) def self.registered(app)

View File

@ -58,20 +58,23 @@ module Msf::DBManager::Workspace
end end
def delete_all_workspaces() def delete_all_workspaces()
delete_workspaces(workspaces.map(&:name)) return delete_workspaces(workspaces.map(&:name))
end end
def delete_workspaces(names) def delete_workspaces(names)
status_msg = []
error_msg = []
switched = false switched = false
# Delete workspaces # Delete workspaces
names.each do |name| names.each do |name|
workspace = framework.db.find_workspace(name) workspace = framework.db.find_workspace(name)
if workspace.nil? if workspace.nil?
print_error("Workspace not found: #{name}") error << "Workspace not found: #{name}"
elsif workspace.default? elsif workspace.default?
workspace.destroy workspace.destroy
workspace = framework.db.add_workspace(name) workspace = framework.db.add_workspace(name)
print_status("Deleted and recreated the default workspace") status_msg << 'Deleted and recreated the default workspace'
else else
# switch to the default workspace if we're about to delete the current one # switch to the default workspace if we're about to delete the current one
if framework.db.workspace.name == workspace.name if framework.db.workspace.name == workspace.name
@ -80,10 +83,11 @@ module Msf::DBManager::Workspace
end end
# now destroy the named workspace # now destroy the named workspace
workspace.destroy workspace.destroy
print_status("Deleted workspace: #{name}") status_msg << "Deleted workspace: #{name}"
end end
end end
print_status("Switched workspace: #{framework.db.workspace.name}") if switched (status_msg << "Switched workspace: #{framework.db.workspace.name}") if switched
return status_msg, error_msg
end end
# #

View File

@ -199,7 +199,7 @@ class Framework
# @return [Metasploit::Framework::DataService::DataProxy] # @return [Metasploit::Framework::DataService::DataProxy]
def db def db
synchronize { synchronize {
@db ||= Metasploit::Framework::DataService::DataProxy.instance @db ||= get_db
} }
end end
@ -268,6 +268,19 @@ protected
attr_writer :db # :nodoc: attr_writer :db # :nodoc:
attr_writer :uuid_db # :nodoc: attr_writer :uuid_db # :nodoc:
attr_writer :browser_profiles # :nodoc: attr_writer :browser_profiles # :nodoc:
private
def get_db
if !options['DatabaseRemoteProcess'] && !options['DisableDatabase']
db_manager = Msf::DBManager.new(self)
db_manager.init_db(options)
options[:db_manager] = db_manager
end
Metasploit::Framework::DataService::DataProxy.new(options)
end
end end
class FrameworkEventSubscriber class FrameworkEventSubscriber

View File

@ -104,7 +104,7 @@ module Msf::Modules::Metadata::Store
def get_user_store def get_user_store
store_dir = ::File.join(Msf::Config.config_directory, "store") store_dir = ::File.join(Msf::Config.config_directory, "store")
FileUtils.mkdir(store_dir) if !::File.exist?(store_dir) FileUtils.makedirs(store_dir) if !::File.exist?(store_dir)
return ::File.join(store_dir, UserMetaDataFile) return ::File.join(store_dir, UserMetaDataFile)
end end

View File

@ -393,7 +393,6 @@ class Creds
} }
tbl = Rex::Text::Table.new(tbl_opts) tbl = Rex::Text::Table.new(tbl_opts)
opts = {}
opts[:wspace] = framework.db.workspace opts[:wspace] = framework.db.workspace
query = framework.db.creds(opts) query = framework.db.creds(opts)

View File

@ -89,13 +89,11 @@ module Msf
end end
def cmd_set_data_service(service_id) def cmd_set_data_service(service_id)
data_proxy = Metasploit::Framework::DataService::DataProxy.instance framework.db.set_data_service(service_id)
data_proxy.set_data_service(service_id)
end end
def cmd_list_data_services() def cmd_list_data_services()
data_service_manager = Metasploit::Framework::DataService::DataProxy.instance framework.db.print_data_services
data_service_manager.print_data_services
end end
def cmd_add_data_service(*args) def cmd_add_data_service(*args)
@ -127,8 +125,7 @@ module Msf
endpoint = "#{protocol}://#{host}:#{port}" endpoint = "#{protocol}://#{host}:#{port}"
remote_data_service = Metasploit::Framework::DataService::RemoteHTTPDataService.new(endpoint, https_opts) remote_data_service = Metasploit::Framework::DataService::RemoteHTTPDataService.new(endpoint, https_opts)
data_service_manager = Metasploit::Framework::DataService::DataProxy.instance framework.db.register_data_service(remote_data_service)
data_service_manager.register_data_service(remote_data_service)
end end
def cmd_add_data_service_help def cmd_add_data_service_help
@ -157,8 +154,7 @@ module Msf
end end
puts 'Reporting test host to data service' puts 'Reporting test host to data service'
data_service = Metasploit::Framework::DataService::DataProxy.instance framework.db.report_host host
data_service.report_host host
end end
def cmd_test_data_service_loot(*args) def cmd_test_data_service_loot(*args)
@ -181,8 +177,7 @@ module Msf
end end
puts 'Reporting test loot to data service' puts 'Reporting test loot to data service'
data_service = Metasploit::Framework::DataService::DataProxy.instance framework.db.report_loot loot
data_service.report_loot loot
end end
def cmd_perf_test_data_service_loot(*args) def cmd_perf_test_data_service_loot(*args)
@ -226,11 +221,10 @@ module Msf
end end
puts 'Reporting test loot to data service' puts 'Reporting test loot to data service'
data_service = Metasploit::Framework::DataService::DataProxy.instance
start_time = Time.now start_time = Time.now
puts "#{start_time} - Staring loot perf test" puts "#{start_time} - Staring loot perf test"
loots.each do |loot| loots.each do |loot|
data_service.report_loot loot framework.db.report_loot loot
end end
end_time = Time.now end_time = Time.now
puts "#{end_time} - Ending loot perf test. Duration was #{end_time - start_time}" puts "#{end_time} - Ending loot perf test. Duration was #{end_time - start_time}"
@ -284,9 +278,11 @@ module Msf
end end
framework.db.workspace = workspace framework.db.workspace = workspace
elsif deleting and names elsif deleting and names
framework.db.delete_workspaces(names) status_msg, error_msg = framework.db.delete_workspaces(names)
print_msgs(status_msg, error_msg)
elsif delete_all elsif delete_all
framework.db.delete_all_workspaces() status_msg, error_msg = framework.db.delete_all_workspaces()
print_msgs(status_msg, error_msg)
elsif renaming elsif renaming
if names.length != 2 if names.length != 2
print_error("Wrong number of arguments to rename") print_error("Wrong number of arguments to rename")
@ -2021,6 +2017,18 @@ module Msf
end end
end end
private
def print_msgs(status_msg, error_msg)
status_msg.each do |s|
print_status(s)
end
error_msg.each do |e|
print_error(e)
end
end
end end
end end end end end end end end

View File

@ -122,7 +122,6 @@ class Driver < Msf::Ui::Driver
enstack_dispatcher(dispatcher) enstack_dispatcher(dispatcher)
end end
framework.db.init(framework, opts)
if (framework.db.active) if (framework.db.active)
require 'msf/ui/console/command_dispatcher/db' require 'msf/ui/console/command_dispatcher/db'
enstack_dispatcher(CommandDispatcher::Db) enstack_dispatcher(CommandDispatcher::Db)

View File

@ -77,7 +77,7 @@ RSpec.describe Msf::Auxiliary::Cisco do
context '#cisco_ios_config_eater' do context '#cisco_ios_config_eater' do
before(:example) do before(:example) do
expect(aux_cisco).to receive(:myworkspace).and_return(workspace) expect(aux_cisco).to receive(:myworkspace).at_least(:once).and_return(workspace)
end end
it 'deals with udp ports' do it 'deals with udp ports' do

View File

@ -6,12 +6,12 @@ RSpec.shared_context 'Msf::DBManager' do
end end
let(:db_manager) do let(:db_manager) do
framework.db framework.db.get_data_service
end end
before(:example) do before(:example) do
# already connected due to use_transactional_fixtures, but need some of the side-effects of #connect # already connected due to use_transactional_fixtures, but need some of the side-effects of #connect
framework.db.workspace = framework.db.default_workspace db_manager.workspace = db_manager.default_workspace
allow(db_manager).to receive(:active).and_return(active) allow(db_manager).to receive(:active).and_return(active)
end end
end end

View File

@ -5,7 +5,6 @@ RSpec.shared_examples_for 'Msf::DBManager::Host' do
it { is_expected.to respond_to :get_host } it { is_expected.to respond_to :get_host }
it { is_expected.to respond_to :has_host? } it { is_expected.to respond_to :has_host? }
it { is_expected.to respond_to :hosts } it { is_expected.to respond_to :hosts }
it { is_expected.to respond_to :normalize_host }
it { is_expected.to respond_to :report_host } it { is_expected.to respond_to :report_host }
it { is_expected.to respond_to :update_host_via_sysinfo } it { is_expected.to respond_to :update_host_via_sysinfo }
end end

View File

@ -172,20 +172,6 @@ RSpec.shared_examples_for 'Msf::DBManager::Session' do
end end
context 'with workspace from either :workspace or session' do context 'with workspace from either :workspace or session' do
it 'should pass normalized host from session as :host to #find_or_create_host' do
normalized_host = double('Normalized Host')
expect(db_manager).to receive(:normalize_host).with(session).and_return(normalized_host)
# stub report_vuln so its use of find_or_create_host and Msf::Util::Host.normalize_host doesn't interfere.
expect(db_manager).to receive(:report_vuln)
expect(db_manager).to receive(:find_or_create_host).with(
hash_including(
:host => normalized_host
)
).and_return(host)
report_session
end
context 'with session responds to arch' do context 'with session responds to arch' do
let(:arch) do let(:arch) do
@ -515,20 +501,6 @@ RSpec.shared_examples_for 'Msf::DBManager::Session' do
end end
context 'with workspace from either :workspace or session' do context 'with workspace from either :workspace or session' do
it 'should pass normalized host from session as :host to #find_or_create_host' do
normalized_host = double('Normalized Host')
allow(db_manager).to receive(:normalize_host).with(session).and_return(normalized_host)
# stub report_vuln so its use of find_or_create_host and Msf::Util::Host.normalize_host doesn't interfere.
allow(db_manager).to receive(:report_vuln)
expect(db_manager).to receive(:find_or_create_host).with(
hash_including(
:host => normalized_host
)
).and_return(host)
report_session
end
context 'with session responds to arch' do context 'with session responds to arch' do
let(:arch) do let(:arch) do