Skip to content

Instantly share code, notes, and snippets.

@redherringbone
Created November 11, 2016 16:13
Show Gist options
  • Save redherringbone/4aeb1a64377f33a846eeab4d8fd8ed40 to your computer and use it in GitHub Desktop.
Save redherringbone/4aeb1a64377f33a846eeab4d8fd8ed40 to your computer and use it in GitHub Desktop.
import time
import subprocess
import sys
import xml.etree.ElementTree as ET
import base64
import os
import shutil
import csv
import logging
import logging.handlers
import json
import pprint
from optparse import OptionParser
import requests
VERSION = "2016-11-11"
NMAPFILE = OPT_DIRECTORY = ""
OPT_VERBOSE = OPT_JSON = False
OUTPUTFILE="allHosts"
options = None
REPORT_DIR = "/nmap/reports/"
DATA_DIR = "/nmap/"
def parse_opts():
global NMAPFILE, OPT_VERBOSE, OPT_DIRECTORY, OPT_JSON, options
parser = OptionParser(usage="Iterate directory or file, HTTP POST to Elasticsearch. Version=%s")
parser.add_option("-f", "--file-name", action="store", dest="file_name", help = "the filename of the nmap scan.")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default = False , help = "Verbose shows all hosts and ports, non-verbose only shows interesting ones")
parser.add_option("-d", "--directory", action="store", default=REPORT_DIR, dest="directory_name", help = "Do all xml files in this directory. Default=%s" % (REPORT_DIR))
parser.add_option("-j", "--json", action="store_true", dest="json", default = False, help = "output to JSON and send to Logstash")
parser.add_option("-s", "--summary-only", action="store_true", dest="summaryonly", default = False, help = "Show summary only")
parser.add_option("-p", "", action="store", dest="portskip", help = "Ports to skip")
parser.add_option("-q", "", action="store_true", dest="quiet_actiononly", help = "Quiet mode, only show actionable ports. Suppress errors, do not send to Logstash etc.")
(options, args) = parser.parse_args()
if options.file_name is None:
if options.directory_name is None:
print "you MUST enter a file name or directory , see -h"
exit(1)
NMAPFILE = options.file_name
OPT_VERBOSE = options.verbose
OPT_DIRECTORY = options.directory_name
OPT_JSON = options.json
if options.verbose:
print "Processing directory %s Processing file %s" % (options.directory_name, options.file_name)
return
def parseGFile(theFilePath):
"""
parses
"""
theFileName = os.path.splitext(os.path.basename(theFilePath))[0]
with open(theFilePath, 'r') as theFileH :
try:
lines = [l.rstrip() for l in theFileH.readlines()]
for line in lines:
print "%s: %s " %(theFileName, line)
except:
logOut ("ERROR parseFile (%s)" %(theFilePath))
quit()
def doHostJSON(theJSONDict):
uri = "http://elasticsearch"
headers = {'content-type': 'application/json', 'tag': 'nmap'}
if not options.quiet_actiononly:
print "Posting to uri %s %s " % (uri, theJSONDict)
response = requests.post(uri, data=json.dumps(theJSONDict), headers=headers)
print response
else:
print "(quiet) POST to %s %s " % (uri, theJSONDict)
def toInt(theString):
try:
return(int(theString)) # success, this is an int
except:
return 0 # crunch the invalid value to 0, use -1 for testing
def parseXMLFile(theFilePath):
theFileName = os.path.splitext(os.path.basename(theFilePath))[0]
if options.verbose:
print "processing %s " % (theFilePath)
rowout = {'HostAddressAddr': '', 'HostStatusState': '', 'HostStatusReason':'',
"Filename": "", "OpenPorts": "" }
hostJSON = { "HostStatusState": "", "HostStatusReason": "", "HostStatusTTL": "",
"Hostname": "", "PortProtocol": "", "PortID": "",
"PortState": "", "PortStateReason": "", "PortStateReasonTTL": "",
"HostAddress": "", "Filename": ""
}
hostJSON["Filename"] = theFileName
nCountHosts = 0
nCountPorts = 0
try:
theNMAPTree = ET.parse(theFilePath)
#ET.dump(theNMAPTree)
root = theNMAPTree.getroot()
hosts = theNMAPTree.findall(".//host")
for host in hosts:
portslist = ""
for elem in host.iter():
ports = elem.findall("port")
if elem.tag == "status":
rowout['HostStatusState'] = elem.attrib['state']
rowout['HostStatusReason'] = elem.attrib['reason']
hostJSON['HostStatusState'] = elem.attrib['state']
hostJSON['HostStatusReason'] = elem.attrib['reason']
hostJSON['HostStatusTTL'] = toInt(elem.attrib['reason_ttl'])
if elem.tag == "address":
rowout['HostAddressAddr'] = elem.attrib['addr']
hostJSON['HostAddress'] = elem.attrib['addr']
if elem.tag == "hostname":
hostJSON['Hostname'] = elem.attrib['name']
for port_found in ports:
for pelem in port_found:
pass
states = port_found.findall("state")
for selem in states:
hostJSON['PortProtocol'] = port_found.attrib["protocol"]
hostJSON['PortID'] = toInt(port_found.attrib["portid"])
hostJSON['PortState'] = selem.attrib["state"]
hostJSON['PortStateReason'] = selem.attrib["reason"]
hostJSON['PortStateReasonTTL'] = toInt(selem.attrib["reason_ttl"])
if options.json:
doHostJSON(hostJSON)
if selem.attrib["state"] == "open":
thisportstate = ""
thisportstate += port_found.attrib["protocol"]
thisportstate += " "
thisportstate += port_found.attrib["portid"]
if OPT_VERBOSE:
pass
else:
if port_found.attrib["portid"] == "80" or port_found.attrib["portid"] == "443":
thisportstate = ""
if options.portskip:
if port_found.attrib["portid"] in options.portskip:
thisportstate = ""
if portslist and thisportstate:
portslist += ", "
portslist += thisportstate
if thisportstate:
nCountPorts += 1
NoOpenPorts = False
if portslist == "" :
portslist = "No open ports"
NoOpenPorts = True
rowout["OpenPorts"] = portslist
rowout["Filename"] = theFileName
if options.quiet_actiononly:
RowOutputString = "%s: %s: %s " % (theFileName, rowout['HostAddressAddr'], portslist)
else:
RowOutputString = "%s: %s: %s: %s: %s" % (theFileName, rowout['HostAddressAddr'],
rowout['HostStatusState'], rowout['HostStatusReason'], portslist)
if not OPT_VERBOSE:
if rowout['HostStatusState'] == "down" or NoOpenPorts:
RowOutputString = ""
if RowOutputString:
nCountHosts += 1
if RowOutputString and not options.summaryonly:
print RowOutputString
if OPT_JSON:
pass
if nCountHosts > 0 and not options.quiet_actiononly:
print "%s\tTotal insecure hosts %s\ttotal insecure ports %s " % (theFileName, nCountHosts, nCountPorts)
except Exception, err:
logOut ("ERROR %s parseFile (%s)" %(err, theFilePath))
def parseXMLDirectory(theDirectoryPath):
if theDirectoryPath[len(theDirectoryPath)-1] != "/":
theDirectoryPath += "/"
for file in os.listdir(theDirectoryPath):
if file.endswith(".xml"):
thefile = theDirectoryPath + file
parseXMLFile(thefile)
parse_opts()
if NMAPFILE:
parseXMLFile(NMAPFILE)
elif OPT_DIRECTORY:
parseXMLDirectory(OPT_DIRECTORY)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment