Initial commit: AutoPentestX - Complete automated penetration testing toolkit with 8 modules, comprehensive documentation, and professional PDF reporting

This commit is contained in:
gowtham-darkseid
2025-11-30 14:02:38 +05:30
commit 5ab46b1467
26 changed files with 6071 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
"""
AutoPentestX - Automated Penetration Testing Toolkit
Modules Package Initialization
"""
__version__ = "1.0.0"
__author__ = "AutoPentestX Team"
+282
View File
@@ -0,0 +1,282 @@
#!/usr/bin/env python3
"""
AutoPentestX - CVE Lookup Module
Looks up CVE information for discovered services and versions
"""
import requests
import json
import re
from datetime import datetime
import time
class CVELookup:
def __init__(self):
"""Initialize CVE lookup module"""
self.cve_data = []
self.api_url = "https://cve.circl.lu/api"
self.nvd_api = "https://services.nvd.nist.gov/rest/json/cves/2.0"
def search_cve_by_product(self, product, version=""):
"""Search for CVEs by product name and version"""
print(f"[*] Searching CVEs for: {product} {version}")
cves = []
try:
# Clean product name
product_clean = product.lower().strip()
product_clean = re.sub(r'[^\w\s-]', '', product_clean)
# Try CVE CIRCL API
search_url = f"{self.api_url}/search/{product_clean}"
response = requests.get(search_url, timeout=10)
if response.status_code == 200:
data = response.json()
if isinstance(data, list):
# Limit results to most recent/relevant
for cve_entry in data[:10]: # Top 10 results
cve_info = self.parse_cve_entry(cve_entry)
# Filter by version if specified
if version and version.strip():
if self.version_matches(cve_entry, version):
cves.append(cve_info)
else:
cves.append(cve_info)
print(f"[✓] Found {len(cves)} relevant CVEs for {product}")
else:
print(f"[!] CVE API returned status code: {response.status_code}")
# Rate limiting
time.sleep(1)
except requests.exceptions.RequestException as e:
print(f"[!] CVE lookup failed for {product}: {e}")
except Exception as e:
print(f"[!] Error during CVE lookup: {e}")
return cves
def parse_cve_entry(self, cve_entry):
"""Parse CVE entry and extract relevant information"""
try:
cve_id = cve_entry.get('id', 'Unknown')
summary = cve_entry.get('summary', 'No description available')
# Get CVSS score
cvss_score = 0.0
if 'cvss' in cve_entry:
cvss_score = float(cve_entry.get('cvss', 0.0))
elif 'impact' in cve_entry:
if 'baseMetricV3' in cve_entry['impact']:
cvss_score = float(cve_entry['impact']['baseMetricV3'].get('cvssV3', {}).get('baseScore', 0.0))
elif 'baseMetricV2' in cve_entry['impact']:
cvss_score = float(cve_entry['impact']['baseMetricV2'].get('cvssV2', {}).get('baseScore', 0.0))
# Determine risk level
risk_level = self.calculate_risk_level(cvss_score)
# Get published date
published = cve_entry.get('Published', cve_entry.get('published', 'Unknown'))
# Check if exploit is available
exploitable = self.check_exploit_availability(cve_id, cve_entry)
return {
'cve_id': cve_id,
'description': summary[:500], # Limit description length
'cvss_score': cvss_score,
'risk_level': risk_level,
'published_date': published,
'exploitable': exploitable,
'references': cve_entry.get('references', [])[:3] # Top 3 references
}
except Exception as e:
print(f"[!] Error parsing CVE entry: {e}")
return {
'cve_id': 'Unknown',
'description': 'Error parsing CVE data',
'cvss_score': 0.0,
'risk_level': 'UNKNOWN',
'published_date': 'Unknown',
'exploitable': False,
'references': []
}
def calculate_risk_level(self, cvss_score):
"""Calculate risk level based on CVSS score"""
if cvss_score >= 9.0:
return "CRITICAL"
elif cvss_score >= 7.0:
return "HIGH"
elif cvss_score >= 4.0:
return "MEDIUM"
elif cvss_score > 0.0:
return "LOW"
else:
return "UNKNOWN"
def check_exploit_availability(self, cve_id, cve_entry):
"""Check if exploit is publicly available"""
# Check in CVE data
if 'exploit-db' in str(cve_entry).lower():
return True
if 'metasploit' in str(cve_entry).lower():
return True
# Check references
if 'references' in cve_entry:
for ref in cve_entry['references']:
ref_str = str(ref).lower()
if any(keyword in ref_str for keyword in ['exploit', 'poc', 'metasploit', 'exploit-db']):
return True
return False
def version_matches(self, cve_entry, version):
"""Check if CVE applies to specific version"""
try:
# Simple version matching - can be enhanced
cve_text = json.dumps(cve_entry).lower()
version_clean = version.lower().strip()
# Extract version numbers
version_nums = re.findall(r'\d+\.\d+', version_clean)
if version_nums:
for ver in version_nums:
if ver in cve_text:
return True
# If version is mentioned anywhere in CVE
if version_clean in cve_text:
return True
# Default: include if we can't determine
return True
except:
return True
def lookup_services(self, services):
"""Lookup CVEs for multiple services"""
print("\n" + "="*60)
print("AutoPentestX - CVE Lookup")
print("="*60)
print(f"Services to check: {len(services)}")
print("="*60 + "\n")
all_cves = []
for service in services:
port = service.get('port')
service_name = service.get('service', 'unknown')
version = service.get('version', '')
print(f"\n[*] Checking port {port}: {service_name} {version}")
# Extract product name from service
product = self.extract_product_name(service_name, version)
if product and product != 'unknown':
cves = self.search_cve_by_product(product, version)
for cve in cves:
cve['port'] = port
cve['service'] = service_name
cve['version'] = version
all_cves.append(cve)
print(f" [!] {cve['cve_id']} - CVSS: {cve['cvss_score']} ({cve['risk_level']})")
self.cve_data = all_cves
print("\n" + "="*60)
print("CVE LOOKUP SUMMARY")
print("="*60)
print(f"Total CVEs found: {len(all_cves)}")
# Count by risk level
critical = len([c for c in all_cves if c['risk_level'] == 'CRITICAL'])
high = len([c for c in all_cves if c['risk_level'] == 'HIGH'])
medium = len([c for c in all_cves if c['risk_level'] == 'MEDIUM'])
low = len([c for c in all_cves if c['risk_level'] == 'LOW'])
print(f" CRITICAL: {critical}")
print(f" HIGH: {high}")
print(f" MEDIUM: {medium}")
print(f" LOW: {low}")
print("="*60 + "\n")
return all_cves
def extract_product_name(self, service_name, version):
"""Extract clean product name for CVE search"""
# Common product name mappings
product_map = {
'http': 'apache',
'ssh': 'openssh',
'ftp': 'ftp',
'smtp': 'postfix',
'mysql': 'mysql',
'postgresql': 'postgresql',
'microsoft-ds': 'microsoft windows',
'netbios-ssn': 'samba',
'domain': 'bind',
'ssl/http': 'apache',
'https': 'apache'
}
service_lower = service_name.lower()
# Check mapped products
for key, product in product_map.items():
if key in service_lower:
return product
# Try to extract from version string
version_lower = version.lower()
products = ['apache', 'nginx', 'openssh', 'vsftpd', 'proftpd',
'mysql', 'postgresql', 'bind', 'postfix', 'dovecot']
for product in products:
if product in version_lower:
return product
# Return service name if nothing else matches
return service_name if service_name != 'unknown' else None
def get_results(self):
"""Return CVE lookup results"""
return self.cve_data
def save_results(self, filename):
"""Save CVE data to JSON file"""
try:
with open(filename, 'w') as f:
json.dump(self.cve_data, f, indent=4)
print(f"[✓] CVE data saved to {filename}")
except Exception as e:
print(f"[✗] Failed to save CVE data: {e}")
if __name__ == "__main__":
# Test CVE lookup
cve_lookup = CVELookup()
sample_services = [
{'port': 22, 'service': 'ssh', 'version': 'OpenSSH 7.4'},
{'port': 80, 'service': 'http', 'version': 'Apache 2.4.6'}
]
results = cve_lookup.lookup_services(sample_services)
print(f"\nTotal CVEs found: {len(results)}")
+284
View File
@@ -0,0 +1,284 @@
#!/usr/bin/env python3
"""
AutoPentestX - Database Module
Handles SQLite database operations for storing scan results
"""
import sqlite3
import json
from datetime import datetime
import os
class Database:
def __init__(self, db_path="database/autopentestx.db"):
"""Initialize database connection"""
self.db_path = db_path
self.ensure_directory()
self.conn = None
self.cursor = None
self.connect()
self.create_tables()
def ensure_directory(self):
"""Ensure database directory exists"""
db_dir = os.path.dirname(self.db_path)
if db_dir and not os.path.exists(db_dir):
os.makedirs(db_dir)
def connect(self):
"""Establish database connection"""
try:
self.conn = sqlite3.connect(self.db_path)
self.cursor = self.conn.cursor()
print(f"[✓] Database connected: {self.db_path}")
except sqlite3.Error as e:
print(f"[✗] Database connection error: {e}")
raise
def create_tables(self):
"""Create necessary database tables"""
try:
# Scans table
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS scans (
id INTEGER PRIMARY KEY AUTOINCREMENT,
target TEXT NOT NULL,
scan_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
os_detection TEXT,
scan_duration REAL,
total_ports INTEGER,
open_ports INTEGER,
vulnerabilities_found INTEGER,
risk_score TEXT,
status TEXT DEFAULT 'completed'
)
''')
# Ports table
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS ports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
scan_id INTEGER,
port_number INTEGER,
protocol TEXT,
state TEXT,
service_name TEXT,
service_version TEXT,
FOREIGN KEY (scan_id) REFERENCES scans(id)
)
''')
# Vulnerabilities table
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS vulnerabilities (
id INTEGER PRIMARY KEY AUTOINCREMENT,
scan_id INTEGER,
port_number INTEGER,
service_name TEXT,
vuln_name TEXT,
vuln_description TEXT,
cve_id TEXT,
cvss_score REAL,
risk_level TEXT,
exploitable BOOLEAN,
FOREIGN KEY (scan_id) REFERENCES scans(id)
)
''')
# Exploits table
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS exploits (
id INTEGER PRIMARY KEY AUTOINCREMENT,
scan_id INTEGER,
vuln_id INTEGER,
exploit_name TEXT,
exploit_status TEXT,
exploit_result TEXT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (scan_id) REFERENCES scans(id),
FOREIGN KEY (vuln_id) REFERENCES vulnerabilities(id)
)
''')
# Web vulnerabilities table
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS web_vulnerabilities (
id INTEGER PRIMARY KEY AUTOINCREMENT,
scan_id INTEGER,
url TEXT,
vuln_type TEXT,
severity TEXT,
description TEXT,
FOREIGN KEY (scan_id) REFERENCES scans(id)
)
''')
self.conn.commit()
print("[✓] Database tables created successfully")
except sqlite3.Error as e:
print(f"[✗] Error creating tables: {e}")
raise
def insert_scan(self, target, os_detection="Unknown"):
"""Insert new scan record"""
try:
self.cursor.execute('''
INSERT INTO scans (target, os_detection, status)
VALUES (?, ?, 'in_progress')
''', (target, os_detection))
self.conn.commit()
return self.cursor.lastrowid
except sqlite3.Error as e:
print(f"[✗] Error inserting scan: {e}")
return None
def update_scan(self, scan_id, **kwargs):
"""Update scan record with new information"""
try:
updates = []
values = []
for key, value in kwargs.items():
updates.append(f"{key} = ?")
values.append(value)
values.append(scan_id)
query = f"UPDATE scans SET {', '.join(updates)} WHERE id = ?"
self.cursor.execute(query, values)
self.conn.commit()
except sqlite3.Error as e:
print(f"[✗] Error updating scan: {e}")
def insert_port(self, scan_id, port_data):
"""Insert port information"""
try:
self.cursor.execute('''
INSERT INTO ports (scan_id, port_number, protocol, state, service_name, service_version)
VALUES (?, ?, ?, ?, ?, ?)
''', (
scan_id,
port_data.get('port'),
port_data.get('protocol', 'tcp'),
port_data.get('state', 'open'),
port_data.get('service', 'unknown'),
port_data.get('version', 'unknown')
))
self.conn.commit()
except sqlite3.Error as e:
print(f"[✗] Error inserting port: {e}")
def insert_vulnerability(self, scan_id, vuln_data):
"""Insert vulnerability information"""
try:
self.cursor.execute('''
INSERT INTO vulnerabilities
(scan_id, port_number, service_name, vuln_name, vuln_description,
cve_id, cvss_score, risk_level, exploitable)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
scan_id,
vuln_data.get('port'),
vuln_data.get('service'),
vuln_data.get('name'),
vuln_data.get('description'),
vuln_data.get('cve_id'),
vuln_data.get('cvss_score', 0.0),
vuln_data.get('risk_level', 'UNKNOWN'),
vuln_data.get('exploitable', False)
))
self.conn.commit()
return self.cursor.lastrowid
except sqlite3.Error as e:
print(f"[✗] Error inserting vulnerability: {e}")
return None
def insert_web_vulnerability(self, scan_id, web_vuln_data):
"""Insert web vulnerability information"""
try:
self.cursor.execute('''
INSERT INTO web_vulnerabilities
(scan_id, url, vuln_type, severity, description)
VALUES (?, ?, ?, ?, ?)
''', (
scan_id,
web_vuln_data.get('url'),
web_vuln_data.get('type'),
web_vuln_data.get('severity'),
web_vuln_data.get('description')
))
self.conn.commit()
except sqlite3.Error as e:
print(f"[✗] Error inserting web vulnerability: {e}")
def insert_exploit(self, scan_id, vuln_id, exploit_data):
"""Insert exploit attempt information"""
try:
self.cursor.execute('''
INSERT INTO exploits (scan_id, vuln_id, exploit_name, exploit_status, exploit_result)
VALUES (?, ?, ?, ?, ?)
''', (
scan_id,
vuln_id,
exploit_data.get('name'),
exploit_data.get('status'),
exploit_data.get('result')
))
self.conn.commit()
except sqlite3.Error as e:
print(f"[✗] Error inserting exploit: {e}")
def get_scan_data(self, scan_id):
"""Retrieve complete scan data"""
try:
# Get scan info
self.cursor.execute('SELECT * FROM scans WHERE id = ?', (scan_id,))
scan = self.cursor.fetchone()
# Get ports
self.cursor.execute('SELECT * FROM ports WHERE scan_id = ?', (scan_id,))
ports = self.cursor.fetchall()
# Get vulnerabilities
self.cursor.execute('SELECT * FROM vulnerabilities WHERE scan_id = ?', (scan_id,))
vulnerabilities = self.cursor.fetchall()
# Get web vulnerabilities
self.cursor.execute('SELECT * FROM web_vulnerabilities WHERE scan_id = ?', (scan_id,))
web_vulns = self.cursor.fetchall()
# Get exploits
self.cursor.execute('SELECT * FROM exploits WHERE scan_id = ?', (scan_id,))
exploits = self.cursor.fetchall()
return {
'scan': scan,
'ports': ports,
'vulnerabilities': vulnerabilities,
'web_vulnerabilities': web_vulns,
'exploits': exploits
}
except sqlite3.Error as e:
print(f"[✗] Error retrieving scan data: {e}")
return None
def get_all_scans(self):
"""Get list of all scans"""
try:
self.cursor.execute('SELECT * FROM scans ORDER BY scan_date DESC')
return self.cursor.fetchall()
except sqlite3.Error as e:
print(f"[✗] Error retrieving scans: {e}")
return []
def close(self):
"""Close database connection"""
if self.conn:
self.conn.close()
print("[✓] Database connection closed")
if __name__ == "__main__":
# Test database
db = Database()
print("Database module test completed successfully")
db.close()
+315
View File
@@ -0,0 +1,315 @@
#!/usr/bin/env python3
"""
AutoPentestX - Exploit Engine
Safe exploitation module with Metasploit integration
Educational/Lab use only - Safe mode enabled by default
"""
import subprocess
import json
import re
from datetime import datetime
import os
class ExploitEngine:
def __init__(self, safe_mode=True):
"""Initialize exploit engine"""
self.safe_mode = safe_mode
self.exploit_results = []
self.metasploit_available = self.check_metasploit()
# Exploit database (common exploits mapped to vulnerabilities)
self.exploit_db = {
'vsftpd 2.3.4': {
'name': 'vsftpd_234_backdoor',
'module': 'exploit/unix/ftp/vsftpd_234_backdoor',
'description': 'VSFTPD v2.3.4 Backdoor Command Execution',
'safe': True
},
'ProFTPD 1.3.3c': {
'name': 'proftpd_133c_backdoor',
'module': 'exploit/unix/ftp/proftpd_133c_backdoor',
'description': 'ProFTPD 1.3.3c Backdoor',
'safe': True
},
'EternalBlue': {
'name': 'ms17_010_eternalblue',
'module': 'exploit/windows/smb/ms17_010_eternalblue',
'description': 'MS17-010 EternalBlue SMB Remote Windows Kernel Pool Corruption',
'safe': False # Potentially destructive
},
'Shellshock': {
'name': 'apache_mod_cgi_bash_env_exec',
'module': 'exploit/multi/http/apache_mod_cgi_bash_env_exec',
'description': 'Apache mod_cgi Bash Environment Variable Code Injection (Shellshock)',
'safe': True
},
'Drupalgeddon2': {
'name': 'drupalgeddon2',
'module': 'exploit/unix/webapp/drupal_drupalgeddon2',
'description': 'Drupal Drupalgeddon 2 Remote Code Execution',
'safe': True
}
}
def check_metasploit(self):
"""Check if Metasploit is installed"""
try:
result = subprocess.run(['which', 'msfconsole'],
capture_output=True, text=True)
if result.returncode == 0:
print("[✓] Metasploit Framework detected")
return True
else:
print("[!] Metasploit not found - Exploitation features limited")
return False
except Exception as e:
print(f"[!] Error checking Metasploit: {e}")
return False
def match_exploits(self, vulnerabilities, cves):
"""Match vulnerabilities to available exploits"""
print("\n" + "="*60)
print("AutoPentestX - Exploit Matching")
print("="*60)
matched_exploits = []
# Match based on service versions
for vuln in vulnerabilities:
service = vuln.get('service', '').lower()
version = vuln.get('version', '').lower()
# Check exploit database
for key, exploit in self.exploit_db.items():
if key.lower() in f"{service} {version}":
matched_exploits.append({
'vulnerability': vuln,
'exploit': exploit,
'port': vuln.get('port'),
'confidence': 'HIGH'
})
print(f"[✓] Exploit matched: {exploit['name']} for port {vuln.get('port')}")
# Match based on CVEs
for cve in cves:
cve_id = cve.get('cve_id', '')
# Known CVE to exploit mappings
cve_exploits = {
'CVE-2017-0144': 'EternalBlue', # MS17-010
'CVE-2014-6271': 'Shellshock',
'CVE-2018-7600': 'Drupalgeddon2'
}
for cve_pattern, exploit_key in cve_exploits.items():
if cve_pattern in cve_id and exploit_key in self.exploit_db:
matched_exploits.append({
'cve': cve,
'exploit': self.exploit_db[exploit_key],
'port': cve.get('port'),
'confidence': 'MEDIUM'
})
print(f"[✓] Exploit matched: {self.exploit_db[exploit_key]['name']} "
f"for CVE {cve_id}")
print(f"\n[*] Total exploits matched: {len(matched_exploits)}")
return matched_exploits
def run_metasploit_exploit(self, target, port, exploit_module, payload='generic/shell_reverse_tcp'):
"""Execute Metasploit exploit in safe mode"""
if not self.metasploit_available:
return {
'status': 'SKIPPED',
'reason': 'Metasploit not available'
}
if not self.safe_mode:
print("[!] WARNING: Safe mode disabled - This could cause system damage!")
return {
'status': 'BLOCKED',
'reason': 'Exploitation disabled for safety'
}
print(f"[*] Simulating exploit: {exploit_module}")
print(f" Target: {target}:{port}")
print(f" Payload: {payload}")
# In safe mode, we only CHECK if the exploit would work, not actually execute
result = {
'status': 'SIMULATED',
'exploit_module': exploit_module,
'target': target,
'port': port,
'payload': payload,
'timestamp': datetime.now().isoformat(),
'safe_mode': True,
'result': 'Exploit would be executed in non-safe mode'
}
# Create resource script for Metasploit (for reference)
rc_script = self.create_rc_script(target, port, exploit_module, payload)
result['rc_script'] = rc_script
return result
def create_rc_script(self, target, port, exploit_module, payload):
"""Create Metasploit resource script"""
rc_content = f"""# Metasploit Resource Script
# Generated by AutoPentestX
# Target: {target}:{port}
# Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
use {exploit_module}
set RHOSTS {target}
set RPORT {port}
set PAYLOAD {payload}
set LHOST 0.0.0.0
set LPORT 4444
check
# Exploit execution disabled in safe mode
# Uncomment to execute: exploit
"""
# Save RC script
rc_filename = f"exploits/exploit_{target}_{port}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.rc"
try:
os.makedirs('exploits', exist_ok=True)
with open(rc_filename, 'w') as f:
f.write(rc_content)
print(f"[✓] Metasploit RC script saved: {rc_filename}")
except Exception as e:
print(f"[!] Failed to save RC script: {e}")
return rc_filename
def simulate_exploitation(self, matched_exploits, target):
"""Simulate exploitation attempts (safe mode)"""
print("\n" + "="*60)
print("AutoPentestX - Exploitation Simulation")
print("="*60)
print(f"Safe Mode: {'ENABLED' if self.safe_mode else 'DISABLED'}")
print(f"Target: {target}")
print("="*60 + "\n")
if self.safe_mode:
print("[*] Running in SAFE MODE - No actual exploitation will occur")
print("[*] Generating exploit feasibility reports...\n")
exploitation_results = []
for match in matched_exploits:
exploit = match.get('exploit')
port = match.get('port')
confidence = match.get('confidence')
if not exploit:
continue
# Check if exploit is safe to run
if not exploit.get('safe', False) and self.safe_mode:
print(f"[!] Skipping potentially dangerous exploit: {exploit['name']}")
result = {
'port': port,
'exploit_name': exploit['name'],
'status': 'SKIPPED',
'reason': 'Exploit marked as potentially destructive',
'safe_mode': True
}
else:
# Simulate exploit
result = self.run_metasploit_exploit(
target,
port,
exploit.get('module', ''),
'generic/shell_reverse_tcp'
)
result['exploit_name'] = exploit['name']
result['description'] = exploit['description']
result['confidence'] = confidence
exploitation_results.append(result)
print(f"[*] Port {port}: {exploit['name']} - {result['status']}")
self.exploit_results = exploitation_results
print("\n" + "="*60)
print("EXPLOITATION SUMMARY")
print("="*60)
print(f"Exploits matched: {len(matched_exploits)}")
print(f"Exploits simulated: {len(exploitation_results)}")
print(f"Safe mode: {'ENABLED' if self.safe_mode else 'DISABLED'}")
print("="*60 + "\n")
if self.safe_mode:
print("[i] Note: All exploitation was simulated only.")
print("[i] RC scripts generated for manual testing if needed.")
return exploitation_results
def generate_exploit_report(self, filename):
"""Generate exploitation report"""
try:
report = {
'timestamp': datetime.now().isoformat(),
'safe_mode': self.safe_mode,
'metasploit_available': self.metasploit_available,
'exploitation_results': self.exploit_results,
'summary': {
'total_attempts': len(self.exploit_results),
'simulated': len([r for r in self.exploit_results if r.get('status') == 'SIMULATED']),
'skipped': len([r for r in self.exploit_results if r.get('status') == 'SKIPPED']),
'successful': len([r for r in self.exploit_results if r.get('status') == 'SUCCESS'])
}
}
with open(filename, 'w') as f:
json.dump(report, f, indent=4)
print(f"[✓] Exploitation report saved: {filename}")
except Exception as e:
print(f"[✗] Failed to save exploitation report: {e}")
def get_results(self):
"""Return exploitation results"""
return self.exploit_results
if __name__ == "__main__":
print("="*60)
print("AutoPentestX - Exploit Engine Test")
print("="*60)
print("\n[!] WARNING: This tool is for EDUCATIONAL/AUTHORIZED TESTING ONLY")
print("[!] Unauthorized use is ILLEGAL and UNETHICAL\n")
# Test exploit engine
exploit_engine = ExploitEngine(safe_mode=True)
# Sample vulnerabilities
sample_vulns = [
{
'port': 21,
'service': 'ftp',
'version': 'vsftpd 2.3.4',
'name': 'FTP Backdoor'
}
]
sample_cves = [
{
'port': 445,
'cve_id': 'CVE-2017-0144',
'service': 'microsoft-ds'
}
]
# Match exploits
matched = exploit_engine.match_exploits(sample_vulns, sample_cves)
# Simulate exploitation
if matched:
results = exploit_engine.simulate_exploitation(matched, "192.168.1.100")
exploit_engine.generate_exploit_report("exploits/test_exploit_report.json")
+546
View File
@@ -0,0 +1,546 @@
#!/usr/bin/env python3
"""
AutoPentestX - PDF Report Generator
Generates professional penetration testing reports using ReportLab
"""
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter, A4
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, PageBreak, Image
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.pdfgen import canvas
from datetime import datetime
import os
class PDFReportGenerator:
def __init__(self, target, scan_id):
"""Initialize PDF report generator"""
self.target = target
self.scan_id = scan_id
self.timestamp = datetime.now()
self.filename = f"reports/AutoPentestX_Report_{target.replace('.', '_')}_{self.timestamp.strftime('%Y%m%d_%H%M%S')}.pdf"
# Ensure reports directory exists
os.makedirs('reports', exist_ok=True)
# Initialize document
self.doc = SimpleDocTemplate(self.filename, pagesize=letter)
self.story = []
self.styles = getSampleStyleSheet()
# Custom styles
self.create_custom_styles()
def create_custom_styles(self):
"""Create custom paragraph styles"""
# Title style
self.styles.add(ParagraphStyle(
name='CustomTitle',
parent=self.styles['Heading1'],
fontSize=24,
textColor=colors.HexColor('#1a1a1a'),
spaceAfter=30,
alignment=TA_CENTER,
fontName='Helvetica-Bold'
))
# Section heading style
self.styles.add(ParagraphStyle(
name='SectionHeading',
parent=self.styles['Heading2'],
fontSize=16,
textColor=colors.HexColor('#2c3e50'),
spaceAfter=12,
spaceBefore=12,
fontName='Helvetica-Bold'
))
# Risk level styles
self.styles.add(ParagraphStyle(
name='CriticalRisk',
parent=self.styles['Normal'],
fontSize=12,
textColor=colors.red,
fontName='Helvetica-Bold'
))
self.styles.add(ParagraphStyle(
name='HighRisk',
parent=self.styles['Normal'],
fontSize=12,
textColor=colors.orangered,
fontName='Helvetica-Bold'
))
self.styles.add(ParagraphStyle(
name='MediumRisk',
parent=self.styles['Normal'],
fontSize=12,
textColor=colors.orange,
fontName='Helvetica-Bold'
))
self.styles.add(ParagraphStyle(
name='LowRisk',
parent=self.styles['Normal'],
fontSize=12,
textColor=colors.blue,
fontName='Helvetica-Bold'
))
def add_cover_page(self, tester_name="AutoPentestX Team"):
"""Add cover page to report"""
# Title
title = Paragraph("PENETRATION TESTING REPORT", self.styles['CustomTitle'])
self.story.append(title)
self.story.append(Spacer(1, 0.5*inch))
# Target information
target_info = f"""
<para align=center fontSize=14>
<b>Target System:</b> {self.target}<br/>
<b>Scan ID:</b> {self.scan_id}<br/>
<b>Report Date:</b> {self.timestamp.strftime('%B %d, %Y')}<br/>
<b>Report Time:</b> {self.timestamp.strftime('%H:%M:%S %Z')}<br/>
</para>
"""
self.story.append(Paragraph(target_info, self.styles['Normal']))
self.story.append(Spacer(1, 1*inch))
# Confidential notice
confidential = """
<para align=center fontSize=12 textColor=red>
<b>CONFIDENTIAL</b><br/>
This report contains sensitive security information.<br/>
Handle with appropriate care and restrict distribution.
</para>
"""
self.story.append(Paragraph(confidential, self.styles['Normal']))
self.story.append(Spacer(1, 0.5*inch))
# Tester information
tester_info = f"""
<para align=center fontSize=12>
<b>Prepared by:</b> {tester_name}<br/>
<b>Tool:</b> AutoPentestX v1.0<br/>
<b>Framework:</b> Automated Penetration Testing Toolkit
</para>
"""
self.story.append(Paragraph(tester_info, self.styles['Normal']))
self.story.append(PageBreak())
def add_executive_summary(self, risk_summary):
"""Add executive summary section"""
self.story.append(Paragraph("EXECUTIVE SUMMARY", self.styles['SectionHeading']))
overall_risk = risk_summary.get('overall_risk_level', 'UNKNOWN')
total_vulns = risk_summary.get('total_vulnerabilities', 0)
summary_text = f"""
<para align=justify>
This penetration testing report presents the findings of an automated security assessment
conducted on the target system <b>{self.target}</b>. The assessment was performed on
{self.timestamp.strftime('%B %d, %Y')} using the AutoPentestX automated penetration testing toolkit.
<br/><br/>
<b>Overall Risk Level: </b><font color="{self.get_risk_color(overall_risk)}">{overall_risk}</font><br/>
<b>Total Vulnerabilities Identified: </b>{total_vulns}<br/>
<b>Critical/High Risk Items: </b>{len(risk_summary.get('high_risk_items', []))}<br/>
<b>Web Vulnerabilities: </b>{risk_summary.get('web_vulnerabilities', 0)}<br/>
<b>SQL Injection Points: </b>{risk_summary.get('sql_vulnerabilities', 0)}<br/>
</para>
"""
self.story.append(Paragraph(summary_text, self.styles['Normal']))
self.story.append(Spacer(1, 0.3*inch))
# Risk assessment summary
if overall_risk in ['CRITICAL', 'HIGH']:
warning = f"""
<para align=justify textColor=red>
<b>⚠ CRITICAL FINDING:</b> The target system exhibits {overall_risk} risk level.
Immediate remediation action is required to address identified security vulnerabilities
before the system can be considered secure for production use.
</para>
"""
self.story.append(Paragraph(warning, self.styles['Normal']))
self.story.append(Spacer(1, 0.3*inch))
def add_scan_details(self, scan_data):
"""Add scan details section"""
self.story.append(Paragraph("SCAN DETAILS", self.styles['SectionHeading']))
os_detection = scan_data.get('os_detection', 'Unknown')
scan_time = scan_data.get('scan_time', 0) or 0
total_ports = len(scan_data.get('ports', []))
details_text = f"""
<para>
<b>Target:</b> {self.target}<br/>
<b>Operating System:</b> {os_detection}<br/>
<b>Scan Duration:</b> {scan_time:.2f} seconds<br/>
<b>Total Open Ports:</b> {total_ports}<br/>
<b>Scan Method:</b> Automated comprehensive scan using Nmap, Nikto, and SQLMap<br/>
</para>
"""
self.story.append(Paragraph(details_text, self.styles['Normal']))
self.story.append(Spacer(1, 0.3*inch))
def add_open_ports_table(self, ports_data):
"""Add table of open ports"""
self.story.append(Paragraph("OPEN PORTS AND SERVICES", self.styles['SectionHeading']))
if not ports_data:
self.story.append(Paragraph("No open ports detected.", self.styles['Normal']))
return
# Create table data
table_data = [['Port', 'Protocol', 'State', 'Service', 'Version']]
for port in ports_data[:20]: # Limit to 20 ports for readability
table_data.append([
str(port.get('port', '')),
port.get('protocol', 'tcp'),
port.get('state', 'open'),
port.get('service', 'unknown'),
port.get('version', 'unknown')[:30] # Truncate long versions
])
# Create table
table = Table(table_data, colWidths=[0.8*inch, 1*inch, 0.8*inch, 1.5*inch, 2.5*inch])
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 10),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
('GRID', (0, 0), (-1, -1), 1, colors.black),
('FONTSIZE', (0, 1), (-1, -1), 8),
]))
self.story.append(table)
self.story.append(Spacer(1, 0.3*inch))
def add_vulnerabilities_table(self, vulnerabilities, cves):
"""Add vulnerabilities table"""
self.story.append(PageBreak())
self.story.append(Paragraph("VULNERABILITIES IDENTIFIED", self.styles['SectionHeading']))
all_vulns = []
# Add regular vulnerabilities
for vuln in vulnerabilities:
all_vulns.append({
'port': vuln.get('port', 'N/A'),
'name': vuln.get('name', 'Unknown'),
'severity': vuln.get('severity', 'UNKNOWN'),
'cve_id': vuln.get('cve_id', 'N/A'),
'description': vuln.get('description', '')[:100]
})
# Add CVEs
for cve in cves[:15]: # Limit CVEs
all_vulns.append({
'port': cve.get('port', 'N/A'),
'name': cve.get('cve_id', 'Unknown'),
'severity': cve.get('risk_level', 'UNKNOWN'),
'cve_id': cve.get('cve_id', 'N/A'),
'description': cve.get('description', '')[:100]
})
if not all_vulns:
self.story.append(Paragraph("No vulnerabilities detected.", self.styles['Normal']))
return
# Create table
table_data = [['Port', 'Vulnerability', 'Severity', 'CVE ID']]
for vuln in all_vulns[:25]: # Limit to 25 for space
table_data.append([
str(vuln['port']),
vuln['name'][:40],
vuln['severity'],
vuln['cve_id']
])
table = Table(table_data, colWidths=[0.7*inch, 2.5*inch, 1*inch, 1.5*inch])
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 10),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('GRID', (0, 0), (-1, -1), 1, colors.black),
('FONTSIZE', (0, 1), (-1, -1), 8),
]))
self.story.append(table)
self.story.append(Spacer(1, 0.3*inch))
def add_risk_assessment(self, risk_summary):
"""Add risk assessment section"""
self.story.append(PageBreak())
self.story.append(Paragraph("RISK ASSESSMENT", self.styles['SectionHeading']))
overall_risk = risk_summary.get('overall_risk_level', 'UNKNOWN')
total_risk_score = risk_summary.get('total_risk_score', 0)
risk_text = f"""
<para align=justify>
Based on the comprehensive analysis of identified vulnerabilities, their severity levels,
exploitability, and potential impact, the overall risk assessment for the target system is:
<br/><br/>
<b>Overall Risk Level:</b> <font color="{self.get_risk_color(overall_risk)}">{overall_risk}</font><br/>
<b>Total Risk Score:</b> {total_risk_score:.2f}<br/>
<b>Average Risk per Port:</b> {risk_summary.get('average_risk_per_port', 0):.2f}<br/>
</para>
"""
self.story.append(Paragraph(risk_text, self.styles['Normal']))
self.story.append(Spacer(1, 0.2*inch))
# High risk items
high_risk_items = risk_summary.get('high_risk_items', [])
if high_risk_items:
self.story.append(Paragraph("<b>High Risk Items:</b>", self.styles['Normal']))
for item in high_risk_items[:10]:
if isinstance(item, dict):
if 'port' in item:
item_text = f"• Port {item.get('port')}: {item.get('service', 'Unknown')} - Risk Score: {item.get('risk_score', 0)}/10"
else:
item_text = f"{item.get('category', 'Unknown')}: {item.get('count', 0)} issues found"
self.story.append(Paragraph(item_text, self.styles['Normal']))
self.story.append(Spacer(1, 0.2*inch))
def add_exploitation_results(self, exploit_results):
"""Add exploitation results section"""
self.story.append(Paragraph("EXPLOITATION ASSESSMENT", self.styles['SectionHeading']))
if not exploit_results:
self.story.append(Paragraph("No exploitation attempts were made.", self.styles['Normal']))
return
exploit_text = f"""
<para align=justify>
The following exploitation scenarios were evaluated in SAFE MODE.
No actual exploitation was performed to prevent system damage.
<br/><br/>
<b>Total Exploits Identified:</b> {len(exploit_results)}<br/>
</para>
"""
self.story.append(Paragraph(exploit_text, self.styles['Normal']))
self.story.append(Spacer(1, 0.2*inch))
# List exploits
for exploit in exploit_results[:10]:
exploit_info = f"""
<para>
<b>• Port {exploit.get('port')}:</b> {exploit.get('exploit_name', 'Unknown')}<br/>
&nbsp;&nbsp;<i>Status:</i> {exploit.get('status', 'Unknown')}<br/>
&nbsp;&nbsp;<i>Description:</i> {exploit.get('description', 'N/A')[:100]}<br/>
</para>
"""
self.story.append(Paragraph(exploit_info, self.styles['Normal']))
self.story.append(Spacer(1, 0.2*inch))
def add_recommendations(self, recommendations):
"""Add security recommendations"""
self.story.append(PageBreak())
self.story.append(Paragraph("SECURITY RECOMMENDATIONS", self.styles['SectionHeading']))
if not recommendations:
self.story.append(Paragraph("No specific recommendations available.", self.styles['Normal']))
return
intro = """
<para align=justify>
Based on the identified vulnerabilities and risk assessment, the following remediation
actions are recommended to improve the security posture of the target system:
</para>
"""
self.story.append(Paragraph(intro, self.styles['Normal']))
self.story.append(Spacer(1, 0.2*inch))
# Group by priority
priorities = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']
for priority in priorities:
priority_recs = [r for r in recommendations if r.get('priority') == priority]
if priority_recs:
self.story.append(Paragraph(f"<b>{priority} Priority:</b>", self.styles['Normal']))
for rec in priority_recs[:5]:
rec_text = f"""
<para>
<b>• {rec.get('action', 'Unknown Action')}</b><br/>
&nbsp;&nbsp;{rec.get('description', 'No description')}<br/>
</para>
"""
self.story.append(Paragraph(rec_text, self.styles['Normal']))
self.story.append(Spacer(1, 0.15*inch))
def add_conclusion(self):
"""Add conclusion section"""
self.story.append(PageBreak())
self.story.append(Paragraph("CONCLUSION", self.styles['SectionHeading']))
conclusion_text = """
<para align=justify>
This automated penetration testing assessment has identified various security vulnerabilities
and potential risks in the target system. The findings should be carefully reviewed and
prioritized based on the risk levels assigned.
<br/><br/>
It is strongly recommended to address all CRITICAL and HIGH severity findings immediately,
followed by MEDIUM and LOW severity items according to available resources and priorities.
<br/><br/>
Regular security assessments should be conducted to maintain a strong security posture
and protect against emerging threats.
<br/><br/>
<b>Important Notes:</b><br/>
• This assessment was conducted using automated tools and may not identify all vulnerabilities<br/>
• Manual verification and testing is recommended for critical systems<br/>
• Results should be validated before taking remediation actions<br/>
• This report is confidential and should be handled securely<br/>
</para>
"""
self.story.append(Paragraph(conclusion_text, self.styles['Normal']))
def add_disclaimer(self):
"""Add legal disclaimer"""
self.story.append(Spacer(1, 0.5*inch))
disclaimer_text = """
<para align=justify fontSize=9 textColor=grey>
<b>DISCLAIMER:</b> This penetration testing report is provided for educational and authorized
security assessment purposes only. The tools and techniques used are intended for legitimate
security testing in controlled environments with proper authorization. Unauthorized use of
these tools against systems you do not own or have explicit permission to test is illegal
and unethical. The developers and users of AutoPentestX assume no liability for misuse or
damage caused by this tool.
</para>
"""
self.story.append(Paragraph(disclaimer_text, self.styles['Normal']))
def get_risk_color(self, risk_level):
"""Get color code for risk level"""
colors_map = {
'CRITICAL': 'red',
'HIGH': 'orangered',
'MEDIUM': 'orange',
'LOW': 'blue',
'MINIMAL': 'green',
'UNKNOWN': 'grey'
}
return colors_map.get(risk_level, 'black')
def generate_report(self, scan_data, vulnerabilities, cves, web_vulns, sql_vulns,
risk_summary, exploit_results, tester_name="AutoPentestX Team"):
"""Generate complete PDF report"""
print("\n" + "="*60)
print("AutoPentestX - PDF Report Generation")
print("="*60)
print(f"Target: {self.target}")
print(f"Generating report: {self.filename}")
print("="*60 + "\n")
try:
# Build report sections
print("[*] Adding cover page...")
self.add_cover_page(tester_name)
print("[*] Adding executive summary...")
self.add_executive_summary(risk_summary)
print("[*] Adding scan details...")
self.add_scan_details(scan_data)
print("[*] Adding open ports table...")
self.add_open_ports_table(scan_data.get('ports', []))
print("[*] Adding vulnerabilities...")
self.add_vulnerabilities_table(vulnerabilities, cves)
print("[*] Adding risk assessment...")
self.add_risk_assessment(risk_summary)
print("[*] Adding exploitation results...")
self.add_exploitation_results(exploit_results)
print("[*] Adding recommendations...")
self.add_recommendations(risk_summary.get('recommendations', []))
print("[*] Adding conclusion...")
self.add_conclusion()
print("[*] Adding disclaimer...")
self.add_disclaimer()
# Build PDF
print("[*] Building PDF document...")
self.doc.build(self.story)
print("\n" + "="*60)
print("PDF REPORT GENERATED SUCCESSFULLY")
print("="*60)
print(f"Report saved to: {self.filename}")
print(f"File size: {os.path.getsize(self.filename) / 1024:.2f} KB")
print("="*60 + "\n")
return self.filename
except Exception as e:
print(f"[✗] Error generating PDF report: {e}")
import traceback
traceback.print_exc()
return None
if __name__ == "__main__":
# Test PDF generator
print("Testing PDF Report Generator...")
sample_scan = {
'target': '192.168.1.100',
'os_detection': 'Linux Ubuntu 20.04',
'scan_time': 45.67,
'ports': [
{'port': 22, 'protocol': 'tcp', 'state': 'open', 'service': 'ssh', 'version': 'OpenSSH 8.2'},
{'port': 80, 'protocol': 'tcp', 'state': 'open', 'service': 'http', 'version': 'Apache 2.4.41'}
]
}
sample_vulns = [
{'port': 22, 'name': 'Outdated SSH', 'severity': 'MEDIUM', 'cve_id': 'N/A', 'description': 'SSH version is outdated'}
]
sample_risk = {
'overall_risk_level': 'MEDIUM',
'total_risk_score': 15.5,
'average_risk_per_port': 7.75,
'high_risk_items': [],
'total_vulnerabilities': 1,
'web_vulnerabilities': 0,
'sql_vulnerabilities': 0,
'recommendations': [
{'priority': 'HIGH', 'action': 'Update SSH', 'description': 'Update to latest version'}
]
}
generator = PDFReportGenerator('192.168.1.100', 1)
generator.generate_report(sample_scan, sample_vulns, [], [], [], sample_risk, [])
+300
View File
@@ -0,0 +1,300 @@
#!/usr/bin/env python3
"""
AutoPentestX - Risk Assessment Engine
Calculates overall risk scores based on vulnerabilities and CVSS scores
"""
from collections import defaultdict
import json
class RiskEngine:
def __init__(self):
"""Initialize risk engine"""
self.risk_scores = {
'CRITICAL': 10,
'HIGH': 7,
'MEDIUM': 4,
'LOW': 2,
'UNKNOWN': 1
}
self.severity_weights = {
'exploitable': 2.0,
'public_exploit': 1.5,
'network_accessible': 1.3,
'authenticated': 0.7
}
def calculate_cvss_risk(self, cvss_score):
"""Convert CVSS score to risk level"""
if cvss_score >= 9.0:
return "CRITICAL"
elif cvss_score >= 7.0:
return "HIGH"
elif cvss_score >= 4.0:
return "MEDIUM"
elif cvss_score > 0.0:
return "LOW"
else:
return "UNKNOWN"
def calculate_port_risk(self, port_data, vulnerabilities, cves):
"""Calculate risk for a specific port"""
risk_score = 0
risk_factors = []
port_num = port_data.get('port')
service = port_data.get('service', '').lower()
# Base risk for port exposure
if port_num < 1024: # Well-known ports
risk_score += 1
risk_factors.append("Well-known port exposed")
# Check for sensitive services
sensitive_services = ['ftp', 'telnet', 'smtp', 'mysql', 'postgresql',
'microsoft-ds', 'netbios-ssn', 'rdp']
if any(svc in service for svc in sensitive_services):
risk_score += 2
risk_factors.append(f"Sensitive service exposed: {service}")
# Check vulnerabilities for this port
port_vulns = [v for v in vulnerabilities if v.get('port') == port_num]
for vuln in port_vulns:
severity = vuln.get('severity', 'UNKNOWN')
risk_score += self.risk_scores.get(severity, 1)
risk_factors.append(f"{severity} vulnerability: {vuln.get('name', 'Unknown')}")
if vuln.get('exploitable', False):
risk_score *= 1.5
risk_factors.append("Exploitable vulnerability detected")
# Check CVEs for this port
port_cves = [c for c in cves if c.get('port') == port_num]
for cve in port_cves:
cvss = cve.get('cvss_score', 0)
risk_score += cvss / 2 # Weight CVE score
if cve.get('exploitable', False):
risk_score *= 1.3
risk_factors.append(f"CVE with public exploit: {cve.get('cve_id')}")
# Normalize to 0-10 scale
normalized_score = min(risk_score, 10.0)
return {
'port': port_num,
'service': service,
'risk_score': round(normalized_score, 2),
'risk_level': self.calculate_cvss_risk(normalized_score),
'risk_factors': risk_factors
}
def calculate_overall_risk(self, scan_data, vulnerabilities, cves, web_vulns, sql_vulns):
"""Calculate overall system risk score"""
print("\n" + "="*60)
print("AutoPentestX - Risk Assessment")
print("="*60)
total_risk = 0
high_risk_items = []
port_risks = []
# Analyze each port
ports = scan_data.get('ports', [])
for port in ports:
port_risk = self.calculate_port_risk(port, vulnerabilities, cves)
port_risks.append(port_risk)
total_risk += port_risk['risk_score']
if port_risk['risk_level'] in ['CRITICAL', 'HIGH']:
high_risk_items.append(port_risk)
print(f"[!] HIGH RISK: Port {port_risk['port']} - {port_risk['service']} "
f"(Score: {port_risk['risk_score']}/10)")
# Add web vulnerabilities to risk
web_risk = len(web_vulns) * 2 # Each web vuln adds 2 points
total_risk += web_risk
if web_vulns:
print(f"[!] Web vulnerabilities detected: {len(web_vulns)} issues")
high_risk_items.append({
'category': 'Web Security',
'risk_score': web_risk,
'count': len(web_vulns)
})
# Add SQL injection vulnerabilities (highest risk)
sql_risk = len(sql_vulns) * 5 # SQL injection is critical
total_risk += sql_risk
if sql_vulns:
print(f"[!] CRITICAL: SQL Injection vulnerabilities found: {len(sql_vulns)}")
high_risk_items.append({
'category': 'SQL Injection',
'risk_score': sql_risk,
'count': len(sql_vulns),
'risk_level': 'CRITICAL'
})
# Calculate average risk per port
avg_risk = total_risk / len(ports) if ports else 0
# Determine overall risk level
overall_risk_level = self.determine_overall_risk_level(
total_risk, avg_risk, high_risk_items
)
# Risk summary
risk_summary = {
'total_risk_score': round(total_risk, 2),
'average_risk_per_port': round(avg_risk, 2),
'overall_risk_level': overall_risk_level,
'high_risk_items': high_risk_items,
'port_risks': port_risks,
'total_vulnerabilities': len(vulnerabilities) + len(cves),
'web_vulnerabilities': len(web_vulns),
'sql_vulnerabilities': len(sql_vulns),
'recommendations': self.generate_recommendations(
overall_risk_level, high_risk_items, vulnerabilities, cves
)
}
# Print summary
print("\n" + "="*60)
print("RISK ASSESSMENT SUMMARY")
print("="*60)
print(f"Overall Risk Level: {overall_risk_level}")
print(f"Total Risk Score: {risk_summary['total_risk_score']}")
print(f"Average Risk per Port: {risk_summary['average_risk_per_port']}")
print(f"High Risk Items: {len(high_risk_items)}")
print(f"Total Vulnerabilities: {risk_summary['total_vulnerabilities']}")
print("="*60 + "\n")
return risk_summary
def determine_overall_risk_level(self, total_risk, avg_risk, high_risk_items):
"""Determine overall system risk level"""
# Count critical and high risk items
critical_count = len([item for item in high_risk_items
if item.get('risk_level') == 'CRITICAL'])
high_count = len([item for item in high_risk_items
if item.get('risk_level') == 'HIGH'])
# Decision logic
if critical_count > 0 or total_risk > 50:
return "CRITICAL"
elif high_count >= 3 or total_risk > 30:
return "HIGH"
elif avg_risk > 4 or total_risk > 15:
return "MEDIUM"
elif total_risk > 5:
return "LOW"
else:
return "MINIMAL"
def generate_recommendations(self, risk_level, high_risk_items, vulnerabilities, cves):
"""Generate security recommendations based on findings"""
recommendations = []
# General recommendations by risk level
if risk_level in ['CRITICAL', 'HIGH']:
recommendations.append({
'priority': 'CRITICAL',
'action': 'Immediate Action Required',
'description': 'Critical vulnerabilities detected. Isolate system and patch immediately.'
})
# Specific recommendations based on vulnerabilities
vuln_types = defaultdict(int)
for vuln in vulnerabilities:
vuln_types[vuln.get('service', 'unknown')] += 1
for service, count in vuln_types.items():
if count > 0:
recommendations.append({
'priority': 'HIGH',
'action': f'Update {service} service',
'description': f'Found {count} vulnerabilities in {service}. Update to latest version.'
})
# CVE-based recommendations
critical_cves = [cve for cve in cves if cve.get('risk_level') == 'CRITICAL']
if critical_cves:
recommendations.append({
'priority': 'CRITICAL',
'action': 'Patch Critical CVEs',
'description': f'Apply security patches for {len(critical_cves)} critical CVEs.'
})
# SQL Injection recommendations
if any('sql' in str(item).lower() for item in high_risk_items):
recommendations.append({
'priority': 'CRITICAL',
'action': 'Fix SQL Injection Vulnerabilities',
'description': 'Implement parameterized queries and input validation immediately.'
})
# General security recommendations
recommendations.extend([
{
'priority': 'MEDIUM',
'action': 'Enable Firewall',
'description': 'Configure firewall to restrict access to necessary ports only.'
},
{
'priority': 'MEDIUM',
'action': 'Update All Services',
'description': 'Ensure all services are running latest stable versions.'
},
{
'priority': 'LOW',
'action': 'Implement Monitoring',
'description': 'Set up intrusion detection and continuous monitoring.'
},
{
'priority': 'LOW',
'action': 'Security Hardening',
'description': 'Apply security hardening guidelines for the operating system.'
}
])
return recommendations
def save_risk_assessment(self, risk_summary, filename):
"""Save risk assessment to JSON file"""
try:
with open(filename, 'w') as f:
json.dump(risk_summary, f, indent=4)
print(f"[✓] Risk assessment saved to {filename}")
except Exception as e:
print(f"[✗] Failed to save risk assessment: {e}")
if __name__ == "__main__":
# Test risk engine
risk_engine = RiskEngine()
sample_scan = {
'ports': [
{'port': 22, 'service': 'ssh'},
{'port': 80, 'service': 'http'},
{'port': 3306, 'service': 'mysql'}
]
}
sample_vulns = [
{'port': 22, 'name': 'Outdated SSH', 'severity': 'MEDIUM', 'exploitable': False},
{'port': 3306, 'name': 'MySQL Exposed', 'severity': 'HIGH', 'exploitable': True}
]
sample_cves = [
{'port': 22, 'cve_id': 'CVE-2021-1234', 'cvss_score': 7.5, 'exploitable': False}
]
results = risk_engine.calculate_overall_risk(sample_scan, sample_vulns, sample_cves, [], [])
print(json.dumps(results, indent=2))
+221
View File
@@ -0,0 +1,221 @@
#!/usr/bin/env python3
"""
AutoPentestX - Network Scanner Module
Handles port scanning, OS detection, and service enumeration using Nmap
"""
import nmap
import subprocess
import json
import re
from datetime import datetime
class Scanner:
def __init__(self, target):
"""Initialize scanner with target"""
self.target = target
self.nm = nmap.PortScanner()
self.scan_results = {
'target': target,
'os_detection': 'Unknown',
'ports': [],
'services': [],
'scan_time': None
}
def validate_target(self):
"""Validate target IP or domain"""
try:
# Try to resolve the target
import socket
socket.gethostbyname(self.target)
return True
except socket.gaierror:
print(f"[✗] Invalid target: {self.target}")
return False
def detect_os(self):
"""Detect operating system using Nmap"""
print(f"[*] Detecting operating system for {self.target}...")
try:
# Run OS detection with Nmap (requires root/sudo)
self.nm.scan(self.target, arguments='-O -Pn')
if self.target in self.nm.all_hosts():
if 'osmatch' in self.nm[self.target]:
os_matches = self.nm[self.target]['osmatch']
if os_matches:
os_name = os_matches[0]['name']
accuracy = os_matches[0]['accuracy']
self.scan_results['os_detection'] = f"{os_name} (Accuracy: {accuracy}%)"
print(f"[✓] OS Detected: {os_name} ({accuracy}% accuracy)")
return self.scan_results['os_detection']
# Fallback: Try using TTL values
result = subprocess.run(['ping', '-c', '1', self.target],
capture_output=True, text=True, timeout=5)
if result.returncode == 0:
ttl_match = re.search(r'ttl=(\d+)', result.stdout.lower())
if ttl_match:
ttl = int(ttl_match.group(1))
if ttl <= 64:
self.scan_results['os_detection'] = "Linux/Unix (TTL <= 64)"
elif ttl <= 128:
self.scan_results['os_detection'] = "Windows (TTL <= 128)"
else:
self.scan_results['os_detection'] = "Unknown (TTL > 128)"
print(f"[✓] OS Detected (TTL-based): {self.scan_results['os_detection']}")
return self.scan_results['os_detection']
self.scan_results['os_detection'] = "Unknown"
print("[!] Could not detect OS reliably")
return "Unknown"
except Exception as e:
print(f"[!] OS Detection failed: {e}")
self.scan_results['os_detection'] = "Unknown"
return "Unknown"
def scan_all_ports(self):
"""Perform comprehensive port scan"""
print(f"[*] Scanning all TCP ports on {self.target}...")
try:
start_time = datetime.now()
# Scan top 1000 ports first (faster)
print("[*] Phase 1: Scanning top 1000 ports...")
self.nm.scan(self.target, arguments='-sS -sV -T4 -Pn --top-ports 1000')
if self.target in self.nm.all_hosts():
host = self.nm[self.target]
# Process TCP ports
if 'tcp' in host:
for port in host['tcp'].keys():
port_info = host['tcp'][port]
if port_info['state'] == 'open':
port_data = {
'port': port,
'protocol': 'tcp',
'state': port_info['state'],
'service': port_info.get('name', 'unknown'),
'version': port_info.get('product', '') + ' ' + port_info.get('version', ''),
'extrainfo': port_info.get('extrainfo', '')
}
self.scan_results['ports'].append(port_data)
print(f"[✓] Port {port}/tcp open - {port_data['service']} {port_data['version']}")
# Process UDP ports (limited scan for speed)
print("[*] Phase 2: Scanning common UDP ports...")
self.nm.scan(self.target, arguments='-sU -Pn --top-ports 20')
if 'udp' in self.nm[self.target]:
for port in self.nm[self.target]['udp'].keys():
port_info = self.nm[self.target]['udp'][port]
if port_info['state'] in ['open', 'open|filtered']:
port_data = {
'port': port,
'protocol': 'udp',
'state': port_info['state'],
'service': port_info.get('name', 'unknown'),
'version': port_info.get('product', '') + ' ' + port_info.get('version', ''),
'extrainfo': port_info.get('extrainfo', '')
}
self.scan_results['ports'].append(port_data)
print(f"[✓] Port {port}/udp {port_info['state']} - {port_data['service']}")
end_time = datetime.now()
scan_duration = (end_time - start_time).total_seconds()
self.scan_results['scan_time'] = scan_duration
print(f"[✓] Port scan completed in {scan_duration:.2f} seconds")
print(f"[✓] Total open ports found: {len(self.scan_results['ports'])}")
return self.scan_results['ports']
except Exception as e:
print(f"[✗] Port scanning failed: {e}")
return []
def enumerate_services(self):
"""Extract detailed service information"""
print(f"[*] Enumerating services on {self.target}...")
services = []
for port_data in self.scan_results['ports']:
service_info = {
'port': port_data['port'],
'protocol': port_data['protocol'],
'service': port_data['service'],
'version': port_data['version'].strip(),
'banner': port_data.get('extrainfo', ''),
'vulnerabilities': []
}
services.append(service_info)
self.scan_results['services'] = services
print(f"[✓] Enumerated {len(services)} services")
return services
def run_full_scan(self):
"""Execute complete scan workflow"""
print("\n" + "="*60)
print("AutoPentestX - Network Scanner")
print("="*60)
print(f"Target: {self.target}")
print(f"Scan started: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("="*60 + "\n")
# Validate target
if not self.validate_target():
return None
# Step 1: OS Detection
self.detect_os()
# Step 2: Port Scanning
self.scan_all_ports()
# Step 3: Service Enumeration
self.enumerate_services()
print("\n" + "="*60)
print("SCAN SUMMARY")
print("="*60)
print(f"Target: {self.target}")
print(f"OS: {self.scan_results['os_detection']}")
print(f"Open Ports: {len(self.scan_results['ports'])}")
print(f"Services Detected: {len(self.scan_results['services'])}")
print("="*60 + "\n")
return self.scan_results
def get_results(self):
"""Return scan results"""
return self.scan_results
def save_results(self, filename):
"""Save scan results to JSON file"""
try:
with open(filename, 'w') as f:
json.dump(self.scan_results, f, indent=4)
print(f"[✓] Scan results saved to {filename}")
except Exception as e:
print(f"[✗] Failed to save results: {e}")
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("Usage: python scanner.py <target>")
sys.exit(1)
target = sys.argv[1]
scanner = Scanner(target)
results = scanner.run_full_scan()
if results:
scanner.save_results(f"scan_{target.replace('.', '_')}.json")
+344
View File
@@ -0,0 +1,344 @@
#!/usr/bin/env python3
"""
AutoPentestX - Vulnerability Scanner Module
Integrates Nikto (web scanning) and SQLMap (SQL injection detection)
"""
import subprocess
import json
import re
import os
from datetime import datetime
class VulnerabilityScanner:
def __init__(self, target, ports_data):
"""Initialize vulnerability scanner"""
self.target = target
self.ports_data = ports_data
self.web_ports = []
self.vulnerabilities = []
self.web_vulns = []
self.sql_vulns = []
# Identify web ports
self.identify_web_services()
def identify_web_services(self):
"""Identify HTTP/HTTPS services from port scan"""
common_web_ports = [80, 443, 8080, 8443, 8000, 8888, 3000, 5000]
web_services = ['http', 'https', 'ssl/http', 'http-proxy', 'http-alt']
for port in self.ports_data:
service = port.get('service', '').lower()
port_num = port.get('port')
# Check if it's a known web service or common web port
if any(web_svc in service for web_svc in web_services) or port_num in common_web_ports:
protocol = 'https' if port_num == 443 or 'https' in service or 'ssl' in service else 'http'
self.web_ports.append({
'port': port_num,
'protocol': protocol,
'url': f"{protocol}://{self.target}:{port_num}"
})
print(f"[✓] Detected web service: {protocol}://{self.target}:{port_num}")
def scan_with_nikto(self, url):
"""Run Nikto web vulnerability scanner"""
print(f"[*] Running Nikto scan on {url}...")
try:
# Check if Nikto is installed
nikto_check = subprocess.run(['which', 'nikto'], capture_output=True)
if nikto_check.returncode != 0:
print("[!] Nikto not installed, skipping web vulnerability scan")
return []
# Run Nikto
cmd = [
'nikto',
'-h', url,
'-Format', 'json',
'-output', f'logs/nikto_{self.target}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json',
'-Tuning', '123456789', # All tests
'-timeout', '10'
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
# Parse Nikto output
vulns = self.parse_nikto_output(result.stdout)
print(f"[✓] Nikto scan completed: {len(vulns)} vulnerabilities found")
return vulns
except subprocess.TimeoutExpired:
print("[!] Nikto scan timed out")
return []
except Exception as e:
print(f"[!] Nikto scan failed: {e}")
return []
def parse_nikto_output(self, output):
"""Parse Nikto JSON output"""
vulnerabilities = []
try:
# Try to parse as JSON
if output:
# Nikto output may have multiple JSON objects
json_objects = re.findall(r'\{.*?\}', output, re.DOTALL)
for json_str in json_objects:
try:
data = json.loads(json_str)
if 'vulnerabilities' in data:
for vuln in data['vulnerabilities']:
vulnerabilities.append({
'type': 'web',
'url': vuln.get('url', ''),
'severity': self.map_nikto_severity(vuln.get('OSVDB', '')),
'description': vuln.get('msg', 'Unknown vulnerability')
})
except json.JSONDecodeError:
continue
except Exception as e:
print(f"[!] Error parsing Nikto output: {e}")
# If JSON parsing fails, try text parsing
if not vulnerabilities and output:
lines = output.split('\n')
for line in lines:
if '+ ' in line and any(keyword in line.lower() for keyword in
['vulnerable', 'outdated', 'disclosure', 'injection', 'xss', 'security']):
vulnerabilities.append({
'type': 'web',
'url': self.target,
'severity': 'MEDIUM',
'description': line.strip()
})
return vulnerabilities
def map_nikto_severity(self, osvdb_id):
"""Map OSVDB ID to severity level"""
if not osvdb_id:
return 'MEDIUM'
# Simplified severity mapping
return 'MEDIUM'
def scan_sql_injection(self, url):
"""Scan for SQL injection vulnerabilities using SQLMap"""
print(f"[*] Scanning for SQL injection on {url}...")
try:
# Check if SQLMap is installed
sqlmap_check = subprocess.run(['which', 'sqlmap'], capture_output=True)
if sqlmap_check.returncode != 0:
print("[!] SQLMap not installed, skipping SQL injection scan")
return []
# Run SQLMap with batch mode and basic options
cmd = [
'sqlmap',
'-u', url,
'--batch',
'--crawl=2',
'--level=1',
'--risk=1',
'--random-agent',
'--timeout=30',
'--retries=2',
'--threads=3'
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=180)
# Parse SQLMap output
sql_vulns = self.parse_sqlmap_output(result.stdout, url)
print(f"[✓] SQL injection scan completed: {len(sql_vulns)} vulnerabilities found")
return sql_vulns
except subprocess.TimeoutExpired:
print("[!] SQLMap scan timed out")
return []
except Exception as e:
print(f"[!] SQLMap scan failed: {e}")
return []
def parse_sqlmap_output(self, output, url):
"""Parse SQLMap output for vulnerabilities"""
vulnerabilities = []
try:
# Look for SQL injection indicators
if 'parameter' in output.lower() and 'injectable' in output.lower():
# Extract injectable parameters
param_matches = re.findall(r"Parameter: (.*?) \(.*?\) is vulnerable", output, re.IGNORECASE)
for param in param_matches:
vulnerabilities.append({
'type': 'sql_injection',
'url': url,
'parameter': param,
'severity': 'HIGH',
'description': f"SQL Injection vulnerability found in parameter: {param}"
})
# Check for database information
if 'back-end DBMS' in output:
db_match = re.search(r'back-end DBMS: (.*?)[\n\r]', output)
if db_match and vulnerabilities:
vulnerabilities[0]['database'] = db_match.group(1)
except Exception as e:
print(f"[!] Error parsing SQLMap output: {e}")
return vulnerabilities
def scan_common_vulnerabilities(self):
"""Scan for common vulnerabilities based on service versions"""
print("[*] Checking for common vulnerabilities based on service versions...")
common_vulns = []
for port in self.ports_data:
service = port.get('service', '').lower()
version = port.get('version', '').lower()
port_num = port.get('port')
# Check for outdated/vulnerable services
vuln_checks = [
# SSH vulnerabilities
{
'service': 'ssh',
'versions': ['openssh 5', 'openssh 6', 'openssh 7.0', 'openssh 7.1', 'openssh 7.2'],
'vuln_name': 'Outdated SSH Version',
'description': 'SSH service running outdated version with known vulnerabilities',
'severity': 'MEDIUM'
},
# FTP vulnerabilities
{
'service': 'ftp',
'versions': ['vsftpd 2.3.4', 'proftpd 1.3.3'],
'vuln_name': 'Vulnerable FTP Service',
'description': 'FTP service with known backdoor or vulnerabilities',
'severity': 'HIGH'
},
# SMB vulnerabilities
{
'service': 'microsoft-ds',
'versions': ['smb'],
'vuln_name': 'SMB Service Exposed',
'description': 'SMB service exposed, potential for EternalBlue or similar exploits',
'severity': 'HIGH'
},
# MySQL vulnerabilities
{
'service': 'mysql',
'versions': ['5.0', '5.1', '5.5'],
'vuln_name': 'Outdated MySQL Version',
'description': 'MySQL running outdated version with known vulnerabilities',
'severity': 'MEDIUM'
},
# Apache vulnerabilities
{
'service': 'http',
'versions': ['apache 2.0', 'apache 2.2'],
'vuln_name': 'Outdated Apache Server',
'description': 'Apache HTTP server running outdated version',
'severity': 'MEDIUM'
}
]
# Check each vulnerability pattern
for check in vuln_checks:
if check['service'] in service:
for vuln_version in check['versions']:
if vuln_version in version or version == '':
common_vulns.append({
'port': port_num,
'service': service,
'name': check['vuln_name'],
'description': check['description'],
'severity': check['severity'],
'version': version,
'exploitable': True
})
print(f"[!] Found: {check['vuln_name']} on port {port_num}")
break
return common_vulns
def run_full_scan(self):
"""Execute complete vulnerability scan"""
print("\n" + "="*60)
print("AutoPentestX - Vulnerability Scanner")
print("="*60)
print(f"Target: {self.target}")
print(f"Services to scan: {len(self.ports_data)}")
print("="*60 + "\n")
# Scan common vulnerabilities
common_vulns = self.scan_common_vulnerabilities()
self.vulnerabilities.extend(common_vulns)
# Scan web services if found
if self.web_ports:
print(f"\n[*] Found {len(self.web_ports)} web service(s)")
for web_service in self.web_ports:
url = web_service['url']
# Nikto scan
nikto_vulns = self.scan_with_nikto(url)
self.web_vulns.extend(nikto_vulns)
# SQL injection scan
sql_vulns = self.scan_sql_injection(url)
self.sql_vulns.extend(sql_vulns)
else:
print("[!] No web services detected")
print("\n" + "="*60)
print("VULNERABILITY SCAN SUMMARY")
print("="*60)
print(f"Common Vulnerabilities: {len(common_vulns)}")
print(f"Web Vulnerabilities: {len(self.web_vulns)}")
print(f"SQL Injection Points: {len(self.sql_vulns)}")
print(f"Total Vulnerabilities: {len(self.vulnerabilities) + len(self.web_vulns) + len(self.sql_vulns)}")
print("="*60 + "\n")
return {
'vulnerabilities': self.vulnerabilities,
'web_vulnerabilities': self.web_vulns,
'sql_vulnerabilities': self.sql_vulns
}
def get_results(self):
"""Return vulnerability scan results"""
return {
'vulnerabilities': self.vulnerabilities,
'web_vulnerabilities': self.web_vulns,
'sql_vulnerabilities': self.sql_vulns
}
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("Usage: python vuln_scanner.py <target>")
sys.exit(1)
# This would normally receive port data from scanner module
# For testing, we'll use sample data
target = sys.argv[1]
sample_ports = [
{'port': 80, 'service': 'http', 'version': 'Apache 2.2.8'},
{'port': 22, 'service': 'ssh', 'version': 'OpenSSH 7.0'}
]
vuln_scanner = VulnerabilityScanner(target, sample_ports)
results = vuln_scanner.run_full_scan()