Nessus Grep

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) 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: