metasploit-framework/lib/nessus/nessus-cli.rb

383 lines
10 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# = nessus-cli.rb: Nessus command line interface for XML-RPC
# Author:: Vlatko Kosturjak
#
# (C) Vlatko Kosturjak, Kost. Distributed under GPL and BSD (dual licensed).
require 'nessus-xmlrpc'
require 'getoptlong'
verbose = 0
debug = 0
operation = ''
targets = ''
deletereport = false
user = ''
password = ''
scanname = ''
output = ''
output1 = ''
wait = ''
policy = ''
url = ''
def intro
$stderr.print $0 + ": Nessus command line interface for XML-RPC\n"
$stderr.print "(C) Vlatko Kosturjak, Kost. Distributed under GPL.\n"
$stderr.print "\n"
end
intro
def give_help
puts <<-EOF
--user <user> user for login to Nessus server
--password <p> password for login to Nessus server
--scan <name> start scan with name
--target <ip> specify list of targets, separated by comma
--policy <pol> specify policy to use (name of policy)
--url <url> url of Nessus server (default: localhost:8834)
--wait [t] wait scan to finish (ask in regular periods of <t> for status)
--output <f> output report XML to file <f>
--output1 <f> output report XML v1 to file <f>
--reportdelete delete report after finish or delete report by id (if alone)
--stop <id> stop scan identified by <id>
--stop-all stop all scans
--pause <id> pause scan identified by <id>
--pause-all pause all scans
--resume <id> resume scan identified by <id>
--resume-all resume all scans
--report <id> download report identified by <id>
--list-scans list scans
--list-policy list policies
--status <id> get status of scan by <id>
--verbose be verbose
--debug be even more verbose
--help this help
Examples:
#{$0} --user john --password doe --scan scan-localhost --wait --output report.xml --target localhost
EOF
exit 0
end
if ARGV.length < 1
give_help
end
opt = GetoptLong.new(
["--help", "-h", GetoptLong::NO_ARGUMENT],
["--verbose", "-v", GetoptLong::OPTIONAL_ARGUMENT],
["--target", "-t", GetoptLong::REQUIRED_ARGUMENT],
["--user", "-u", GetoptLong::REQUIRED_ARGUMENT],
["--password", "-p", GetoptLong::REQUIRED_ARGUMENT],
["--policy", "-P", GetoptLong::REQUIRED_ARGUMENT],
["--url", "-U", GetoptLong::REQUIRED_ARGUMENT],
["--deletereport", "-D", GetoptLong::OPTIONAL_ARGUMENT],
["--wait", "-w", GetoptLong::OPTIONAL_ARGUMENT],
["--scan", "-s", GetoptLong::REQUIRED_ARGUMENT],
["--list-scans", "-l", GetoptLong::NO_ARGUMENT],
["--list-policy", "-L", GetoptLong::NO_ARGUMENT],
["--status", "-W", GetoptLong::REQUIRED_ARGUMENT],
["--stop", "-S", GetoptLong::REQUIRED_ARGUMENT],
["--stop-all", "-a", GetoptLong::NO_ARGUMENT],
["--pause", "-q", GetoptLong::REQUIRED_ARGUMENT],
["--pause-all", "-Q", GetoptLong::NO_ARGUMENT],
["--resume", "-e", GetoptLong::REQUIRED_ARGUMENT],
["--resume-all", "-E", GetoptLong::NO_ARGUMENT],
["--report", "-r", GetoptLong::REQUIRED_ARGUMENT],
["--output", "-o", GetoptLong::REQUIRED_ARGUMENT],
["--output1", "-1", GetoptLong::REQUIRED_ARGUMENT]
)
def give_error
$stderr.print "You used incompatible options, probably you mixed --scan with --stop"
$stderr.print "or something similar."
exit 0
end
opt.each do |opt,arg|
case opt
when '--help'
give_help
when '--user'
user = arg
when '--password'
password = arg
when '--stop'
if operation == ''
operation = "stop"
scanname = arg
else
give_error
end
when '--pause'
if operation == ''
operation = "pause"
scanname = arg
else
give_error
end
when '--resume'
if operation == ''
operation = "resume"
scanname = arg
else
give_error
end
when '--stop-all'
if operation == ''
operation = "stop-all"
else
give_error
end
when '--pause-all'
if operation == ''
operation = "pause-all"
else
give_error
end
when '--resume-all'
if operation == ''
operation = "resume-all"
else
give_error
end
when '--report'
if operation == ''
operation = "report"
scanname = arg
else
give_error
end
when '--scan'
if operation == ''
operation = "scan"
scanname = arg
else
give_error
end
when '--target'
if arg[0..6] == 'file://'
f = File.open(arg[7..-1], "r")
f.each_line do |line|
line=line.chomp
line=line.strip
unless line == '' or line == nil
if targets == ''
targets = line
else
targets = targets + "," + line
end
end
end
f.close
else
# if there's multiple target options, add comma
if targets == ''
targets = arg
else
targets = targets + "," + arg
end
end
when '--wait'
if arg == ''
wait = 15
else
wait = arg.to_i
end
when '--reportdelete'
if arg == ''
deletereport=true
else
operation = "reportdelete"
scanname = arg
end
when '--output'
output = arg
when '--output1'
output1 = arg
when '--policy'
policy = arg
when '--status'
if operation == ''
operation = "status"
scanname = arg
else
give_error
end
when '--url'
url = arg
when '--verbose'
if arg == ''
verbose += 1
else
verbose = arg.to_i
end
when '--debug'
if arg == ''
debug += 1
else
debug = arg.to_i
end
when '--list-scans'
if operation == ''
operation = "list-scans"
scanname = arg
else
give_error
end
when '--list-policy'
if operation == ''
operation = "list-policy"
scanname = arg
else
give_error
end
end
end
if (user == '') or (password == '')
$stderr.print "User and password is required to login to Nessus server"
$stderr.print "Try --help!"
exit 1
end
$stderr.print "[i] Targets: " + targets +"\n" if verbose > 0
$stderr.print "[i] Connecting to nessus server: " if verbose > 0
n=NessusXMLRPC::NessusXMLRPC.new(url,user,password)
if n.logged_in
$stderr.print "OK!\n" if verbose > 0
else
$stderr.print "[e] Error connecting/logging to the server!\n"
exit 2
end
case operation
when "scan"
if policy == ''
$stderr.print "[w] Policy not defined, using first served from the server\n"
pid,name = n.policy_get_first
$stderr.print "[w] using policy id " + pid + " with name " + name + "\n"
else
pid=n.policy_get_id(policy)
if pid == ''
$stderr.print "[e] policy doesn't exit: " + policy + "\n"
exit 3
end
end
if targets == ''
$stderr.print "[w] Targets not defined, using localhost as target\n"
targets = '127.0.0.1'
end
$stderr.print "[i] Initiating scan with targets: "+targets+': ' if verbose > 0
uid=n.scan_new(pid,scanname,targets)
$stderr.print "done\n" if verbose > 0
unless wait == ''
while not n.scan_finished(uid)
$stderr.print "[v] Sleeping for " + wait.to_s() + ": " if verbose > 1
sleep wait
$stderr.print "done\n" if verbose > 1
stat = n.scan_status(uid)
print "\r" + stat if verbose > 0
end
else
puts uid
exit 0
end
unless output == ''
$stderr.print "[i] Output XML report to file: "+output if verbose > 0
content=n.report_file_download(uid)
File.open(output, 'w') {|f| f.write(content) }
$stderr.print ": done\n" if verbose > 0
end
unless output1 == ''
$stderr.print "[i] Output XML1 report to file: "+output1 if verbose > 0
content=n.report_file1_download(uid)
File.open(output, 'w') {|f| f.write(content) }
$stderr.print ": done\n" if verbose > 0
end
if deletereport
$stderr.print "[i] Deleting report: " if verbose > 0
n.report_delete(uid)
$stderr.print "done\n" if verbose > 0
end
when "report"
uid=scanname
if (output == '') and (output1 == '')
$stderr.print "[e] You want report, but specify filename with --output or output1\n"
end
unless output == ''
$stderr.print "[i] Output XML report to file: "+output if verbose > 0
content=n.report_file_download(uid)
File.open(output, 'w') {|f| f.write(content) }
$stderr.print ": done\n" if verbose > 0
end
unless output1 == ''
$stderr.print "[i] Output XML1 report to file: "+output1 if verbose > 0
content=n.report1_file_download(uid)
File.open(output, 'w') {|f| f.write(content) }
$stderr.print ": done\n" if verbose > 0
end
if deletereport
$stderr.print "[i] Deleting report: " if verbose > 0
n.report_delete(uid)
$stderr.print "done\n" if verbose > 0
end
when "stop"
$stderr.print "[i] Stopping scan: " + scanname if verbose > 0
n.scan_stop(scanname)
$stderr.print "done\n" if verbose > 0
when "stop-all"
$stderr.print "[i] Stopping all scans: " if verbose > 0
list=n.scan_stop_all
$stderr.print "done\n" if verbose > 0
if verbose > 1
list.each {|uuid| puts "[v] Stop all: " + uuid }
end
when "pause"
$stderr.print "[i] Pausing scan: " + scanname if verbose > 0
n.scan_pause(scanname)
$stderr.print "done\n" if verbose > 0
when "pause-all"
$stderr.print "[i] Pausing all scans: " if verbose > 0
list=n.scan_pause_all
$stderr.print "done\n" if verbose > 0
if verbose > 1
list.each {|uuid| puts "[v] Pause all: " + uuid }
end
when "resume"
$stderr.print "[i] Resuming scan: " + scanname if verbose > 0
n.scan_resume(scanname)
$stderr.print "done\n" if verbose > 0
when "resume-all"
$stderr.print "[i] Resuming all scans: " if verbose > 0
list=n.scan_resume_all
$stderr.print "done\n" if verbose > 0
if verbose > 1
list.each {|uuid| puts "[v] Resume all: " + uuid }
end
when "reportdelete"
$stderr.print "[i] Deleting report: " + scanname if verbose > 0
n.report_delete(scanname)
$stderr.print "done\n" if verbose > 0
when "status"
puts "status: " + n.scan_status(scanname)
when "list-scans"
list=n.scan_list_hash
list.each {|scan|
puts scan['id']+":"+scan['name']+":"+ \
scan['current']+"/"+scan['total']
}
when "list-policy"
list=n.policy_list_names
list.each {|policy|
puts policy
}
end
$stderr.print "[v] End reached.\n" if verbose > 1