diff --git a/analysis/analysis.py b/analysis/analysis.py index c153293..345e82e 100644 --- a/analysis/analysis.py +++ b/analysis/analysis.py @@ -3,6 +3,7 @@ from classes.zeekengine import ZeekEngine from classes.suricataengine import SuricataEngine +from classes.report import Report from multiprocessing import Process, Manager import sys import re @@ -20,14 +21,23 @@ if __name__ == "__main__": capture_directory = sys.argv[1] if os.path.isdir(capture_directory): - # Alerts bucket. manager = Manager() alerts = manager.dict() def zeekengine(alerts): zeek = ZeekEngine(capture_directory) zeek.start_zeek() - alerts["zeek"] = zeek.get_alerts() + alerts["zeek"] = zeek.retrieve_alerts() + + # whitelist.json writing. + with open(os.path.join(capture_directory, "assets/whitelist.json"), "w") as f: + f.write(json.dumps(zeek.retrieve_whitelist(), + indent=4, separators=(',', ': '))) + + # conns.json writing. + with open(os.path.join(capture_directory, "assets/conns.json"), "w") as f: + f.write(json.dumps(zeek.retrieve_conns(), + indent=4, separators=(',', ': '))) def snortengine(alerts): suricata = SuricataEngine(capture_directory) @@ -45,7 +55,7 @@ if __name__ == "__main__": p2.join() # Some formating and alerts.json writing. - with open(os.path.join(capture_directory, "alerts.json"), "w") as f: + with open(os.path.join(capture_directory, "assets/alerts.json"), "w") as f: report = {"high": [], "moderate": [], "low": []} for alert in (alerts["zeek"] + alerts["suricata"]): if alert["level"] == "High": @@ -54,7 +64,11 @@ if __name__ == "__main__": report["moderate"].append(alert) if alert["level"] == "Low": report["low"].append(alert) - f.write(json.dumps(report)) + f.write(json.dumps(report, indent=4, separators=(',', ': '))) + + # Generate the report + report = Report(capture_directory) + report.generate_report() else: print("The directory doesn't exist.") else: diff --git a/analysis/classes/report.py b/analysis/classes/report.py new file mode 100644 index 0000000..49a9b78 --- /dev/null +++ b/analysis/classes/report.py @@ -0,0 +1,431 @@ +import weasyprint +import os +import json +import hashlib + +from weasyprint import HTML +from pathlib import Path +from datetime import datetime + + +class Report(object): + + def __init__(self, capture_directory): + self.capture_directory = capture_directory + self.alerts = self.read_json(os.path.join( + capture_directory, "assets/alerts.json")) + self.whitelist = self.read_json(os.path.join( + capture_directory, "assets/whitelist.json")) + self.conns = self.read_json(os.path.join( + capture_directory, "assets/conns.json")) + self.device = self.read_json(os.path.join( + capture_directory, "assets/device.json")) + + try: + with open(os.path.join(self.capture_directory, "capture.pcap"), "rb") as f: + self.capture_sha1 = hashlib.sha1(f.read()).hexdigest() + except: + self.capture_sha1 = "N/A" + + def read_json(self, json_path): + """ + Read and convert a JSON file. + :return: array or dict. + """ + with open(json_path, "r") as json_file: + return json.load(json_file) + + def generate_report(self): + """ + Generate the full report in PDF + :return: nothing + """ + content = self.generate_page_header() + content += self.generate_header() + content += self.generate_warning() + content += self.generate_alerts() + content += self.generate_suspect_conns_block() + content += self.generate_uncat_conns_block() + content += self.generate_whitelist_block() + + htmldoc = HTML(string=content, base_url="").write_pdf() + Path(os.path.join(self.capture_directory, + "report.pdf")).write_bytes(htmldoc) + + def generate_warning(self): + """ + Generate the warning message. + :return: str + """ + if len(self.alerts["high"]): + return "
Protocol | +Domain | +Dst IP Address | +Dst port | +
---|---|---|---|
{} | ".format(rec["proto"].upper()) + table += "{} | ".format(rec["resolution"] + if rec["resolution"] != rec["ip_dst"] else "--") + table += "{} | ".format(rec["ip_dst"]) + table += "{} | ".format(rec["port_dst"]) + table += "
Protocol | +Domain | +Dst IP Address | +Dst port | +
---|---|---|---|
{} | ".format(rec["proto"].upper()) + table += "{} | ".format(rec["resolution"] + if rec["resolution"] != rec["ip_dst"] else "--") + table += "{} | ".format(rec["ip_dst"]) + table += "{} | ".format(rec["port_dst"]) + table += "
Protocol | +Domain | +Dst IP Address | +Dst port | +
---|---|---|---|
{} | ".format(rec["proto"].upper()) + table += "{} | ".format(rec["resolution"] + if rec["resolution"] != rec["ip_dst"] else "--") + table += "{} | ".format(rec["ip_dst"]) + table += "{} | ".format(rec["port_dst"]) + table += "
Device name: {}
".format(
+ self.device["name"])
+ header += "Device MAC address: {}
".format(
+ self.device["mac_address"])
+ header += "Report generated on {}
".format(
+ datetime.now().strftime("%d/%m/%Y at %H:%M:%S"))
+
+ header += "Capture SHA1: {}
".format(self.capture_sha1)
+ header += "
{}
".format( + alert["description"]) + alerts += "{}
".format( + alert["description"]) + alerts += "{}
".format( + alert["description"]) + alerts += "