diff --git a/lib/metasploit/framework/data_service/proxy/service_data_proxy.rb b/lib/metasploit/framework/data_service/proxy/service_data_proxy.rb index 33715bf2c8..e82272145b 100644 --- a/lib/metasploit/framework/data_service/proxy/service_data_proxy.rb +++ b/lib/metasploit/framework/data_service/proxy/service_data_proxy.rb @@ -29,6 +29,15 @@ module ServiceDataProxy end end + def update_service(opts) + begin + data_service = self.get_data_service() + data_service.update_service(opts) + rescue Exception => e + self.log_error(e, 'Problem updating service') + end + end + def delete_service(opts) begin data_service = self.get_data_service() diff --git a/lib/metasploit/framework/data_service/remote/http/remote_service_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_service_data_service.rb index 0beb13aecb..452f2cb836 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_service_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_service_data_service.rb @@ -10,6 +10,15 @@ module RemoteServiceDataService json_to_mdm_object(self.post_data(SERVICE_API_PATH, opts), SERVICE_MDM_CLASS).first end + def update_service(opts) + path = SERVICE_API_PATH + if opts && opts[:id] + id = opts.delete(:id) + path = "#{SERVICE_API_PATH}/#{id}" + end + json_to_mdm_object(self.put_data(path, opts), SERVICE_MDM_CLASS) + end + def delete_service(opts) json_to_mdm_object(self.delete_data(SERVICE_API_PATH, opts), SERVICE_MDM_CLASS) end diff --git a/lib/msf/core/db_manager/http/servlet/service_servlet.rb b/lib/msf/core/db_manager/http/servlet/service_servlet.rb index 1c77fa6948..51fdf24593 100644 --- a/lib/msf/core/db_manager/http/servlet/service_servlet.rb +++ b/lib/msf/core/db_manager/http/servlet/service_servlet.rb @@ -4,9 +4,14 @@ module ServiceServlet '/api/v1/services' end + def self.api_path_with_id + "#{ServiceServlet.api_path}/?:id?" + end + def self.registered(app) app.get ServiceServlet.api_path, &get_services app.post ServiceServlet.api_path, &report_service + app.put ServiceServlet.api_path_with_id, &update_service app.delete ServiceServlet.api_path, &delete_service end @@ -18,7 +23,7 @@ module ServiceServlet lambda { begin opts = params.symbolize_keys - data = get_db().services(opts) + data = get_db.services(opts) set_json_response(data) rescue Exception => e set_error_on_response(e) @@ -28,16 +33,30 @@ module ServiceServlet def self.report_service lambda { - job = lambda { |opts| get_db().report_service(opts) } + job = lambda { |opts| get_db.report_service(opts) } exec_report_job(request, &job) } end + def self.update_service + lambda { + begin + opts = parse_json_request(request, false) + tmp_params = params.symbolize_keys + opts[:id] = tmp_params[:id] if tmp_params[:id] + data = get_db.update_service(opts) + set_json_response(data) + rescue Exception => e + set_error_on_response(e) + end + } + end + def self.delete_service lambda { begin opts = parse_json_request(request, false) - data = get_db().delete_service(opts) + data = get_db.delete_service(opts) set_json_response(data) rescue Exception => e set_error_on_response(e) diff --git a/lib/msf/core/db_manager/service.rb b/lib/msf/core/db_manager/service.rb index e2324a3474..a5db9c2c59 100644 --- a/lib/msf/core/db_manager/service.rb +++ b/lib/msf/core/db_manager/service.rb @@ -151,4 +151,16 @@ module Msf::DBManager::Service wspace.services.includes(:host).where(conditions).order("hosts.address, port") } end + + def update_service(opts) + wspace = opts.delete(:workspace) || workspace + if wspace.kind_of? String + wspace = find_workspace(wspace) + end + + ::ActiveRecord::Base.connection_pool.with_connection { + id = opts.delete(:id) + Mdm::Service.update(id, opts) + } + end end diff --git a/lib/msf/ui/console/command_dispatcher/db.rb b/lib/msf/ui/console/command_dispatcher/db.rb index e8b258420e..d277159d22 100644 --- a/lib/msf/ui/console/command_dispatcher/db.rb +++ b/lib/msf/ui/console/command_dispatcher/db.rb @@ -587,6 +587,8 @@ module Msf mode = :add when '-d','--delete' mode = :delete + when '-U', '--update' + mode = :update when '-u','--up' onlyup = true when '-c' @@ -645,14 +647,15 @@ module Msf print_line " -d,--delete Delete the services instead of searching" print_line " -c Only show the given columns" print_line " -h,--help Show this help information" - print_line " -s Search for a list of service names" - print_line " -p Search for a list of ports" + print_line " -s Name of the service to add" + print_line " -p Port number of the service being added" print_line " -r Only show [tcp|udp] services" print_line " -u,--up Only show services which are up" print_line " -o Send output to a file in csv format" print_line " -O Order rows by specified column number" print_line " -R,--rhosts Set RHOSTS from the results of the search" print_line " -S,--search Search string to filter by" + print_line " -U,--update Update data for existing service" print_line print_line "Available columns: #{default_columns.join(", ")}" print_line @@ -712,7 +715,7 @@ module Msf each_host_range_chunk(host_ranges) do |host_search| break if !host_search.nil? && host_search.empty? - framework.db.services(framework.db.workspace, onlyup, proto, host_search, ports, names).each do |service| + framework.db.services(framework.db.workspace, onlyup, nil, host_search, nil, nil).each do |service| host = service.host if search_term @@ -723,6 +726,13 @@ module Msf end matched_service_ids << service.id + if mode == :update + service.name = names.first if names + service.proto = proto if proto + service.port = ports.first if ports + framework.db.update_service(service.as_json.symbolize_keys) + end + columns = [host.address] + col_names.map { |n| service[n].to_s || "" } tbl << columns if set_rhosts