Nexpose plugin - Query nexpose via v3 api when doing scan

This commit is contained in:
Chris Pomfret
2025-11-24 12:15:55 +00:00
parent d05f50c802
commit f842bb7169
3 changed files with 75 additions and 24 deletions
+8
View File
@@ -79,6 +79,7 @@ PATH
recog
redcarpet
reline
rest-client
rex-arch
rex-bin_tools
rex-core
@@ -285,6 +286,7 @@ GEM
hrr_rb_ssh-ed25519 (0.4.2)
ed25519 (~> 1.2)
hrr_rb_ssh (>= 0.4)
http-accept (1.7.0)
http-cookie (1.0.8)
domain_name (~> 0.5)
http_parser.rb (0.8.0)
@@ -388,6 +390,7 @@ GEM
net-smtp (0.5.1)
net-protocol
net-ssh (7.3.0)
netrc (0.11.0)
network_interface (0.0.4)
nexpose (7.3.0)
nio4r (2.7.4)
@@ -478,6 +481,11 @@ GEM
reline (0.6.2)
io-console (~> 0.5)
require_all (3.0.0)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rex-arch (0.1.18)
rex-text
rex-bin_tools (0.1.10)
+1
View File
@@ -157,6 +157,7 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'net-ldap'
spec.add_runtime_dependency 'net-smtp'
spec.add_runtime_dependency 'net-sftp'
spec.add_runtime_dependency 'rest-client'
spec.add_runtime_dependency 'winrm'
# Pinned to avoid WinRM warnings: https://github.com/WinRb/WinRM/issues/355 - if bumping verify windows/winrm/winrm_script_exec works against metasploitable with vagrant/vagrant creds
spec.add_runtime_dependency 'rexml', '3.4.1'
+65 -23
View File
@@ -1,5 +1,6 @@
require 'English'
require 'nexpose'
require 'rest-client'
module Msf
Nexpose_yaml = "#{Msf::Config.config_directory}/nexpose.yaml".freeze # location of the nexpose.yml containing saved nexpose creds
@@ -391,9 +392,15 @@ module Msf
user = Regexp.last_match(2)
pass = Regexp.last_match(3)
msfid = Time.now.to_i
newcreds = Nexpose::SiteCredentials.for_service("Metasploit Site Credential #{msfid}", nil, nil, nil, nil, type)
newcreds.user_name = user
newcreds.password = pass
newcreds = {
"name": "Metasploit Site Credential #{msfid}",
"enabled": true,
"account": {
"service": type,
"username": user,
"password": pass,
},
}
opt_credentials << newcreds
else
print_error("Unrecognized Nexpose scan credentials: #{val}")
@@ -486,19 +493,35 @@ module Msf
msfid = Time.now.to_i
# Create a temporary site
site = Nexpose::Site.new(nil, opt_template)
site.name = "Metasploit-#{msfid}"
site.description = 'Autocreated by the Metasploit Framework'
site.included_addresses = queue
site.site_credentials = opt_credentials
site.save(@nsc)
create_site_payload = {
description: "Autocreated by the Metasploit Framework'",
scanTemplateId: opt_template,
name: "Metasploit-#{msfid}",
scan: {
assets: {
includedTargets: {
addresses: queue,
},
},
},
}
print_status(" >> Created temporary site ##{site.id}") if opt_verbose
response = post_v3(resource: "sites", payload: create_site_payload)
@site_id = response["id"]
print_status(" >> Created temporary site ##{@site_id}") if opt_verbose
opt_credentials.each do |credential|
response = post_v3(resource: "sites/#{@site_id}/site_credentials", payload: credential)
credential_id = response["id"]
print_status(" >> Created site credential ##{credential_id}: #{credential['name']}")
end
report_formats = ['raw-xml-v2', 'ns-xml']
report_format = report_formats.shift
report = Nexpose::ReportConfig.build(@nsc, site.id, site.name, opt_template, report_format, true)
report = Nexpose::ReportConfig.build(@nsc, @site_id, create_site_payload[:name], opt_template, report_format, true)
report.delivery = Nexpose::Delivery.new(true)
begin
@@ -514,17 +537,8 @@ module Msf
print_status(" >> Created temporary report configuration ##{report.id}") if opt_verbose
# Run the scan
begin
res = site.scan(@nsc)
rescue Nexpose::APIError => e
nexpose_error_message = e.message
nexpose_error_message.gsub!(/NexposeAPI: Action failed: /, '')
print_error nexpose_error_message.to_s
return
end
sid = res.id
response = post_v3(resource: "sites/#{@site_id}/scans", payload: { name: opt_template })
sid = response["id"]
print_status(" >> Scan has been launched with ID ##{sid}") if opt_verbose
@@ -584,7 +598,7 @@ module Msf
end
print_status(' >> Deleting the temporary site and report...') if opt_verbose
begin
@nsc.delete_site(site.id)
@nsc.delete_site(@site_id)
rescue ::Nexpose::APIError => e
print_status(" >> Deletion of temporary site and report failed: #{e.inspect}")
end
@@ -648,6 +662,34 @@ module Msf
end
end
def post_v3(resource: "", payload: {})
response = RestClient::Request.execute(
verify_ssl: false,
method: :post,
url: nexpose_v3_url(resource: resource),
payload: payload.to_json,
headers: nexpose_shared_headers
)
dlog "Response body: #{response.body}"
JSON.parse(response.body)
end
def nexpose_v3_url(resource: "")
"https://#{@host}:#{@port}/api/3/#{resource}"
end
def nexpose_basic_auth_credentials
"Basic #{Base64::encode64([@user, @pass].join(':'))}"
end
def nexpose_shared_headers
{
content_type: :json,
accept: :json,
Authorization: nexpose_basic_auth_credentials,
}
end
end
#