106 lines
3.7 KiB
Python
106 lines
3.7 KiB
Python
#!/usr/bin/python
|
|
#Cronjob script that executes Nmap scans on the background
|
|
import sqlite3
|
|
import os
|
|
import subprocess
|
|
import smtplib
|
|
import datetime
|
|
import uuid
|
|
import lxml.etree as ET
|
|
import distutils.spawn
|
|
|
|
from email.MIMEMultipart import MIMEMultipart
|
|
from email.MIMEText import MIMEText
|
|
|
|
BASE_URL = "http://127.0.0.1:8000"
|
|
SMTP_USER = "youremail@gmail.com"
|
|
SMTP_PASS = "yourpassword"
|
|
SMTP_SERVER = "smtp.gmail.com"
|
|
SMTP_PORT = 587
|
|
OUTPUT_PATH = os.path.normpath("%s/nmaper/static/results" % os.getcwd()).replace("\\", "/")
|
|
|
|
def find_nmap():
|
|
if os.name == "nt":
|
|
nmap_path = distutils.spawn.find_executable("nmap.exe", os.environ["PROGRAMFILES(X86)"]+"\Nmap")
|
|
if not(nmap_path):
|
|
nmap_path = distutils.spawn.find_executable("nmap.exe", os.environ["PROGRAMFILES"]+"\Nmap")
|
|
else:
|
|
nmap_path = distutils.spawn.find_executable("nmap")
|
|
|
|
return nmap_path
|
|
|
|
def notify(id_, email, cmd):
|
|
print('[%s] Sending report %s to %s' % (datetime.datetime.now(), id_, email))
|
|
msg = MIMEMultipart()
|
|
msg['From'] = SMTP_USER
|
|
msg['To'] = email
|
|
msg['Subject'] = "Your scan results are ready"
|
|
body = "{2}\n\nView online:\n{0}/static/results/{1}.html\n\nDownload:\n{0}/static/results/{1}.nmap\n{0}/static/results/{1}.xml\n{0}/static/results/{1}.gnmap".format(BASE_URL, id_, cmd)
|
|
msg.attach(MIMEText(body, 'plain'))
|
|
server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
|
|
server.ehlo()
|
|
server.starttls()
|
|
server.ehlo()
|
|
server.login(SMTP_USER, SMTP_PASS)
|
|
text = msg.as_string()
|
|
server.sendmail(SMTP_USER, email, text)
|
|
|
|
def update_status(id_, status, cursor, db):
|
|
cursor.execute('''UPDATE nmaper_nmapscan SET status_text = ? WHERE id = ? ''', (status, id_))
|
|
db.commit()
|
|
print("[%s] Job #%s status changed to '%s'" % (datetime.datetime.now(), id_, status))
|
|
|
|
def set_random_id(id_, cursor, db):
|
|
rid = uuid.uuid4()
|
|
cursor.execute('''UPDATE nmaper_nmapscan SET uuid = ? WHERE id = ? ''', (rid.hex, id_))
|
|
db.commit()
|
|
return rid.hex
|
|
|
|
def set_endtime(id_, cursor, db):
|
|
cursor.execute('''UPDATE nmaper_nmapscan SET end_date = ? WHERE id = ? ''', (datetime.datetime.now(), id_))
|
|
db.commit()
|
|
|
|
def execute(path, cmd, uuid):
|
|
filename = "%s/%s" % (OUTPUT_PATH, uuid)
|
|
proc = subprocess.Popen('%s %s -oA %s' % (path, cmd, filename), shell=True)
|
|
proc.wait()
|
|
|
|
print('\n[%s] Finished execution of command "%s"' % (datetime.datetime.now(), cmd))
|
|
|
|
dom = ET.parse("%s.xml" % filename)
|
|
xsl_filename = dom.getroot().getprevious().getprevious().parseXSL() # need to add error checking
|
|
transform = ET.XSLT(xsl_filename)
|
|
html = transform(dom)
|
|
html_file = open('%s.html' % filename, 'w')
|
|
html.write(html_file)
|
|
|
|
print('[%s] HTML report generated (%s.html)' % (datetime.datetime.now(), filename))
|
|
|
|
def main():
|
|
path = find_nmap()
|
|
if not path:
|
|
print("[%s] Could not find path for nmap. Quitting!" % datetime.datetime.now())
|
|
exit()
|
|
|
|
db = sqlite3.connect('scandere.sqlite3')
|
|
cursor = db.cursor()
|
|
cursor.execute('''SELECT * FROM nmaper_nmapscan WHERE status_text="waiting"''')
|
|
all_rows = cursor.fetchall()
|
|
print('[%s] Listing pending nmap scans...' % datetime.datetime.now())
|
|
|
|
for row in all_rows:
|
|
cmd = row[2]
|
|
jid = row[0]
|
|
email = row[5]
|
|
print('[%s] Job #%d:%s' % (datetime.datetime.now(), jid, cmd))
|
|
rid = set_random_id(jid, cursor, db)
|
|
update_status(jid, "running", cursor, db)
|
|
execute(path, cmd, rid)
|
|
update_status(jid, "finished", cursor, db)
|
|
set_endtime(jid, cursor, db)
|
|
print("[%s] Job #%d finished. Notifying '%s'" % (datetime.datetime.now(), jid, email))
|
|
notify(rid, email, cmd)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|