Merge branch 'goliath' into MS-2891
commit
dd65141a22
|
@ -3,6 +3,7 @@ require 'metasploit/framework/data_service'
|
|||
require 'metasploit/framework/data_service/remote/http/data_service_auto_loader'
|
||||
require 'net/http'
|
||||
require 'net/https'
|
||||
require 'uri'
|
||||
|
||||
#
|
||||
# Parent data service for managing metasploit data in/on a separate process/machine over HTTP(s)
|
||||
|
@ -14,7 +15,7 @@ class RemoteHTTPDataService
|
|||
include Metasploit::Framework::DataService
|
||||
include DataServiceAutoLoader
|
||||
|
||||
ONLINE_TEST_URL = "/api/1/msf/online"
|
||||
ONLINE_TEST_URL = "/api/v1/online"
|
||||
EXEC_ASYNC = { :exec_async => true }
|
||||
GET_REQUEST = 'GET'
|
||||
POST_REQUEST = 'POST'
|
||||
|
@ -30,71 +31,94 @@ class RemoteHTTPDataService
|
|||
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)
|
||||
make_request(POST_REQUEST, path, data_hash.merge(EXEC_ASYNC))
|
||||
# @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 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
|
||||
|
||||
#
|
||||
# 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 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.
|
||||
#
|
||||
def post_data(path, data_hash)
|
||||
make_request(POST_REQUEST, path, data_hash)
|
||||
def post_data(path, data_hash, query = nil)
|
||||
make_request(POST_REQUEST, path, data_hash, query)
|
||||
end
|
||||
|
||||
#
|
||||
# GET data from the HTTP endpoint
|
||||
#
|
||||
# @param path - The URI path to post to
|
||||
# @param data_hash - A hash representation of the object to be posted. Can be nil or empty.
|
||||
# @param path - The URI path to send the request
|
||||
# @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.
|
||||
#
|
||||
def get_data(path, data_hash = nil)
|
||||
make_request(GET_REQUEST, path, data_hash)
|
||||
def get_data(path, data_hash = nil, query = nil)
|
||||
make_request(GET_REQUEST, path, data_hash, query)
|
||||
end
|
||||
|
||||
#
|
||||
# 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 query - A hash representation of the URI query data. Key-value pairs will be URL-encoded.
|
||||
#
|
||||
# @return A wrapped response (ResponseWrapper), see below.
|
||||
#
|
||||
def delete_data(path, data_hash)
|
||||
make_request(DELETE_REQUEST, path, data_hash)
|
||||
def delete_data(path, data_hash, query = nil)
|
||||
make_request(DELETE_REQUEST, path, data_hash, query)
|
||||
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
|
||||
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()
|
||||
case request_type
|
||||
when GET_REQUEST
|
||||
request = Net::HTTP::Get.new(path)
|
||||
request = Net::HTTP::Get.new(uri.request_uri)
|
||||
when POST_REQUEST
|
||||
request = Net::HTTP::Post.new(path)
|
||||
request = Net::HTTP::Post.new(uri.request_uri)
|
||||
when DELETE_REQUEST
|
||||
request = Net::HTTP::Delete.new(path)
|
||||
request = Net::HTTP::Delete.new(uri.request_uri)
|
||||
else
|
||||
raise Exception, 'A request_type must be specified'
|
||||
end
|
||||
built_request = build_request(request, data_hash)
|
||||
response = client.request(built_request)
|
||||
|
||||
if response.code == "200"
|
||||
# puts 'request sent successfully'
|
||||
return SuccessResponse.new(response)
|
||||
else
|
||||
puts "HTTP #{request_type} request: #{path} failed with code: #{response.code} message: #{response.body}"
|
||||
return FailedResponse.new(response)
|
||||
case response
|
||||
when Net::HTTPOK
|
||||
# puts 'request sent successfully'
|
||||
return SuccessResponse.new(response)
|
||||
else
|
||||
puts "HTTP #{request_type} request: #{uri.request_uri} failed with code: #{response.code} message: #{response.body}"
|
||||
return FailedResponse.new(response)
|
||||
end
|
||||
rescue Exception => e
|
||||
puts "Problem with HTTP #{request_type} request: #{e.message}"
|
||||
|
@ -142,9 +166,7 @@ class RemoteHTTPDataService
|
|||
end
|
||||
|
||||
def set_header(key, value)
|
||||
if (@headers.nil?)
|
||||
@headers = Hash.new()
|
||||
end
|
||||
@headers = Hash.new() if @headers.nil?
|
||||
|
||||
@headers[key] = value
|
||||
end
|
||||
|
@ -195,24 +217,20 @@ class RemoteHTTPDataService
|
|||
|
||||
def append_workspace(data_hash)
|
||||
workspace = data_hash[:workspace]
|
||||
unless (workspace)
|
||||
workspace = data_hash.delete(:wspace)
|
||||
end
|
||||
workspace = data_hash.delete(:wspace) unless workspace
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
if (workspace.nil?)
|
||||
data_hash[:workspace] = current_workspace_name
|
||||
end
|
||||
data_hash[:workspace] = current_workspace_name if workspace.nil?
|
||||
|
||||
data_hash
|
||||
end
|
||||
|
||||
def build_request(request, data_hash)
|
||||
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|
|
||||
if v.is_a?(Msf::Session)
|
||||
puts "#{Time.now} - DEBUG: Dropping Msf::Session object before converting to JSON."
|
||||
|
@ -226,7 +244,7 @@ class RemoteHTTPDataService
|
|||
request.body = json_body
|
||||
end
|
||||
|
||||
if (!@headers.nil? && !@headers.empty?)
|
||||
if !@headers.nil? && !@headers.empty?
|
||||
@headers.each do |key, value|
|
||||
request[key] = value
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
|
|||
module RemoteCredentialDataService
|
||||
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
|
||||
CREDENTIAL_MDM_CLASS = 'Metasploit::Credential::Core'
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module RemoteEventDataService
|
||||
EVENT_API_PATH = '/api/1/msf/event'
|
||||
EVENT_API_PATH = '/api/v1/events'
|
||||
|
||||
def report_event(opts)
|
||||
self.post_data_async(EVENT_API_PATH, opts)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module RemoteExploitDataService
|
||||
EXPLOIT_API_PATH = '/api/1/msf/exploit'
|
||||
EXPLOIT_API_PATH = '/api/v1/exploits'
|
||||
|
||||
def report_exploit_attempt(host, opts)
|
||||
opts[:host] = host
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
|
|||
module RemoteHostDataService
|
||||
include ResponseDataHelper
|
||||
|
||||
HOST_API_PATH = '/api/1/msf/host'
|
||||
HOST_API_PATH = '/api/v1/hosts'
|
||||
HOST_SEARCH_PATH = HOST_API_PATH + "/search"
|
||||
HOST_MDM_CLASS = 'Mdm::Host'
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
|
|||
module RemoteLootDataService
|
||||
include ResponseDataHelper
|
||||
|
||||
LOOT_API_PATH = '/api/1/msf/loot'
|
||||
LOOT_API_PATH = '/api/v1/loots'
|
||||
LOOT_MDM_CLASS = 'Mdm::Loot'
|
||||
|
||||
def loot(opts = {})
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
|
|||
module RemoteNmapDataService
|
||||
include ResponseDataHelper
|
||||
|
||||
NMAP_PATH = '/api/1/msf/nmap'
|
||||
NMAP_PATH = '/api/v1/nmaps'
|
||||
|
||||
def import_nmap_xml_file(opts)
|
||||
filename = opts[:filename]
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
|
|||
module RemoteNoteDataService
|
||||
include ResponseDataHelper
|
||||
|
||||
NOTE_API_PATH = '/api/1/msf/note'
|
||||
NOTE_API_PATH = '/api/v1/notes'
|
||||
|
||||
def report_note(opts)
|
||||
self.post_data_async(NOTE_API_PATH, opts)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module RemoteServiceDataService
|
||||
SERVICE_API_PATH = '/api/1/msf/service'
|
||||
SERVICE_API_PATH = '/api/v1/services'
|
||||
|
||||
def report_service(opts)
|
||||
self.post_data_async(SERVICE_API_PATH, opts)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module RemoteSessionDataService
|
||||
|
||||
SESSION_API_PATH = '/api/1/msf/session'
|
||||
SESSION_API_PATH = '/api/v1/sessions'
|
||||
SESSION_MDM_CLASS = 'Mdm::Session'
|
||||
|
||||
def report_session(opts)
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
|
|||
module RemoteSessionEventDataService
|
||||
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'
|
||||
|
||||
def session_events(opts = {})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module RemoteVulnDataService
|
||||
|
||||
VULN_API_PATH = '/api/1/msf/vuln'
|
||||
VULN_API_PATH = '/api/v1/vulns'
|
||||
def report_vuln(opts)
|
||||
self.post_data_async(VULN_API_PATH, opts)
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
|
|||
module RemoteWebDataService
|
||||
include ResponseDataHelper
|
||||
|
||||
WEB_API_PATH = '/api/1/msf/web'
|
||||
WEB_API_PATH = '/api/v1/webs'
|
||||
|
||||
def report_web_site(opts)
|
||||
self.post_data_async(WEB_API_PATH, opts)
|
||||
|
|
|
@ -3,8 +3,9 @@ require 'metasploit/framework/data_service/remote/http/response_data_helper'
|
|||
module RemoteWorkspaceDataService
|
||||
include ResponseDataHelper
|
||||
|
||||
WORKSPACE_COUNTS_API_PATH = '/api/1/msf/workspace/counts'
|
||||
WORKSPACE_API_PATH = '/api/1/msf/workspace'
|
||||
# TODO: should counts be a flag in query data for the workspaces resource?
|
||||
WORKSPACE_COUNTS_API_PATH = '/api/v1/workspaces/counts'
|
||||
WORKSPACE_API_PATH = '/api/v1/workspaces'
|
||||
WORKSPACE_MDM_CLASS = 'Mdm::Workspace'
|
||||
DEFAULT_WORKSPACE_NAME = 'default'
|
||||
|
||||
|
@ -38,7 +39,7 @@ module RemoteWorkspaceDataService
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
#########
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module CredentialServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/credential'
|
||||
'/api/v1/credentials'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module EventServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/event'
|
||||
'/api/v1/events'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module ExploitServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/exploit'
|
||||
'/api/v1/exploits'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module HostServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/host'
|
||||
'/api/v1/hosts'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module LootServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/loot'
|
||||
'/api/v1/loots'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module NmapServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/nmap'
|
||||
'/api/v1/nmaps'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module NoteServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/note'
|
||||
'/api/v1/notes'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module OnlineTestServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/online'
|
||||
'/api/v1/online'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module ServiceServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/service'
|
||||
'/api/v1/services'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module SessionEventServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/session_event'
|
||||
'/api/v1/session-events'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module SessionServlet
|
||||
def self.api_path
|
||||
'/api/1/msf/session'
|
||||
'/api/v1/sessions'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module VulnServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/vuln'
|
||||
'/api/v1/vulns'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module WebServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/web'
|
||||
'/api/v1/webs'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module WorkspaceServlet
|
||||
|
||||
def self.api_path
|
||||
'/api/1/msf/workspace'
|
||||
'/api/v1/workspaces'
|
||||
end
|
||||
|
||||
def self.registered(app)
|
||||
|
|
Loading…
Reference in New Issue