-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreport_generator.py
More file actions
129 lines (104 loc) · 6.34 KB
/
Copy pathreport_generator.py
File metadata and controls
129 lines (104 loc) · 6.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import os
from datetime import datetime
class ReportGenerator:
def generate_html_report(self, nmap_results, httpx_results, vulnerabilities, options, domains_with_descriptions):
"""
Generate an HTML report using Nmap/Naabu results, HTTPX results, and vulnerabilities.
"""
domains_dict = dict(domains_with_descriptions)
try:
nmap_grouped_by_domain = self.group_results_by_domain(nmap_results, options, domains_with_descriptions)
httpx_grouped_by_domain = self.group_results_by_domain(httpx_results, options, domains_with_descriptions)
html_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Security Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.section-title { font-size: 18px; font-weight: bold; margin-top: 20px; }
.domain-title { font-size: 16px; font-weight: bold; margin-top: 10px; }
</style>
</head>
<body>
<h1>Security Report</h1>
"""
html_content += "<div class='section-title'>Nmap/Naabu Results</div>"
for domain, results in nmap_grouped_by_domain.items():
# html_content += f"<div class='domain-title'>Domain: {domain}</div>"
if options.get('exclude_ip', False):
description = domains_dict.get(domain, domain) # Default to domain if no description found
html_content += f"<div class='domain-title'>Description: {description}</div>"
else:
html_content += f"<div class='domain-title'>Domain: {domain}</div>"
html_content += "<table><tr><th>Port</th><th>Service</th></tr>"
for result in results:
ports = ','.join([entry.split(':')[1] for entry in result[3].split() if ':' in entry])
html_content += f"<tr><td>{ports}</td><td>{result[4]}</td></tr>" # Only print extracted Ports and Service
html_content += "</table>"
httpx_section_content = ""
for domain, results in httpx_grouped_by_domain.items():
valid_results = []
for result in results:
if not all(value is None for value in result[2:8]):
valid_results.append(result)
if valid_results:
if options.get('exclude_ip', False):
description = domains_dict.get(domain, domain)
httpx_section_content += f"<div class='domain-title'>Domain: {description}</div>"
else:
httpx_section_content += f"<div class='domain-title'>Domain: {domain}</div>"
httpx_section_content += "<table><tr><th>Subdomain</th><th>Port</th><th>Webserver</th><th>Final URL</th><th>Host</th><th>Tech</th></tr>"
for result in valid_results:
if options.get('exclude_ip', False) and domains_dict.get(result[2]):
# print("----------------------------",result[2])
description = domains_dict.get(result[2])
httpx_section_content += f"<tr><td>{description}</td><td>{result[3]}</td><td>{result[4]}</td><td>{result[5]}</td><td>{result[6]}</td><td>{result[7]}</td></tr>"
else:
httpx_section_content += f"<tr><td>{result[2]}</td><td>{result[3]}</td><td>{result[4]}</td><td>{result[5]}</td><td>{result[6]}</td><td>{result[7]}</td></tr>"
httpx_section_content += "</table>"
# Only print the HTTPX section if there were any valid results
if httpx_section_content:
html_content += "<div class='section-title'>HTTPX Results</div>"
html_content += httpx_section_content
html_content += "<div class='section-title'>Vulnerabilities</div>"
html_content += "<table><tr><th>Subdomain</th><th>URL</th><th>Vulnerability</th><th>Severity</th><th>Description</th></tr>"
for row in vulnerabilities:
if options.get('exclude_ip', False) and domains_dict.get(row[0]):
description = domains_dict.get(row[0])
html_content += f"<tr><td>{description}</td><td>{row[1]}</td><td>{row[2]}</td><td>{row[3]}</td><td>{row[4]}</td></tr>"
else:
html_content += f"<tr><td>{row[0]}</td><td>{row[1]}</td><td>{row[2]}</td><td>{row[3]}</td><td>{row[4]}</td></tr>"
html_content += "</table>"
html_content += """
</body>
</html>
"""
result_dir = "result"
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
html_report_path = os.path.join(result_dir, f'security_report_{timestamp}.html')
# Ensure the result directory exists
os.makedirs(result_dir, exist_ok=True)
# Use the path from `html_report_path` to write the file to the `result` directory
with open(html_report_path, 'w') as report_file:
report_file.write(html_content)
print(f"[INFO] HTML report generated successfully: {html_report_path}")
except Exception as e:
print(f"[ERROR] Failed to generate HTML report: {e}")
def group_results_by_domain(self, results, options, domains_with_descriptions):
"""
Group results by domain. If the --no-ip option is provided, replace IP with the description.
"""
grouped_results = {}
for row in results:
domain = row[0]
if domain not in grouped_results:
grouped_results[domain] = []
grouped_results[domain].append(row)
return grouped_results