#!/usr/bin/env python3 import os import datetime import mysql.connector from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.units import mm from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable from reportlab.lib.enums import TA_CENTER SEVERITY_COLORS = { "critical": "#c0392b", "high": "#e67e22", "medium": "#f1c40f", "low": "#27ae60", "unknown": "#7f8c8d", } RISK_COLORS = { "CRITICAL": "#c0392b", "HIGH": "#e67e22", "MEDIUM": "#f1c40f", "LOW": "#27ae60", "UNKNOWN": "#7f8c8d", } def get_connection(): return mysql.connector.connect( host="localhost", user="metatron", password="123", database="metatron" ) def fetch_session(sl_no: int) -> dict: conn = get_connection() c = conn.cursor() c.execute("SELECT * FROM history WHERE sl_no = %s", (sl_no,)) history = c.fetchone() c.execute("SELECT * FROM vulnerabilities WHERE sl_no = %s", (sl_no,)) vulns = c.fetchall() c.execute("SELECT * FROM fixes WHERE sl_no = %s", (sl_no,)) fixes = c.fetchall() c.execute("SELECT * FROM exploits_attempted WHERE sl_no = %s", (sl_no,)) exploits = c.fetchall() c.execute("SELECT * FROM summary WHERE sl_no = %s", (sl_no,)) summary = c.fetchone() conn.close() return {"history": history, "vulns": vulns, "fixes": fixes, "exploits": exploits, "summary": summary} def fetch_all_history(): conn = get_connection() c = conn.cursor() c.execute("SELECT sl_no, target, scan_date, status FROM history ORDER BY sl_no DESC") rows = c.fetchall() conn.close() return rows def export_pdf(data: dict, output_dir: str) -> str: h = data["history"] sl = h[0] tgt = h[1] date = str(h[2]) risk = data["summary"][4] if data["summary"] else "UNKNOWN" ai = data["summary"][3] if data["summary"] else "" os.makedirs(output_dir, exist_ok=True) safe = tgt.replace("https://","").replace("http://","").replace("/","_").replace(".","_") filename = os.path.join(output_dir, f"metatron_SL{sl}_{safe}.pdf") doc = SimpleDocTemplate(filename, pagesize=A4, topMargin=15*mm, bottomMargin=15*mm, leftMargin=15*mm, rightMargin=15*mm) title_style = ParagraphStyle("t", fontSize=22, fontName="Helvetica-Bold", textColor=colors.HexColor("#c0392b"), spaceAfter=4) sub_style = ParagraphStyle("s", fontSize=10, fontName="Helvetica", textColor=colors.HexColor("#555555"), spaceAfter=2) h1_style = ParagraphStyle("h1", fontSize=13, fontName="Helvetica-Bold", textColor=colors.HexColor("#2c3e50"), spaceBefore=10, spaceAfter=4) body_style = ParagraphStyle("b", fontSize=9, fontName="Helvetica", textColor=colors.black, leading=13) code_style = ParagraphStyle("c", fontSize=7.5, fontName="Courier", textColor=colors.HexColor("#2c3e50"), backColor=colors.HexColor("#f4f4f4"), leading=11, leftIndent=6, rightIndent=6, spaceBefore=2, spaceAfter=2) footer_style = ParagraphStyle("f", fontSize=7, textColor=colors.HexColor("#aaaaaa"), alignment=TA_CENTER) story = [] story.append(Paragraph("METATRON", title_style)) story.append(Paragraph("AI Penetration Testing Report", sub_style)) story.append(HRFlowable(width="100%", thickness=1.5, color=colors.HexColor("#c0392b"), spaceAfter=8)) risk_color = colors.HexColor(RISK_COLORS.get(risk.upper(), "#7f8c8d")) meta = [["Target", tgt], ["Scan Date", date], ["Session", f"SL# {sl}"], ["Risk Level", risk], ["Generated", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")]] mt = Table(meta, colWidths=[35*mm, 130*mm]) mt.setStyle(TableStyle([ ("FONTNAME", (0,0), (-1,-1), "Helvetica"), ("FONTSIZE", (0,0), (-1,-1), 9), ("FONTNAME", (0,0), (0,-1), "Helvetica-Bold"), ("TEXTCOLOR", (0,0), (0,-1), colors.HexColor("#2c3e50")), ("TEXTCOLOR", (1,3), (1,3), risk_color), ("FONTNAME", (1,3), (1,3), "Helvetica-Bold"), ("ROWBACKGROUNDS", (0,0), (-1,-1), [colors.HexColor("#f9f9f9"), colors.white]), ("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#dddddd")), ("PADDING", (0,0), (-1,-1), 5), ])) story.append(mt) story.append(Spacer(1, 10)) story.append(Paragraph("Vulnerabilities", h1_style)) story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#dddddd"), spaceAfter=6)) if data["vulns"]: vd = [["#", "Vulnerability", "Severity", "Port", "Service"]] for v in data["vulns"]: vd.append([str(v[0]), str(v[2] or "-"), str(v[3] or "-").upper(), str(v[4] or "-"), str(v[5] or "-")]) vt = Table(vd, colWidths=[10*mm, 72*mm, 24*mm, 18*mm, 28*mm], repeatRows=1) vts = [ ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ("FONTSIZE", (0,0), (-1,-1), 8), ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#2c3e50")), ("TEXTCOLOR", (0,0), (-1,0), colors.white), ("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#dddddd")), ("PADDING", (0,0), (-1,-1), 5), ("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.HexColor("#f9f9f9"), colors.white]), ] for i, v in enumerate(data["vulns"], 1): sc = colors.HexColor(SEVERITY_COLORS.get((v[3] or "unknown").lower(), "#7f8c8d")) vts.append(("TEXTCOLOR", (2,i), (2,i), sc)) vts.append(("FONTNAME", (2,i), (2,i), "Helvetica-Bold")) vt.setStyle(TableStyle(vts)) story.append(vt) story.append(Spacer(1, 6)) story.append(Paragraph("Vulnerability Details", h1_style)) story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#dddddd"), spaceAfter=6)) for v in data["vulns"]: sc = colors.HexColor(SEVERITY_COLORS.get((v[3] or "unknown").lower(), "#7f8c8d")) lbl = ParagraphStyle("vl", fontSize=9, fontName="Helvetica-Bold", textColor=sc) story.append(Paragraph(f"[{(v[3] or 'UNKNOWN').upper()}] {v[2]}", lbl)) if v[6]: story.append(Paragraph(str(v[6]), body_style)) story.append(Spacer(1, 4)) else: story.append(Paragraph("No vulnerabilities recorded.", body_style)) story.append(Spacer(1, 6)) story.append(Paragraph("Fixes & Mitigations", h1_style)) story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#dddddd"), spaceAfter=6)) if data["fixes"]: for f in data["fixes"]: story.append(Paragraph(f"Fix for vuln id={f[2]}:", body_style)) story.append(Paragraph(str(f[3] or "-"), code_style)) story.append(Spacer(1, 3)) else: story.append(Paragraph("No fixes recorded.", body_style)) story.append(Spacer(1, 6)) story.append(Paragraph("Exploits Attempted", h1_style)) story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#dddddd"), spaceAfter=6)) if data["exploits"]: ed = [["#", "Exploit", "Tool", "Result"]] for e in data["exploits"]: ed.append([str(e[0]), str(e[2] or "-")[:60], str(e[3] or "-")[:30], str(e[5] or "-")[:30]]) et = Table(ed, colWidths=[10*mm, 80*mm, 40*mm, 28*mm]) et.setStyle(TableStyle([ ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ("FONTSIZE", (0,0), (-1,-1), 8), ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#2c3e50")), ("TEXTCOLOR", (0,0), (-1,0), colors.white), ("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#dddddd")), ("PADDING", (0,0), (-1,-1), 5), ("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.HexColor("#f9f9f9"), colors.white]), ])) story.append(et) else: story.append(Paragraph("No exploits recorded.", body_style)) story.append(Spacer(1, 6)) story.append(Paragraph("AI Analysis Summary", h1_style)) story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#dddddd"), spaceAfter=6)) if ai: for line in str(ai).split("\n"): line = line.strip() if line: story.append(Paragraph(line, body_style)) story.append(Spacer(1, 2)) else: story.append(Paragraph("No AI analysis recorded.", body_style)) story.append(Spacer(1, 10)) story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#dddddd"), spaceAfter=4)) story.append(Paragraph( "Generated by METATRON — AI Penetration Testing Assistant | " "github.com/sooryathejas/METATRON | For authorized use only.", footer_style)) doc.build(story) return filename def export_html(data: dict, output_dir: str) -> str: h = data["history"] sl = h[0] tgt = h[1] date = str(h[2]) risk = data["summary"][4] if data["summary"] else "UNKNOWN" ai = data["summary"][3] if data["summary"] else "" rc = RISK_COLORS.get(risk.upper(), "#7f8c8d") os.makedirs(output_dir, exist_ok=True) safe = tgt.replace("https://","").replace("http://","").replace("/","_").replace(".","_") filename = os.path.join(output_dir, f"metatron_SL{sl}_{safe}.html") vuln_rows = "" for v in data["vulns"]: sc = SEVERITY_COLORS.get((v[3] or "unknown").lower(), "#7f8c8d") vuln_rows += (f"
{f[3] or '-'}{str(e[4] or '-')[:80]}{line}
" for line in str(ai).split("\n") if line.strip()) html = f"""AI Penetration Testing Report
| # | Vulnerability | Severity | Port | Service |
|---|
None recorded.
'}| # | Vuln | Fix | Source |
|---|
None recorded.
'}| # | Exploit | Tool | Payload | Result |
|---|
None recorded.
'}None recorded.
'}