Nessus API Python Script
27 February 2015
A while ago when I was still learning Python, I wrote a Python script that would interact with the Nessus API to pull out certain information. Things like scans, hosts, vulnerabilities, policies, etc. You could also create new scans from the script as well. The script was also able to print out in key/value pair (which would be great with Splunk) certain information from the reports.
It's been sitting in a folder on my computer for a long time doing nothing, so I figured I would just post it on here, in case someone else could get some use out of it.
Please note this is released "As Is" and I don't intend to fix any part of it in the future.
#!/usr/bin/env python 2.7.5
# -*- coding: utf-8 -*-
# @name: nessus.py
# @author: Brian Warehime
# @date: 2014/03/07
# @copyright: <https://www.gnu.org/licenses/gpl-3.0.html>
#############
# LIBRARIES #
#############
import urllib2
import argparse
import os
import xml.etree.cElementTree as ET
import time
##################
# LOGIN FUNCTION #
##################
def login():
# API Call to login to Nessus
log = urllib2.urlopen('https://'+url+':'+port+'/login/','login=test'&password=password')
# Parsing XML for the token, needed for all future API calls requiring authentication
tree = ET.parse(log)
tree.getroot()
for elem in tree.findall('contents/token'):
token = elem.text
return token
####################
# REPORTS FUNCTION #
####################
def reports():
# API Call to get a list of reports on Nessus Server
report = urllib2.urlopen('https://'+url+':'+port+'/report/list', 'token=' + token)
# Header for listed reports
print ""
print "Nessus CLI v1.0"
print "---------------------------------------------------------------------------------------------------------------------"
print "Report Name".ljust(20), "Status".ljust(20), "Date/Time".ljust(22), "UUID"
print "---------------------------------------------------------------------------------------------------------------------"
# Parse XML for all the reports, then grabs the name, status and timestamp of each report.
tree = ET.parse(report)
tree.getroot()
for elem in tree.findall('contents/reports/'):
name = elem.find('readableName').text
status = elem.find('status').text
timestamp = elem.find('timestamp').text
uuid = elem.find('name').text
# Convert the epoch string timestamp into a readable timestamp format
floatedtime = float(timestamp)
truetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(floatedtime))
# Print the Report information in format with Header
print name.ljust(20), status.capitalize().ljust(20), truetime.ljust(22), uuid
#####################
# Create a New Scan #
#####################
def newscan():
# Asking for scan information
scanname = args.scanname
target = args.target
policy = args.policy
# Manually URL Encoding . to %2E, since urlencode doens't encode .'s
x = target.replace('.','%2E')
# API Call to create a new scan, using the token as authentication, a scan name, the targets, and policy ID
scan = urllib2.urlopen('https://'+url+':'+port+'/scan/new', 'token=' + token + '&scan%5fname=' +
scanname + '&target=' + target + '&policy%5fid='+ policy)
# Printing the Header
print ""
print "Nessus CLI v1.0"
print "-----------------------------------------------------------------------"
print "Report Name".ljust(20), "Date/Time Created".ljust(20), "UUID"
print "-----------------------------------------------------------------------"
# Parse XML for valuable information from new scan.
tree = ET.parse(scan)
tree.getroot()
for child in tree.iter('scan'):
uuid = child.find('uuid').text
start_time = child.find('start_time').text
scan_name = child.find('scan_name').text
# Convert the epoch string timestamp into a reable timestamp format
floatedstarttime = float(start_time)
truetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(floatedstarttime))
# Print the New Scan information in format with the header
print scan_name.ljust(20), truetime.ljust(20), uuid
#####################
# Policies Function #
#####################
def policies():
# API Call to get a list of the policies
scan = urllib2.urlopen('https://'+url+':'+port+'/policy/list', 'token=' + token)
#Printing the Header
print ""
print "Nessus CLI v1.0"
print "-----------------------------------------------------------------------"
print "Name".ljust(20), "ID".ljust(5), "Owner".ljust(10), "Comments"
print "-----------------------------------------------------------------------"
# Parse XML for Policy ID and information
tree = ET.parse(scan)
tree.getroot()
for child in tree.iter('policy'):
policyid = child.find('policyID').text
policyname = child.find('policyName').text
policyowner = child.find('policyOwner').text
policycomments = child.find('policyContents/policyComments').text
#Print the Policy Information in format with the header
print policyname.ljust(20), policyid.ljust(5), policyowner.ljust(10), policycomments
#################
# Load Function #
#################
def load():
# API Call to get load values
scan = urllib2.urlopen('https://'+url+':'+port+'/server/load', 'token=' + token)
# Printing the Header
print ""
print "Nessus CLI v1.0"
print "---------------------------------------------------------------------------------"
print "# Of Scans".ljust(15), "# Of Sessions".ljust(15), "# Of Hosts".ljust(15), "# Of TCP Sessions".ljust(20), "Load Average"
print "---------------------------------------------------------------------------------"
# Parsing XML
tree = ET.parse(scan)
tree.getroot()
for child in tree.iter('load'):
numscans = child.find('num_scans').text
numsessions = child.find('num_sessions').text
numhosts = child.find('num_hosts').text
numtcp = child.find('num_tcp_sessions').text
loadavg = child.find('loadavg').text
print " " + numscans.ljust(15), numsessions.ljust(15), numhosts.ljust(15), numtcp.ljust(20), loadavg
###################
# Vulnerabilities #
###################
def vulns():
uuid = args.uuid
scan = urllib2.urlopen('https://'+url+':'+port+'/report2/vulnerabilities', 'token=' + token + '&report=' + uuid)
tree = ET.parse(scan)
tree.getroot()
for child in tree.iter('vulnerability'):
pluginid = child.find('plugin_id').text
pluginname = child.find('plugin_name').text
pluginfamily = child.find('plugin_family').text
count = child.find('count').text
severity = child.find('severity').text
print "Plugin ID: " + pluginid
print "Plugin Name: " + pluginname
print "Plugin Family: " + pluginfamily
print "Count: " + count
print "Severity: " + severity
print ""
#########
# Hosts #
#########
def hosts():
uuid = args.uuid
scan = urllib2.urlopen('https://'+url+':'+port+'/report/hosts', 'token=' + token + '&report=' + uuid)
# Print Header
print ""
print "Nessus CLI v1.0"
print "-------------------------------------"
print "Hostname".ljust(20), "Vulnerabilities"
print "-------------------------------------"
# Parse XML
tree = ET.parse(scan)
tree.getroot()
for child in tree.iter('host'):
hostname = child.find('hostname').text
vulnerabilities = child.find('severity').text
print hostname.ljust(25), vulnerabilities
##############
# Log Format #
##############
def log():
report = urllib2.urlopen('https://'+url+':'+port+'/report/list', 'token=' + token)
# Parse XML for all the reports, then grabs the name, status and timestamp of each report.
tree = ET.parse(report)
tree.getroot()
for elem in tree.findall('contents/reports/'):
name = elem.find('readableName').text
status = elem.find('status').text
timestamp = elem.find('timestamp').text
uuid = elem.find('name').text
# Convert the epoch string timestamp into a readable timestamp format
floatedtime = float(timestamp)
truetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(floatedtime))
# Print the Report information in format with Header
print "time="+truetime + " " + "report_name="+name + " " + "status="+status + " " + "uuid="+uuid
scan2 = urllib2.urlopen('https://'+url+':'+port+'/server/load', 'token=' + token)
# Parsing XML
tree = ET.parse(scan2)
tree.getroot()
for child in tree.iter('load'):
numscans = child.find('num_scans').text
numsessions = child.find('num_sessions').text
numhosts = child.find('num_hosts').text
numtcp = child.find('num_tcp_sessions').text
loadavg = child.find('loadavg').text
print "loadavg="+loadavg+" "+"tcpsessions="+numtcp
##############################
# Parsing Arguments Function #
##############################
def parse_args():
# Option Parsing
parser = argparse.ArgumentParser(__file__, description="Nessus CLI")
parser.add_argument('-r', '--reports', help='List all reports', action="store_true")
parser.add_argument('-n', '--newscan', help='Creates a new scan', action="store_true")
parser.add_argument('-p', '--policies',help='List all policies', action="store_true")
parser.add_argument('-l', '--load', help='Get the current load', action="store_true")
parser.add_argument('--target', help='Specify a target', dest="target")
parser.add_argument('--policy', help='Specify a policy', dest="policy")
parser.add_argument('--scanname', help='Specify a name for the scan', dest="scanname")
parser.add_argument('--uuid', help='Specify a report UUID', dest="uuid")
parser.add_argument('-v', '--vulns', help='Get the current vulnerabilities for report', action="store_true")
parser.add_argument('-a', '--hosts', help='Get a list of hosts in a given report', action="store_true")
parser.add_argument('-s', '--log', help='Output to log format', action="store_true")
args = parser.parse_args()
return args
#################
# Main Function #
#################
if __name__ == '__main__':
url = 'localhost'
port = '8834'
token = login()
args = parse_args()
if (args.reports):
reports()
elif (args.newscan):
newscan()
elif (args.policies):
policies()
elif (args.load):
load()
elif (args.vulns):
vulns()
elif (args.hosts):
hosts()
elif (args.log):
log()