Nessus Grep
February 7, 2010 Leave a comment
The code is pretty self explanatory. It searches through a .nessus file and spits out matching hosts.
#!/usr/bin/python def usage(): print """ This program takes a regular expression for a problem and returns the affected hosts. It iterates through all reports saved in a .nessus file making no attempt at uniqueness, (eg if you scanned a host more than once) searching through titles, data, port, and IDs for matches. It prints one host per line, relying on tools like wc, tr, sort, uniq USAGE: arg[0] [--dns] myfile.nessus regex For a regex reference, see http://docs.python.org/library/re.html The --dns flag will print out the dns name in addition to what was given for the scan EXAMPLES: #search for hosts that ran the nikto plugin python nessus_grep.py scan.nessus nikto #case insensitive search for nikto python nessus_grep.py scan.nessus "(?i)nikto" #it's usually probably ok to just check for id, but be careful #as an added precaution I give it the beginning end of lines python nessus_grep.py scan.nessus "^10386$" #find all hosts with either the SSL Cipher "bug" or running SSL Version 2 python nessus_grep.py scan.nessus "(SSL Weak Cipher Suites Supported|SSL Version 2 (v2) Protocol Detection)" """ import sys import re from lxml import etree def regexsearch(regex, *strings): for i in strings: try: if re.search(regex, i): return True except TypeError: pass """ Although there is some repeating logic in dotnessusparse and dotxmlparse, they are two different formats and are kept separate in case of changes to only one """ def dotnessusparse(nessus_xml, hostprint=False): for report in nessus_xml.getroot(): if "Report" in repr(report.tag): for host in report: if "ReportHost" in host.tag: hostname = (host.find("HostName").text) dnsname = host.find("dns_name").text.rstrip(".\n") if ("(unknown)" in dnsname): dnsname = "" reptitem = (host.findall("ReportItem")) for issue in reptitem: data = issue.find("data").text pluginname = issue.find("pluginName").text pluginid = issue.find("pluginID").text port = issue.find("port").text if regexsearch(regex, data, pluginname, pluginid, port): if hostprint: hostname = hostname + " (" + dnsname + ")" print hostname break def dotxmlparse(nessus_xml, hostprint=False): for report in nessus_xml.getroot(): if "Report" in repr(report.tag): for host in report: if "ReportHost" in host.tag: hostname = host.get("name") dnsname = "" hostprops = host.find("HostProperties").findall("tag") for prop in hostprops: if prop.get("name") == "host-fqdn": dnsname = prop.text reptitem = (host.findall("ReportItem")) for issue in reptitem: data = sol = syn = plugout = None if issue.find("description") is not None: data = issue.find("description").text if issue.find("solution") is not None: sol = issue.find("solution").text if issue.find("synopsis") is not None: syn = issue.find("synopsis").text if issue.find("plugin_output") is not None: plugout = issue.find("plugin_output").text pluginname = issue.get("pluginName") pluginId = issue.get("pluginID") if regexsearch(regex, sol, syn, plugout, pluginname, pluginId): if hostprint: hostname = hostname + " (" + dnsname + ")" print hostname break if __name__ == "__main__": re.IGNORECASE if len(sys.argv) < 3: usage() sys.exit(0) filelist = sys.argv[1:-1] try: filelist.remove("--dns") hostprint = True except ValueError: hostprint = False regex = sys.argv[-1] for nessusfile in filelist: nessus_xml = etree.parse(nessusfile) if nessusfile.endswith(".nessus"): dotnessusparse(nessus_xml, hostprint) if nessusfile.endswith(".xml"): dotxmlparse(nessus_xml, hostprint)