add latest nessus plugin patches from Zate, fixes #2704

git-svn-id: file:///home/svn/framework3/trunk@10685 4d416f70-5f16-0410-b530-b9f4589650da
unstable
James Lee 2010-10-14 18:54:35 +00:00
parent e9df13c761
commit 238242ecb9
4 changed files with 623 additions and 316 deletions

View File

@ -2,7 +2,7 @@ require 'rex/parser/nmap_xml'
require 'rex/parser/nexpose_xml'
require 'rex/parser/retina_xml'
require 'rex/parser/netsparker_xml'
require 'rex/parser/nessus_xml'
require 'rex/socket'
require 'zip'
require 'uri'
@ -3540,70 +3540,96 @@ class DBManager
data = args[:data]
wspace = args[:wspace] || workspace
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
doc = rexmlify(data)
doc.elements.each('/NessusClientData_v2/Report/ReportHost') do |host|
# if Nessus resovled the host, its host-ip tag should be set
# otherwise, fall back to the name attribute which would
# logically need to be an IP address
begin
addr = host.elements["HostProperties/tag[@name='host-ip']"].text
rescue
addr = host.attribute("name").value
end
#@host = {
#'hname' => nil,
#'addr' => nil,
#'mac' => nil,
#'os' => nil,
#'ports' => [ 'port' => { 'port' => nil,
# 'svc_name' => nil,
# 'proto' => nil,
# 'severity' => nil,
# 'nasl' => nil,
# 'description' => nil,
# 'cve' => [],
# 'bid' => [],
# 'xref' => []
# }
# ]
#}
parser = Rex::Parser::NessusXMLStreamParser.new
parser.on_found_host = Proc.new { |host|
addr = host['addr'] || host['hname']
next unless ipv4_validator(addr) # Catches SCAN-ERROR, among others.
if bl.include? addr
next
else
yield(:address,addr) if block
end
os = host.elements["HostProperties/tag[@name='operating-system']"]
os = host['os']
yield(:os,os) if block
if os
report_note(
:workspace => wspace,
:host => addr,
:type => 'host.os.nessus_fingerprint',
:data => {
:os => os.text.to_s.strip
:os => os.to_s.strip
}
)
end
hname = host.elements["HostProperties/tag[@name='host-fqdn']"]
hname = host['hname']
if hname
report_host(
:workspace => wspace,
:host => addr,
:name => hname.text.to_s.strip
:name => hname.to_s.strip
)
end
mac = host.elements["HostProperties/tag[@name='mac-address']"]
mac = host['mac']
if mac
report_host(
:workspace => wspace,
:host => addr,
:mac => mac.text.to_s.strip.upcase
:mac => mac.to_s.strip.upcase
)
end
host.elements.each('ReportItem') do |item|
nasl = item.attribute('pluginID').value
port = item.attribute('port').value
proto = item.attribute('protocol').value
name = item.attribute('svc_name').value
severity = item.attribute('severity').value
description = item.elements['plugin_output']
cve = item.elements['cve']
bid = item.elements['bid']
xref = item.elements['xref']
handle_nessus_v2(wspace, addr, port, proto, name, nasl, severity, description, cve, bid, xref)
host['ports'].each do |item|
next if item['port'] == 0
msf = nil
nasl = item['nasl'].to_s
port = item['port'].to_s
proto = item['proto'] || "tcp"
name = item['svc_name']
severity = item['severity']
description = item['description']
cve = item['cve']
bid = item['bid']
xref = item['xref']
msf = item['msf']
yield(:port,port) if block
handle_nessus_v2(wspace, addr, port, proto, hname, nasl, severity, description, cve, bid, xref, msf)
end
end
yield(:end,hname) if block
}
REXML::Document.parse_stream(data, parser)
end
#
@ -3898,7 +3924,7 @@ protected
# NESSUS v2 file format has a dramatically different layout
# for ReportItem data
#
def handle_nessus_v2(wspace,addr,port,proto,name,nasl,severity,description,cve,bid,xref)
def handle_nessus_v2(wspace,addr,port,proto,name,nasl,severity,description,cve,bid,xref,msf)
report_host(:workspace => wspace, :host => addr, :state => Msf::HostState::Alive)
@ -3915,27 +3941,30 @@ protected
refs = []
cve.collect do |r|
cve.each do |r|
r.to_s.gsub!(/C(VE|AN)\-/, '')
refs.push('CVE-' + r.to_s)
end if cve
bid.collect do |r|
bid.each do |r|
refs.push('BID-' + r.to_s)
end if bid
xref.collect do |r|
xref.each do |r|
ref_id, ref_val = r.to_s.split(':')
ref_val ? refs.push(ref_id + '-' + ref_val) : refs.push(ref_id)
end if xref
msfref = "MSF-" << msf if msf
refs.push msfref if msfref
nss = 'NSS-' + nasl
vuln = {
:workspace => wspace,
:host => addr,
:name => nss,
:info => description ? description.text : "",
:info => description ? description : "",
:refs => refs
}
@ -3947,6 +3976,7 @@ protected
report_vuln(vuln)
end
#
# Qualys report parsing/handling
#

View File

