diff --git a/Framework/Built_In_Automation/Security/nmap_scan.py b/Framework/Built_In_Automation/Security/nmap_scan.py
index 0c046ac24..a0b190123 100644
--- a/Framework/Built_In_Automation/Security/nmap_scan.py
+++ b/Framework/Built_In_Automation/Security/nmap_scan.py
@@ -8,13 +8,17 @@
from pathlib import Path
import shutil
from datetime import datetime, timedelta
+import socket
+import ssl
+import urllib.request
+import urllib.parse
def run_nmap(ip, output_dir=None):
os.makedirs(output_dir, exist_ok=True)
xml_output_file = os.path.join(output_dir, f"nmap_scan_{ip}.xml")
normal_output_file = os.path.join(output_dir, f"nmap_scan_{ip}.txt")
- process = subprocess.Popen(["nmap", "-sV", "--script", "vuln", "-oX", xml_output_file, "-oN", normal_output_file, ip], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ process = subprocess.Popen(["nmap", "-sV", "-T4", "--open", "--min-rate", "1000", "--script", "vuln", "-oX", xml_output_file, "-oN", normal_output_file, ip], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
spinner = ['|', '/', '-', '\\']
start_time = datetime.now()
@@ -111,13 +115,38 @@ def parse_nmap_output(xml_file):
script_id = script.get("id")
script_output = script.get("output")
- if "CVE" in script_output or "EXPLOIT" in script_output:
+ # Check for vulnerability indicators
+ is_vulnerable = "VULNERABLE" in script_output or "CVE" in script_output or "EXPLOIT" in script_output or "vulnerable" in script_output.lower()
+
+ if is_vulnerable:
cve_matches = re.findall(r'(CVE-\d{4}-\d+)', script_output)
severity_matches = re.findall(r'(\d\.\d)', script_output)
+
+ # Extract description
description_match = re.search(r'VULNERABLE:\s*(.*?)(?=\n\n|\n\s*\|\s*|\Z)', script_output, re.DOTALL)
- description = description_match.group(1).strip() if description_match else "No description available"
+ if not description_match:
+ # Fallback to just the output if regex fails
+ description = script_output[:200] + "..." if len(script_output) > 200 else script_output
+ else:
+ description = description_match.group(1).strip()
- for i in range(len(cve_matches)):
+ # Logic to handle cases with CVEs and without
+ if cve_matches:
+ for i in range(len(cve_matches)):
+ vulnerabilities.append({
+ "ip": ip_address,
+ "hostname": hostname,
+ "port": port_id,
+ "protocol": protocol,
+ "state": state,
+ "service": service_info,
+ "script": script_id,
+ "cve": cve_matches[i],
+ "severity": float(severity_matches[i]) if i < len(severity_matches) else 5.0, # Default to medium if severity not found
+ "description": description
+ })
+ else:
+ # No CVE found but it is a vulnerability
vulnerabilities.append({
"ip": ip_address,
"hostname": hostname,
@@ -126,8 +155,8 @@ def parse_nmap_output(xml_file):
"state": state,
"service": service_info,
"script": script_id,
- "cve": cve_matches[i],
- "severity": float(severity_matches[i]) if i < len(severity_matches) else 0,
+ "cve": "N/A",
+ "severity": 5.0, # Default risk for unknown vulnerabilities
"description": description
})
@@ -135,7 +164,7 @@ def parse_nmap_output(xml_file):
return vulnerabilities, scan_info
-def generate_html(vulnerabilities, scan_info, target_ip, output_dir=None):
+def generate_html(vulnerabilities, scan_info, target_ip, output_dir=None, crypto_data=None):
"""Generate HTML report for security vulnerabilities."""
severity_counts = {
@@ -146,34 +175,43 @@ def generate_html(vulnerabilities, scan_info, target_ip, output_dir=None):
"None (0.0)": 0
}
+ # Calculate Severity Counts
for v in vulnerabilities:
- if v["severity"] >= 8.0:
+ # Ensure severity is a float
+ try:
+ sev = float(v.get("severity", 0))
+ except (ValueError, TypeError):
+ sev = 0.0
+
+ if sev >= 8.0:
severity_counts["Critical (8.0-10.0)"] += 1
- elif v["severity"] >= 6.0:
+ elif sev >= 6.0:
severity_counts["High (6.0-7.9)"] += 1
- elif v["severity"] >= 4.0:
+ elif sev >= 4.0:
severity_counts["Medium (4.0-5.9)"] += 1
- elif v["severity"] > 0:
+ elif sev > 0:
severity_counts["Low (0.1-3.9)"] += 1
else:
severity_counts["None (0.0)"] += 1
+ # JSON Data for Charts
severity_data = [{"level": k, "count": v} for k, v in severity_counts.items()]
json_severity_data = json.dumps(severity_data)
- chart_data = [{"cve": v["cve"], "severity": v["severity"]} for v in vulnerabilities]
+ chart_data = [{"cve": v.get("cve", "N/A"), "severity": v.get("severity", 0)} for v in vulnerabilities]
json_data = json.dumps(chart_data)
service_counts = {}
for v in vulnerabilities:
- service_name = v["service"].split(" ")[0]
+ service_name = v.get("service", "Unknown").split(" ")[0]
service_counts[service_name] = service_counts.get(service_name, 0) + 1
service_data = [{"service": k, "count": v} for k, v in service_counts.items()]
json_service_data = json.dumps(service_data)
port_counts = {}
for v in vulnerabilities:
- port_counts[v["port"]] = port_counts.get(v["port"], 0) + 1
+ port_val = v.get("port", "Unknown")
+ port_counts[port_val] = port_counts.get(port_val, 0) + 1
port_data = [{"port": k, "count": v} for k, v in port_counts.items()]
json_port_data = json.dumps(port_data)
@@ -183,81 +221,126 @@ def generate_html(vulnerabilities, scan_info, target_ip, output_dir=None):
# Calculate scan duration if available
scan_duration = "N/A"
if "start_time" in scan_info and "end_time" in scan_info:
- start_time = datetime.strptime(scan_info["start_time"], "%Y-%m-%d %H:%M:%S")
- end_time = datetime.strptime(scan_info["end_time"], "%Y-%m-%d %H:%M:%S")
- duration = end_time - start_time
- scan_duration = f"{duration.seconds // 60} minutes, {duration.seconds % 60} seconds"
+ try:
+ start_time = datetime.strptime(scan_info["start_time"], "%Y-%m-%d %H:%M:%S")
+ end_time = datetime.strptime(scan_info["end_time"], "%Y-%m-%d %H:%M:%S")
+ duration = end_time - start_time
+ scan_duration = f"{duration.seconds // 60}m {duration.seconds % 60}s"
+ except Exception:
+ pass
- # Calculate risk score (fixed to be between 0-100)
- total_severity = sum(v["severity"] for v in vulnerabilities)
+ # Calculate risk score (0-100)
vuln_count = len(vulnerabilities)
+ is_clean = vuln_count == 0
+
+ risk_score = 0
+ risk_level = "Secure"
+ risk_color = "#10b981" # Green
- if vuln_count > 0:
- # Base score on average severity and number of vulnerabilities
+ if not is_clean:
+ total_severity = sum(float(v.get("severity", 0)) for v in vulnerabilities)
avg_severity = total_severity / vuln_count
- # Scale from 0-10 to 0-70 (severity component)
severity_component = (avg_severity / 10) * 70
- # Scale count component (max out at 20 vulnerabilities)
count_component = min(vuln_count / 20, 1) * 30
risk_score = round(severity_component + count_component)
- # Ensure score is capped at 100
risk_score = min(risk_score, 100)
- else:
- risk_score = 0
-
+
+ if risk_score >= 80:
+ risk_level = "Critical"
+ risk_color = "#dc3545"
+ elif risk_score >= 60:
+ risk_level = "High"
+ risk_color = "#f59e0b"
+ elif risk_score >= 40:
+ risk_level = "Medium"
+ risk_color = "#3b82f6"
+ else:
+ risk_level = "Low"
+ risk_color = "#10b981"
+
+ # Network Info Rows
network_info_rows = ""
for info in scan_info.get("network_info", []):
network_info_rows += f"""
- {info['type']}
- {info['address']}
- {info['vendor']}
+ {info.get('type', 'Unknown')}
+ {info.get('address', 'N/A')}
+ {info.get('vendor', '')}
"""
+
+ # Vulnerability Table Rows
table_rows = ""
- for v in sorted(vulnerabilities, key=lambda x: x['severity'], reverse=True):
- if v['severity'] >= 8.0:
- severity_class = "critical"
- elif v['severity'] >= 6.0:
- severity_class = "high"
- elif v['severity'] >= 4.0:
- severity_class = "medium"
- elif v['severity'] > 0:
- severity_class = "low"
+ sorted_vulns = sorted(vulnerabilities, key=lambda x: float(x.get('severity', 0)), reverse=True)
+
+ for v in sorted_vulns:
+ sev = float(v.get('severity', 0))
+ if sev >= 8.0:
+ severity_class = "severity-critical"
+ sev_label = "CRITICAL"
+ elif sev >= 6.0:
+ severity_class = "severity-high"
+ sev_label = "HIGH"
+ elif sev >= 4.0:
+ severity_class = "severity-medium"
+ sev_label = "MEDIUM"
+ elif sev > 0:
+ severity_class = "severity-low"
+ sev_label = "LOW"
else:
- severity_class = "none"
+ severity_class = "severity-none"
+ sev_label = "INFO"
+
+ cve_display = v.get('cve', 'N/A')
+ cve_link = f'{cve_display} ' if cve_display != "N/A" else "N/A"
table_rows += f"""
- {v['ip']}
- {v['hostname']}
- {v['port']}/{v['protocol']}
- {v['service']}
- {v['cve']}
+ {sev}
-
- {v['severity']}
-
+ {v.get('service', 'Unknown')}
+ {v.get('port', 'N/A')}/{v.get('protocol', 'tcp')}
+
+ {cve_link}
+
+ {v.get('description', 'No description')}
+ Script: {v.get('script', 'Unknown')}
- {v['description']}
"""
-
+
+ # HTML Template Construction
html_template = f"""
- Security Vulnerability Report
+ Security Scan Report - {target_ip}
+
+
+
+
+
+
-