@ -104,7 +104,8 @@ module NessusXMLRPC
begin
status = docxml.root.elements['status'].text
rescue
print_error("Error connecting/logging to the server!")
puts("Error connecting/logging to the server!")
return
end
if status == "OK"
return docxml
@ -129,7 +130,7 @@ module NessusXMLRPC
begin
response = @https.request( request )
rescue
print_error("error connecting to server: #{@nurl} with URI: #{uri}")
puts("error connecting to server: #{@nurl} with URI: #{uri}")
exit
end
# puts response.body
@ -188,7 +189,11 @@ module NessusXMLRPC
# returns: array of uids of active scans
def scan_list_uids
post= { "token" => @token }
docxml = nil
docxml=nessus_request('scan/list', post)
if docxml.nil?
return
end
uuids=Array.new
docxml.root.elements['contents'].elements['scans'].elements['scanList'].each_element('//scan') {|scan| uuids.push(scan.elements['uuid'].text) }
return uuids
@ -199,7 +204,11 @@ module NessusXMLRPC
# returns: array of hash of active scans
def scan_list_hash
post= { "token" => @token }
docxml = nil
docxml=nessus_request('scan/list', post)
if docxml.nil?
return
end
scans=Array.new
docxml.root.elements['contents'].elements['scans'].elements['scanList'].each_element('//scan') {|scan|
entry=Hash.new
@ -214,49 +223,54 @@ module NessusXMLRPC
}
return scans
end
def template_list_hash
post= { "token" => @token }
docxml = nessus_request('scan/list', post)
templates = Array.new
docxml.elements.each('/reply/contents/templates/template') { |template|
entry=Hash.new
entry['name']=template.elements['name'].text if template.elements['name']
entry['pid']=template.elements['policy_id'].text if template.elements['policy_id']
entry['rname']=template.elements['readableName'].text if template.elements['readableName']
entry['owner']=template.elements['owner'].text if template.elements['owner']
entry['target']=template.elements['target'].text if template.elements['target']
templates.push(entry)
}
return templates
end
# get hash of policies
#
# returns: array of hash of policies
def policy_list_hash
post= { "token" => @token }
docxml=nessus_request('policy/list', post)
docxml = nil
docxml=nessus_request('scan/list', post)
if docxml.nil?
return
end
policies=Array.new
docxml.elements.each('/reply/contents/policies/policy') { |policy|
docxml.elements.each('/reply/contents/policies/policies/policy') { |policy|
entry=Hash.new
entry['id']=policy.elements['policyID'].text
entry['name']=policy.elements['policyName'].text
entry['owner']=policy.elements['policyOwner'].text
entry['vis']=policy.elements['visibility'].text
entry['comment']=policy.elements['policyComments'].text
policies.push(entry)
}
return policies
end
# get hash of templates
#
# returns: array of hash of templates
def template_list_hash
post= { "token" => @token }
docxml=nessus_request('scan/list', post)
scans=Array.new
docxml.root.elements['contents'].elements['scans'].elements['scanList'].each_element('//scan') {|scan|
entry=Hash.new
entry['id']=scan.elements['uuid'].text if scan.elements['uuid']
entry['name']=scan.elements['readableName'].text if scan.elements['readableName']
entry['current']=scan.elements['completion_current'].text if scan.elements['completion_current']
entry['total']=scan.elements['completion_total'].text if scan.elements['completion_total']
scans.push(entry)
}
return scans
end
# get hash of templates
# get hash of reportss
#
# returns: array of hash of templates
def report_list_hash
post= { "token" => @token }
docxml = nil
docxml=nessus_request('report/list', post)
if docxml.nil?
return
end
#puts docxml
reports=Array.new
docxml.root.elements['contents'].elements['reports'].each_element('//report') {|report|
@ -275,7 +289,11 @@ module NessusXMLRPC
# returns: policyID
def policy_get_id(textname)
post= { "token" => @token }
docxml = nil
docxml=nessus_request('policy/list', post)
if docxml.nil?
return
end
docxml.root.elements['contents'].elements['policies'].each_element('//policy') {|policy|
if policy.elements['policyName'].text == textname
return policy.elements['policyID'].text
@ -289,7 +307,11 @@ module NessusXMLRPC
# returns: policyID, policyName
def policy_get_first
post= { "token" => @token }
docxml = nil
docxml=nessus_request('policy/list', post)
if docxml.nil?
return
end
docxml.root.elements['contents'].elements['policies'].each_element('//policy') {|policy|
return policy.elements['policyID'].text, policy.elements['policyName'].text
}
@ -300,7 +322,11 @@ module NessusXMLRPC
# returns: array of all policy uids
def policy_list_uids
post= { "token" => @token }
docxml = nil
docxml=nessus_request('policy/list', post)
if docxml.nil?
return
end
pids=Array.new
docxml.root.elements['contents'].elements['policies'].each_element('//policy') { |policy|
pids.push(policy.elements['policyID'].text) }
@ -310,7 +336,11 @@ module NessusXMLRPC
# stop scan identified by scan_uuid
def scan_stop(uuid)
post= { "token" => @token, "scan_uuid" => uuid }
docxml = nil
docxml=nessus_request('scan/stop', post)
if docxml.nil?
return
end
return docxml
end
@ -333,7 +363,11 @@ module NessusXMLRPC
# pause scan identified by scan_uuid
def scan_pause(uuid)
post= { "token" => @token, "scan_uuid" => uuid }
docxml = nil
docxml=nessus_request('scan/pause', post)
if docxml.nil?
return
end
return docxml
end
@ -356,7 +390,11 @@ module NessusXMLRPC
# remove scan identified by uuid
def scan_resume(uuid)
post= { "token" => @token, "scan_uuid" => uuid }
docxml = nil
docxml=nessus_request('scan/resume', post)
if docxml.nil?
return
end
return docxml
end
# resume all active scans
@ -378,7 +416,11 @@ module NessusXMLRPC
# check status of scan identified by uuid
def scan_status(uuid)
post= { "token" => @token, "report" => uuid }
docxml = nil
docxml=nessus_request('report/list', post)
if docxml.nil?
return
end
docxml.root.elements['contents'].elements['reports'].each_element('//report') { |report|
if report.elements['name'].text == uuid
return (report.elements['status'].text)
@ -402,7 +444,11 @@ module NessusXMLRPC
# returns: XML file of report (nessus v2 format)
def report_file_download(report)
post= { "token" => @token, "report" => report }
file = nil
file=nessus_http_request('file/report/download', post)
if file.nil?
return
end
return file
end
@ -411,14 +457,20 @@ module NessusXMLRPC
# returns: XML file of report (nessus v1 format)
def report_file1_download(report)
post= { "token" => @token, "report" => report, "v1" => "true" }
file=nessus_http_request('file/report/download', post)
return file
end
# delete report by report ID
def report_delete(id)
post= { "token" => @token, "report" => id }
docxml = nil
docxml=nessus_request('report/delete', post)
if docxml.nil?
return
end
return docxml
end
@ -427,7 +479,11 @@ module NessusXMLRPC
# returns: array of names
def policy_list_names
post= { "token" => @token }
docxml = nil
docxml=nessus_request('policy/list', post)
if docxml.nil?
return
end
list = Array.new
docxml.root.elements['contents'].elements['policies'].each_element('//policy') {|policy|
list.push policy.elements['policyName'].text
@ -449,7 +505,11 @@ module NessusXMLRPC
# scanprogressTotal
def report_hosts(report_id)
post= { "token" => @token, "report" => report_id }
docxml = nil
docxml=nessus_request('report/hosts', post)
if docxml.nil?
return
end
hosts=Array.new
docxml.elements.each('/reply/contents/hostList/host') do |host|
entry=Hash.new
@ -472,7 +532,11 @@ module NessusXMLRPC
def report_host_ports(report_id,host)
post= { "token" => @token, "report" => report_id, "hostname" => host }
docxml = nil
docxml=nessus_request('report/ports', post)
if docxml.nil?
return
end
ports=Array.new
docxml.elements.each('/reply/contents/portList/port') do |port|
entry=Hash.new
@ -495,26 +559,42 @@ module NessusXMLRPC
def report_host_port_details(report_id,host,port,protocol)
post= { "token" => @token, "report" => report_id, "hostname" => host, "port" => port, "protocol" => protocol }
docxml = nil
docxml=nessus_request('report/details', post)
if docxml.nil?
return
end
reportitems=Array.new
docxml.elements.each('/reply/contents/portDetails/ReportItem') do |rpt|
entry=Hash.new
cve = Array.new
bid = Array.new
entry['port'] = rpt.elements['port'].text if rpt.elements['port']
entry['severity'] = rpt.elements['severity'].text if rpt.elements['severity']
entry['pluginID'] = rpt.elements['pluginID'].text if rpt.elements['pluginID']
entry['pluginName'] = rpt.elements['pluginName'].text if rpt.elements['pluginName']
entry['cvss_base_score'] = rpt.elements['data'].elements['cvss_base_score'].text if rpt.elements['data'].elements['cvss_base_score']
entry['exploit_available'] = rpt.elements['data'].elements['exploit_available'].text if rpt.elements['data'].elements['exploit_available']
entry['cve'] = rpt.elements['data'].elements['cve'].text if rpt.elements['data'].elements['cve']
if rpt.elements['data'].elements['cve']
rpt.elements['data'].elements['cve'].each do |x|
cve.push rpt.elements['data'].elements['cve'].text
end
end
entry['cve'] = cve if cve
entry['risk_factor'] = rpt.elements['data'].elements['risk_factor'].text if rpt.elements['data'].elements['risk_factor']
entry['cvss_vector'] = rpt.elements['data'].elements['cvss_vector'].text if rpt.elements['data'].elements['cvss_vector']
#entry['solution'] = rpt.elements['data/solution'].text #not important right now
#entry['description'] = rpt.elements['data/description'].text #not important right now
#entry['synopsis'] = rpt.elements['data/synopsis'].text #not important right now
#entry['see_also'] = rpt.elements['data/see_also'].text # multiple of these
#entry['bid'] = rpt.elements['data/bid'].text multiple of these
#entry['xref'] = rpt.elements['data/xref'].text # multiple of these
#entry['plugin_output'] = rpt.elements['data/plugin_output'].text #not important right now
entry['solution'] = rpt.elements['data'].elements['solution'].text if rpt.elements['data'].elements['solution']
entry['description'] = rpt.elements['data'].elements['description'].text if rpt.elements['data'].elements['description']
entry['synopsis'] = rpt.elements['data'].elements['synopsis'].text if rpt.elements['data'].elements['synopsis']
entry['see_also'] = rpt.elements['data'].elements['see_also'].text if rpt.elements['data'].elements['see_also']
if rpt.elements['data'].elements['bid']
rpt.elements['data'].elements['bid'].each do |y|
bid.push rpt.elements['data'].elements['bid'].text
end
end
entry['bid'] = bid if bid
#entry['xref'] = rpt.elements['data'].elements['xref'].text # multiple of these
entry['plugin_output'] = rpt.elements['data'].elements['plugin_output'].text if rpt.elements['data'].elements['plugin_output']
reportitems.push(entry)
end
return reportitems
@ -523,23 +603,31 @@ module NessusXMLRPC
# get host details for particular host identified by report id
#
# returns: severity, current, total
def report_get_host(report_id,host)
def report_get_host(report_id,hostname)
post= { "token" => @token, "report" => report_id }
docxml = nil
docxml=nessus_request('report/hosts', post)
docxml.root.elements['contents'].elements['hostList'].each_element('//host') { |host|
if host.elements['hostname'].text == host
if docxml.nil?
return
end
docxml.elements.each('/reply/contents/hostList/host') do |host|
if host.elements['hostname'].text == hostname
severity = host.elements['severity'].text
current = host.elements['scanProgressCurrent'].text
total = host.elements['scanProgressTotal'].text
return severity, current, total
end
}
end
end
# gets a list of each plugin family and the number of plugins for that family.
def plugins_list
post= { "token" => @token }
docxml = nil
docxml=nessus_request('plugins/list', post)
if docxml.nil?
return
end
plugins=Array.new
docxml.root.elements['contents'].elements['pluginFamilyList'].each_element('//family') { |plugin|
entry=Hash.new
@ -553,7 +641,11 @@ module NessusXMLRPC
#returns a list of users, if they are an admin and their last login time.
def users_list
post= { "token" => @token }
docxml = nil
docxml=nessus_request('users/list', post)
if docxml.nil?
return
end
users=Array.new
docxml.root.elements['contents'].elements['users'].each_element('//user') { |user|
entry=Hash.new
@ -563,14 +655,16 @@ module NessusXMLRPC
users.push(entry)
}
return users
end
# returns basic data about the feed type and versions.
def feed
post = { "token" => @token }
docxml = nil
docxml = nessus_request('feed', post)
if docxml.nil?
return
end
feed = docxml.root.elements['contents'].elements['feed'].text
version = docxml.root.elements['contents'].elements['server_version'].text
web_version = docxml.root.elements['contents'].elements['web_server_version'].text
@ -579,25 +673,41 @@ module NessusXMLRPC
def user_add(user,pass)
post= { "token" => @token, "login" => user, "password" => pass }
docxml = nil
docxml = nessus_request('users/add', post)
if docxml.nil?
return
end
return docxml
end
def user_del(user)
post= { "token" => @token, "login" => user }
docxml = nil
docxml = nessus_request('users/delete', post)
if docxml.nil?
return
end
return docxml
end
def user_pass(user,pass)
post= { "token" => @token, "login" => user, "password" => pass }
docxml = nil
docxml = nessus_request('users/chpasswd', post)
if docxml.nil?
return
end
return docxml
end
def plugin_family(fam)
post = { "token" => @token, "family" => fam }
docxml = nil
docxml = nessus_request('plugins/list/family', post)
if docxml.nil?
return
end
family=Array.new
docxml.elements.each('/reply/contents/pluginList/plugin') { |plugin|
entry=Hash.new
@ -611,21 +721,31 @@ module NessusXMLRPC
def policy_del(pid)
post= { "token" => @token, "policy_id" => pid }
docxml = nil
docxml = nessus_request('policy/delete', post)
if docxml.nil?
return
end
return docxml
end
def report_del(rid)
post= { "token" => @token, "report" => rid }
docxml = nil
docxml = nessus_request('report/delete', post)
if docxml.nil?
return
end
return docxml
end
def plugin_detail(pname)
post = { "token" => @token, "fname" => pname }
docxml = nil
docxml = nessus_request('plugins/description', post)
#return docxml
#details=Array.new
if docxml.nil?
return
end
entry=Hash.new
docxml.elements.each('reply/contents/pluginDescription') { |desc|
entry['name'] = desc.elements['pluginName'].text
@ -646,14 +766,16 @@ module NessusXMLRPC
entry['cvss_base_score'] = attr.elements['cvss_base_score'].text if attr.elements['cvss_base_score']
}
}
return entry
end
def server_prefs
post= { "token" => @token }
docxml = nil
docxml = nessus_request('preferences/list', post)
if docxml.nil?
return
end
prefs = Array.new
docxml.elements.each('/reply/contents/ServerPreferences/preference') { |pref|
entry=Hash.new
@ -666,7 +788,11 @@ module NessusXMLRPC
def plugin_prefs
post= { "token" => @token }
docxml = nil
docxml = nessus_request('plugins/preferences', post)
if docxml.nil?
return
end
prefs = Array.new
docxml.elements.each('/reply/contents/PluginsPreferences/item') { |pref|
entry=Hash.new

View File

@ -0,0 +1,129 @@
require 'rexml/document'
require 'rex/ui'
module Rex
module Parser
class NessusXMLStreamParser
attr_accessor :on_found_host
def initialize(&block)
reset_state
on_found_host = block if block
end
def reset_state
@host = {'hname' => nil, 'addr' => nil, 'mac' => nil, 'os' => nil, 'ports' => [
'port' => {'port' => nil, 'svc_name' => nil, 'proto' => nil, 'severity' => nil,
'nasl' => nil, 'description' => nil, 'cve' => [], 'bid' => [], 'xref' => [] } ] }
@state = :generic_state
end
def tag_start(name, attributes)
case name
when "tag"
if attributes['name'] == "mac-address"
@state = :is_mac
end
if attributes['name'] == "host-fqdn"
@state = :is_fqdn
end
if attributes['name'] == "ip-addr"
@state = :is_ip
end
if attributes['name'] == "host-ip"
@state = :is_ip
end
if attributes['name'] == "operating-system"
@state = :is_os
end
when "ReportHost"
@host['hname'] = attributes['name']
when "ReportItem"
@cve = Array.new
@bid = Array.new
@xref = Array.new
@x = Hash.new
@x['nasl'] = attributes['pluginID']
@x['port'] = attributes['port']
@x['proto'] = attributes['protocol']
@x['svc_name'] = attributes['svc_name']
@x['severity'] = attributes['severity']
when "description"
@state = :is_desc
when "cve"
@state = :is_cve
when "bid"
@state = :is_bid
when "xref"
@state = :is_xref
when "solution"
@state = :is_solution
when "metasploit_name"
@state = :msf
end
end
def text(str)
case @state
when :is_fqdn
@host['hname'] = str
when :is_ip
@host['addr'] = str
when :is_os
@host['os'] = str
when :is_mac
@host['mac'] = str
when :is_desc
@x['description'] = str
when :is_cve
@cve.push str
when :is_bid
@bid.push str
when :is_xref
@xref.push str
when :msf
#this requires that the user has run nessus_exploits to build the index. Not ready for primetime.
#regex = Regexp.new(str, true, 'n')
#File.open("xindex", "r") do |m|
# while line = m.gets
# if (line.match(regex))
# exp = line.split("|").first
# @x['msf'] = exp
# end
# end
#end
end
end
def tag_end(name)
case name
when "ReportHost"
on_found_host.call(@host) if on_found_host
reset_state
when "ReportItem"
@x['cve'] = @cve
@x['bid'] = @bid
@x['xref'] = @xref
@host['ports'].push @x
end
@state = :generic_state
end
# We don't need these methods, but they're necessary to keep REXML happy
#
def xmldecl(version, encoding, standalone); end
def cdata; end
def comment(str); end
def instruction(name, instruction); end
def attlist; end
end
end
end

View File

@ -51,17 +51,46 @@ module Msf
"nessus_plugin_list" => "Displays each plugin family and the number of plugins",
"nessus_plugin_prefs" => "Display Plugin Prefs",
"nessus_policy_list" => "List all polciies",
#"nessus_policy_new" => "Save new policy"
"nessus_policy_del" => "Delete a policy",
#"nessus_policy_dupe" => "Duplicate a policy"
#"nessus_policy_rename" => "Rename a policy"
"nessus_find_targets" => "Try to find vulnerable targets from a report"
#"nessus_report_hosts_filter" => "Get list of hosts from a report with filter",
#"nessus_report_tags" => "Not sure what this does yet"
#"nessus_report_upload" => "Upload nessusv2 report"
"nessus_exploits" => "Generates a search index for exploits.",
"nessus_template_list" => "List all the templates on the server"
}
end
def cmd_nessus_exploits
#need to expand this to index all modules. What kind of info is needed?
#find a better place to keep the indexes and a way to name them
#put in version checking:
#check if exists and is a valid readable file (read first line)
#If the version line at start of current index doesnt match rev number of msf, rebuild index
start = Time.now
File.open("xindex", "w+") do |f|
framework.exploits.sort.each { |refname, mod|
stuff = ""
o = nil
begin
o = mod.new
rescue ::Exception
end
stuff << "#{refname}|#{o.name}|#{o.platform_to_s}|#{o.arch_to_s}"
next if not o
o.references.map do |x|
if !(x.ctx_id == "URL")
if (x.ctx_id == "MSB")
stuff << "|#{x.ctx_val}"
else
stuff << "|#{x.ctx_id}-#{x.ctx_val}"
end
end
end
stuff << "\n"
f.puts(stuff)
}
end
total = Time.now - start
print_status("It has taken : #{total} seconds to build the exploits search index")
end
def cmd_nessus_logout
@token = nil
@ -70,129 +99,61 @@ module Msf
end
def cmd_nessus_help(*args)
case args[0]
when "test"
puts "test"
when "nessus_connect"
print_status("%redYou must do this before any other commands.%clr")
print_status("Usage: ")
print_status(" nessus_connect username:password@hostname:port <ssl ok>")
print_status(" Example:> nessus_connect msf:msf@192.168.1.10:8834 ok")
print_status(" OR")
print_status(" nessus_connect username@hostname:port <ssl ok>")
print_status(" Example:> nessus_connect msf@192.168.1.10:8834 ok")
print_status(" OR")
print_status(" nessus_connect hostname:port <ssl ok>")
print_status(" Example:> nessus_connect 192.168.1.10:8834 ok")
print_status()
print_status("%bldusername%clr and %bldpassword%clr are the ones you use to login to the nessus web front end")
print_status("%bldhostname%clr can be an ip address or a dns name of the web front end.")
print_status("%bldport%clr is the standard that the nessus web front end runs on : 8834. This is NOT 1241.")
print_status("The \"ok\" on the end is important. It is a way of letting you")
print_status("know that nessus used a self signed cert and the risk that presents.")
when "nessus_report_list"
print_status("Usage: ")
print_status(" nessus_report_list")
print_status(" Example:> nessus_report_list")
print_status()
print_status("Generates a list of all reports visable to your user.")
when "nessus_report_get"
print_status("Usage: ")
print_status(" nessus_report_get <report id>")
print_status(" Example:> nessus_report_get f0eabba3-4065-7d54-5763-f191e98eb0f7f9f33db7e75a06ca")
print_status()
print_status("This command pulls the provided report from the nessus server in the nessusv2 format")
print_status("and parses it the same way db_import_nessus does. After it is parsed it will be")
print_status("available to commands such as db_hosts, db_vulns, db_services and db_autopwn.")
when "nessus_scan_status"
print_status("Usage: ")
print_status(" nessus_scan_status")
print_status(" Example:> nessus_scan_status")
print_status()
when "nessus_server_status"
print_status("Usage: ")
print_status(" nessus_server_status")
print_status(" Example:> nessus_server_status")
print_status()
else
tbl = Rex::Ui::Text::Table.new(
'Columns' =>
[
'Command',
'Help Text'
])
tbl << [ "Generic Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_connect", "Connect to a nessus server" ]
tbl << [ "nessus_logout", "Logout from the nessus server" ]
tbl << [ "nessus_help", "Listing of available nessus commands" ]
tbl << [ "nessus_server_status", "Check the status of your Nessus Server" ]
tbl << [ "nessus_admin", "Checks if user is an admin" ]
tbl << [ "nessus_server_feed", "Nessus Feed Type" ]
tbl << [ "nessus_find_targets", "Try to find vulnerable targets from a report" ]
tbl << [ "", ""]
tbl << [ "Reports Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_report_list", "List all Nessus reports" ]
tbl << [ "nessus_report_get", "Import a report from the nessus server in Nessus v2 format" ]
tbl << [ "nessus_report_hosts", "Get list of hosts from a report" ]
tbl << [ "nessus_report_host_ports", "Get list of open ports from a host from a report" ]
tbl << [ "nessus_report_host_detail", "Detail from a report item on a host" ]
tbl << [ "", ""]
tbl << [ "Scan Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_scan_new", "Create new Nessus Scan" ]
tbl << [ "nessus_scan_status", "List all currently running Nessus scans" ]
tbl << [ "nessus_scan_pause", "Pause a Nessus Scan" ]
tbl << [ "nessus_scan_pause_all", "Pause all Nessus Scans" ]
tbl << [ "nessus_scan_stop", "Stop a Nessus Scan" ]
tbl << [ "nessus_scan_stop_all", "Stop all Nessus Scans" ]
tbl << [ "nessus_scan_resume", "Resume a Nessus Scan" ]
tbl << [ "nessus_scan_resume_all", "Resume all Nessus Scans" ]
tbl << [ "", ""]
tbl << [ "Plugin Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_plugin_list", "Displays each plugin family and the number of plugins" ]
tbl << [ "nessus_plugin_family", "List plugins in a family" ]
tbl << [ "nessus_plugin_details", "List details of a particular plugin" ]
tbl << [ "", ""]
tbl << [ "User Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_user_list", "Show Nessus Users" ]
tbl << [ "nessus_user_add", "Add a new Nessus User" ]
tbl << [ "nessus_user_del", "Delete a Nessus User" ]
tbl << [ "nessus_user_passwd", "Change Nessus Users Password" ]
tbl << [ "", ""]
tbl << [ "Policy Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_policy_list", "List all polciies" ]
tbl << [ "nessus_policy_del", "Delete a policy" ]
#tbl << [ "nessus_server_prefs", "Display Server Prefs" ]
#tbl << [ "nessus_policy_new", "Save new policy" ]
#tbl << [ "nessus_policy_dupe", "Duplicate a policy" ]
#tbl << [ "nessus_policy_rename", "Rename a policy" ]
#tbl << [ "nessus_report_del", "Delete a report" ]
#tbl << [ "nessus_report_hosts_filter", "Get list of hosts from a report with filter" ]
#tbl << [ "nessus_report_tags", "Not sure what this does yet" ]
#tbl << [ "nessus_report_upload", "Upload nessusv2 report" ]
print_good("Nessus Help")
print_good("type nessus_help <command> for help with specific commands")
$stdout.puts "\n"
$stdout.puts tbl.to_s + "\n"
end
tbl = Rex::Ui::Text::Table.new(
'Columns' =>
[
'Command',
'Help Text'
])
tbl << [ "Generic Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_connect", "Connect to a nessus server" ]
tbl << [ "nessus_logout", "Logout from the nessus server" ]
tbl << [ "nessus_help", "Listing of available nessus commands" ]
tbl << [ "nessus_server_status", "Check the status of your Nessus Server" ]
tbl << [ "nessus_admin", "Checks if user is an admin" ]
tbl << [ "nessus_server_feed", "Nessus Feed Type" ]
tbl << [ "nessus_find_targets", "Try to find vulnerable targets from a report" ]
tbl << [ "nessus_server_prefs", "Display Server Prefs" ]
tbl << [ "", ""]
tbl << [ "Reports Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_report_list", "List all Nessus reports" ]
tbl << [ "nessus_report_get", "Import a report from the nessus server in Nessus v2 format" ]
tbl << [ "nessus_report_hosts", "Get list of hosts from a report" ]
tbl << [ "nessus_report_host_ports", "Get list of open ports from a host from a report" ]
tbl << [ "nessus_report_host_detail", "Detail from a report item on a host" ]
tbl << [ "", ""]
tbl << [ "Scan Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_scan_new", "Create new Nessus Scan" ]
tbl << [ "nessus_scan_status", "List all currently running Nessus scans" ]
tbl << [ "nessus_scan_pause", "Pause a Nessus Scan" ]
tbl << [ "nessus_scan_pause_all", "Pause all Nessus Scans" ]
tbl << [ "nessus_scan_stop", "Stop a Nessus Scan" ]
tbl << [ "nessus_scan_stop_all", "Stop all Nessus Scans" ]
tbl << [ "nessus_scan_resume", "Resume a Nessus Scan" ]
tbl << [ "nessus_scan_resume_all", "Resume all Nessus Scans" ]
tbl << [ "", ""]
tbl << [ "Plugin Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_plugin_list", "Displays each plugin family and the number of plugins" ]
tbl << [ "nessus_plugin_family", "List plugins in a family" ]
tbl << [ "nessus_plugin_details", "List details of a particular plugin" ]
tbl << [ "", ""]
tbl << [ "User Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_user_list", "Show Nessus Users" ]
tbl << [ "nessus_user_add", "Add a new Nessus User" ]
tbl << [ "nessus_user_del", "Delete a Nessus User" ]
tbl << [ "nessus_user_passwd", "Change Nessus Users Password" ]
tbl << [ "", ""]
tbl << [ "Policy Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_policy_list", "List all polciies" ]
tbl << [ "nessus_policy_del", "Delete a policy" ]
$stdout.puts "\n"
$stdout.puts tbl.to_s + "\n"
end
def cmd_nessus_server_feed(*args)
@ -220,7 +181,6 @@ module Msf
$stdout.puts "\n"
$stdout.puts tbl.to_s + "\n"
end
end
def nessus_verify_token
@ -228,7 +188,6 @@ module Msf
ncusage
return false
end
true
end
@ -238,9 +197,7 @@ module Msf
print_error("No database has been configured, please use db_create/db_connect first")
return false
end
true
end
def ncusage
@ -277,6 +234,7 @@ module Msf
print_status("%bldport%clr is the standard that the nessus web front end runs on : 8834. This is NOT 1241.")
print_status("The \"ok\" on the end is important. It is a way of letting you")
print_status("know that nessus used a self signed cert and the risk that presents.")
return
end
if ! @token == ''
@ -349,7 +307,6 @@ module Msf
end
nessus_login
#Rex::Ui::Text::IrbShell.new(binding).run
end
def nessus_login
@ -382,6 +339,7 @@ module Msf
print_status(" Example:> nessus_report_list")
print_status()
print_status("Generates a list of all reports visable to your user.")
return
end
if ! nessus_verify_token
@ -389,7 +347,7 @@ module Msf
end
list=@n.report_list_hash
tbl = Rex::Ui::Text::Table.new(
'Columns' =>
[
@ -409,6 +367,25 @@ module Msf
print_status("You can:")
print_status(" Get a list of hosts from the report: nessus_report_hosts <report id>")
end
def check_scan(*args)
case args.length
when 1
rid = args[0]
else
print_error("No Report ID Supplied")
return
end
scans = @n.scan_list_hash
scans.each {|scan|
if scan['id'] == rid
return true
end
}
return false
end
def cmd_nessus_report_get(*args)
@ -421,6 +398,7 @@ module Msf
print_status("and parses it the same way db_import_nessus does. After it is parsed it will be")
print_status("available to commands such as db_hosts, db_vulns, db_services and db_autopwn.")
print_status("Use: nessus_report_list to obtain a list of report id's")
return
end
if ! nessus_verify_token
@ -449,10 +427,50 @@ module Msf
print_status(" use nessus_report_list to list all available reports for importing")
return
end
if check_scan(rid)
print_error("That scan is still running.")
return
end
content = nil
content=@n.report_file_download(rid)
if content.nil?
print_error("Failed, please reauthenticate")
return
end
print_status("importing " + rid)
framework.db.import({:data => content})
framework.db.import({:data => content}) do |type,data|
case type
when :address
@count = 0
print("%bld%blu[*]%clr %bld#{data}%clr")
$stdout.flush
when :port
print("\b")
case @count
when 0
print("%bld%grn|")
@count += 1
when 1
print("%bld%grn/")
@count += 1
when 2
print("%bld%grn-")
@count += 1
when 3
print("%bld%grn/")
@count = 0
end
$stdout.flush
when :end
print("\b Done!%clr\n")
$stdout.flush
when :os
data.gsub!(/[\n\r]/," or ") if data
print(" #{data} ")
end
end
print_good("Done")
end
@ -464,6 +482,7 @@ module Msf
print_status(" Example:> nessus_scan_status")
print_status()
print_status("Returns a list of information about currently running scans.")
return
end
if ! nessus_verify_token
@ -503,6 +522,52 @@ module Msf
print_good(" Import Nessus report to database : nessus_report_get <reportid>")
print_good(" Pause a nessus scan : nessus_scan_pause <scanid>")
end
def cmd_nessus_template_list(*args)
if args[0] == "-h"
print_status("Usage: ")
print_status(" nessus_template_list")
print_status(" Example:> nessus_template_list")
print_status()
print_status("Returns a list of information about the server templates..")
return
end
if ! nessus_verify_token
return
end
list=@n.template_list_hash
if list.empty?
print_status("No Templates Created.")
print_status("You can:")
print_status(" List of completed scans: nessus_report_list")
print_status(" Create a template: nessus_template_new <policy id> <scan name> <target(s)>")
return
end
tbl = Rex::Ui::Text::Table.new(
'Columns' =>
[
'Template ID',
'Policy ID',
'Name',
'Owner',
'Target'
])
list.each {|template|
tbl << [ template['name'], template['pid'], template['rname'], template['owner'], template['target'] ]
}
print_good("Templates")
$stdout.puts "\n"
$stdout.puts tbl.to_s + "\n"
$stdout.puts "\n"
print_status("You can:")
print_good(" Import Nessus report to database : nessus_report_get <reportid>")
end
def cmd_nessus_user_list(*args)
@ -512,6 +577,7 @@ module Msf
print_status(" Example:> nessus_user_list")
print_status()
print_status("Returns a list of the users on the Nessus server and their access level.")
return
end
if ! nessus_verify_token
@ -549,6 +615,7 @@ module Msf
print_status(" Example:> nessus_server_status")
print_status()
print_status("Returns some status items for the server..")
return
end
#Auth
if ! nessus_verify_token
@ -609,6 +676,7 @@ module Msf
print_status(" Example:> nessus_plugin_list")
print_status()
print_status("Returns a list of the plugins on the server per family.")
return
end
if ! nessus_verify_token
@ -635,6 +703,25 @@ module Msf
$stdout.puts tbl.to_s + "\n"
print_status("List plugins for a family : nessus_plugin_family <family name>")
end
def check_policy(*args)
case args.length
when 1
pid = args[0]
else
print_error("No Policy ID supplied.")
return
end
pol = @n.policy_list_hash
pol.each {|p|
if p['id'].to_i == pid
return false
end
}
return true
end
def cmd_nessus_scan_new(*args)
@ -645,6 +732,7 @@ module Msf
print_status()
print_status("Creates a scan based on a policy id and targets.")
print_status("use nessus_policy_list to list all available policies")
return
end
if ! nessus_verify_token
@ -662,6 +750,11 @@ module Msf
print_status(" use nessus_policy_list to list all available policies")
return
end
if check_policy(pid)
print_error("That policy does not exist.")
return
end
print_status("Creating scan from policy number #{pid}, called \"#{name}\" and scanning #{tgts}")
@ -681,6 +774,7 @@ module Msf
print_status()
print_status("Pauses a running scan")
print_status("use nessus_scan_status to list all available scans")
return
end
if ! nessus_verify_token
@ -711,6 +805,7 @@ module Msf
print_status()
print_status("resumes a running scan")
print_status("use nessus_scan_status to list all available scans")
return
end
if ! nessus_verify_token
@ -741,6 +836,7 @@ module Msf
print_status()
print_status("Returns all the hosts associated with a scan and details about their vulnerabilities")
print_status("use nessus_report_list to list all available scans")
return
end
if ! nessus_verify_token
@ -838,6 +934,7 @@ module Msf
print_status()
print_status("Returns all the vulns associated with a port for a specific host")
print_status("use nessus_report_host_ports to list all available ports for a host")
return
end
if ! nessus_verify_token
@ -888,6 +985,7 @@ module Msf
print_status()
print_status("Pauses all currently running scans")
print_status("use nessus_scan_list to list all running scans")
return
end
if ! nessus_verify_token
@ -908,6 +1006,7 @@ module Msf
print_status()
print_status("Stops a currently running scans")
print_status("use nessus_scan_list to list all running scans")
return
end
if ! nessus_verify_token
@ -938,6 +1037,7 @@ module Msf
print_status()
print_status("stops all currently running scans")
print_status("use nessus_scan_list to list all running scans")
return
end
if ! nessus_verify_token
@ -958,6 +1058,7 @@ module Msf
print_status()
print_status("resumes all currently running scans")
print_status("use nessus_scan_list to list all running scans")
return
end
if ! nessus_verify_token
@ -978,6 +1079,7 @@ module Msf
print_status()
print_status("Only adds non admin users. Must be an admin to add users.")
print_status("use nessus_user_list to list all users")
return
end
if ! nessus_verify_token
@ -1065,6 +1167,7 @@ module Msf
print_status()
print_status("Changes the password of a user. Must be an admin to change passwords.")
print_status("use nessus_user_list to list all users")
return
end
if ! nessus_verify_token
@ -1105,6 +1208,7 @@ module Msf
print_status()
print_status("Checks to see if the current user is an admin")
print_status("use nessus_user_list to list all users")
return
end
if ! nessus_verify_token
@ -1127,6 +1231,7 @@ module Msf
print_status()
print_status("Returns a list of all plugins in that family.")
print_status("use nessus_plugin_list to list all plugins")
return
end
if ! nessus_verify_token
@ -1161,75 +1266,6 @@ module Msf
$stdout.puts tbl.to_s + "\n"
end
def cmd_nessus_find_targets(*args)
if args[0] == "-h"
print_status("Usage: ")
print_status(" nessus_find targets <report id>")
print_status(" Example:> nessus_find_targets f0eabba3-4065-7d54-5763-f191e98eb0f7f9f33db7e75a06ca")
print_status()
print_status("Finds targets in a scan with CVSS2 > 7 and returns some info.")
print_status("%redThis plugin is experimental%clr")
end
#given a report ID, find hosts that are the most vulnerable. Try to match to metasploit exploits if we can.
if ! nessus_verify_token
return
end
case args.length
when 1
rid = args[0]
else
print_status("Usage: ")
print_status(" nessus_find_targets <report id>")
print_status(" use nessus_report_list to list all available reports")
return
end
#tbl = Rex::Ui::Text::Table.new(
# 'Columns' =>
# [
# 'Hostname',
# 'Severity',
# 'Sev 0',
# 'Sev 1',
# 'Sev 2',
# 'Sev 3',
# 'Current Progress',
# 'Total Progress'
# ])
print_error("This command is still in dev, right now it (maybe) just outputs vulns from a report that are > CVSS2 7. It's slow.")
hosts=@n.report_hosts(rid)
hosts.each {|host|
#tbl << [ host['hostname'], host['severity'], host['sev0'], host['sev1'], host['sev2'], host['sev3'], host['current'], host['total'] ]
ports=@n.report_host_ports(rid, host['hostname'])
ports.each {|port|
#tbl << [ port['portnum'], port['protocol'], port['severity'], port['svcname'], port['sev0'], port['sev1'], port['sev2'], port['sev3'] ]
details=@n.report_host_port_details(rid, host['hostname'], port['portnum'].to_i, port['protocol'])
details.each {|detail|
if detail['cvss_base_score'].to_i > 7
#match = detail['cve']
#match = '.*' if match.nil?
#regex = Regexp.new(match, true, 'n')
#Msf::Ui::Console::CommandDispatcher::Core.show_module_set
#show_exploits(regex)
print_status("#{host['hostname']} | #{port['portnum']} | #{detail['severity']} | #{detail['pluginName']} | #{detail['cvss_base_score']} | #{detail['exploit_available']} | #{detail['cve']} | #{detail['risk_factor']}")
end
## need to search msf site on all BID's and CVE's and compile a list of possible plugins. maybe db_autopwn does something i can use?
# btw, the | between things looks kinda cool. lets have a party in table.rb later to see if we can add that as an option.
#
}
}
}
#print_good("Report Info")
#$stdout.puts "\n"
#$stdout.puts tbl.to_s + "\n"
end
def cmd_nessus_policy_list(*args)
if args[0] == "-h"
@ -1238,6 +1274,7 @@ module Msf
print_status(" Example:> nessus_policy_list")
print_status()
print_status("Lists all policies on the server")
return
end
if ! nessus_verify_token
@ -1249,12 +1286,11 @@ module Msf
[
'ID',
'Name',
'Owner',
'visability'
'Comments'
])
list=@n.policy_list_hash
list.each {|policy|
tbl << [ policy['id'], policy['name'], policy['owner'], policy['vis'] ]
tbl << [ policy['id'], policy['name'], policy['comments'] ]
}
print_good("Nessus Policy List")
$stdout.puts "\n"
@ -1270,6 +1306,7 @@ module Msf
print_status()
print_status("Must be an admin to del policies.")
print_status("use nessus_policy_list to list all policies")
return
end
if ! nessus_verify_token
@ -1317,6 +1354,7 @@ module Msf
print_status()
print_status("Returns details on a particular plugin.")
print_status("use nessus_plugin_list to list all plugins")
return
end
if ! nessus_verify_token
@ -1369,6 +1407,7 @@ module Msf
print_status()
print_status("Must be an admin to del reports.")
print_status("use nessus_report_list to list all reports")
return
end
if ! nessus_verify_token
@ -1417,6 +1456,7 @@ module Msf
print_status(" Example:> nessus_server_prefs")
print_status()
print_status("Returns a long list of server prefs.")
return
end
if ! nessus_verify_token
@ -1452,6 +1492,7 @@ module Msf
print_status(" Example:> nessus_plugin_prefs")
print_status()
print_status("Returns a long list of plugin prefs.")
return
end
if ! nessus_verify_token
@ -1525,25 +1566,6 @@ module Msf
def desc
"HTTP Bridge to control a Nessus 4.2 scanner."
end
protected
end
end
### List of requested additions.
# refine nessus_find_targets to show vulnerabilities likely to be explitable.
# define a import method to get those vulnerabilities imported for use by db_autopwn. end state should be most (if not all) vulns result in shell from import. Have to becareful of false postitive and false negative.
# match = '.*' if match.nil?
# regex = Regexp.new(match, true, 'n')
# show_exploits(regex, rank)
# parse cvss_temporal_score and look at attack vectors etc.
# convert to using Streaming xml parsing. Nmap XL Parser has the code we need to borrow from.
# add ability to save report in nbe/nessusv1/html format. posibbly all at once.
# look at seeing how nessus_scan_new works with ip addresses, can use a file? How about select from the db? yeah db would be cool.