NeuroSploit v3.2 - Autonomous AI Penetration Testing Platform

116 modules | 100 vuln types | 18 API routes | 18 frontend pages

Major features:
- VulnEngine: 100 vuln types, 526+ payloads, 12 testers, anti-hallucination prompts
- Autonomous Agent: 3-stream auto pentest, multi-session (5 concurrent), pause/resume/stop
- CLI Agent: Claude Code / Gemini CLI / Codex CLI inside Kali containers
- Validation Pipeline: negative controls, proof of execution, confidence scoring, judge
- AI Reasoning: ReACT engine, token budget, endpoint classifier, CVE hunter, deep recon
- Multi-Agent: 5 specialists + orchestrator + researcher AI + vuln type agents
- RAG System: BM25/TF-IDF/ChromaDB vectorstore, few-shot, reasoning templates
- Smart Router: 20 providers (8 CLI OAuth + 12 API), tier failover, token refresh
- Kali Sandbox: container-per-scan, 56 tools, VPN support, on-demand install
- Full IA Testing: methodology-driven comprehensive pentest sessions
- Notifications: Discord, Telegram, WhatsApp/Twilio multi-channel alerts
- Frontend: React/TypeScript with 18 pages, real-time WebSocket updates
This commit is contained in:
CyberSecurityUP
2026-02-22 17:58:12 -03:00
commit e0935793c5
271 changed files with 132462 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
from .network_scanner import NetworkScanner
from .osint_collector import OSINTCollector
from .dns_enumerator import DNSEnumerator
from .subdomain_finder import SubdomainFinder
+165
View File
@@ -0,0 +1,165 @@
#!/usr/bin/env python3
"""
DNSEnumerator - Enumerates DNS records for target domains
"""
import logging
import socket
import subprocess
from typing import Dict, List
import re
logger = logging.getLogger(__name__)
class DNSEnumerator:
"""
A class for enumerating DNS records.
Queries various DNS record types including A, AAAA, MX, NS, TXT, CNAME, and SOA.
"""
def __init__(self, config: Dict):
"""
Initializes the DNSEnumerator.
Args:
config (Dict): The configuration dictionary for the framework.
"""
self.config = config
logger.info("DNSEnumerator initialized")
def enumerate(self, target: str) -> Dict:
"""
Enumerates DNS records for a given domain.
Args:
target (str): The domain name to enumerate.
Returns:
Dict: A dictionary containing DNS records.
"""
logger.info(f"Starting DNS enumeration for {target}")
# Remove protocol if present
domain = target.replace('http://', '').replace('https://', '').split('/')[0]
records = {
"target": domain,
"records": {
"A": self._get_a_records(domain),
"AAAA": self._get_aaaa_records(domain),
"MX": self._get_mx_records(domain),
"NS": self._get_ns_records(domain),
"TXT": self._get_txt_records(domain),
"CNAME": self._get_cname_records(domain)
},
"notes": "DNS enumeration completed"
}
logger.info(f"DNS enumeration completed for {domain}")
return records
def _get_a_records(self, domain: str) -> List[str]:
"""Get A records (IPv4 addresses)"""
try:
records = socket.gethostbyname_ex(domain)[2]
logger.info(f"Found {len(records)} A records for {domain}")
return records
except socket.gaierror as e:
logger.warning(f"Could not resolve A records for {domain}: {e}")
return []
except Exception as e:
logger.error(f"Error getting A records: {e}")
return []
def _get_aaaa_records(self, domain: str) -> List[str]:
"""Get AAAA records (IPv6 addresses)"""
try:
records = socket.getaddrinfo(domain, None, socket.AF_INET6)
ipv6_addrs = list(set([record[4][0] for record in records]))
logger.info(f"Found {len(ipv6_addrs)} AAAA records for {domain}")
return ipv6_addrs
except socket.gaierror:
logger.debug(f"No AAAA records found for {domain}")
return []
except Exception as e:
logger.error(f"Error getting AAAA records: {e}")
return []
def _get_mx_records(self, domain: str) -> List[str]:
"""Get MX records using nslookup/dig fallback"""
return self._query_dns_tool(domain, "MX")
def _get_ns_records(self, domain: str) -> List[str]:
"""Get NS records using nslookup/dig fallback"""
return self._query_dns_tool(domain, "NS")
def _get_txt_records(self, domain: str) -> List[str]:
"""Get TXT records using nslookup/dig fallback"""
return self._query_dns_tool(domain, "TXT")
def _get_cname_records(self, domain: str) -> List[str]:
"""Get CNAME records using nslookup/dig fallback"""
try:
result = socket.getfqdn(domain)
if result != domain:
logger.info(f"Found CNAME for {domain}: {result}")
return [result]
return []
except Exception as e:
logger.debug(f"No CNAME records found for {domain}")
return []
def _query_dns_tool(self, domain: str, record_type: str) -> List[str]:
"""
Query DNS using nslookup (fallback method when dnspython not available)
"""
try:
# Try using nslookup
cmd = ['nslookup', '-type=' + record_type, domain]
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=10,
shell=False
)
if result.returncode == 0:
records = self._parse_nslookup_output(result.stdout, record_type)
logger.info(f"Found {len(records)} {record_type} records for {domain}")
return records
else:
logger.debug(f"nslookup failed for {record_type} records")
return []
except FileNotFoundError:
logger.warning("nslookup not found. DNS enumeration limited to A/AAAA records.")
return []
except subprocess.TimeoutExpired:
logger.warning(f"DNS query timeout for {record_type} records")
return []
except Exception as e:
logger.error(f"Error querying {record_type} records: {e}")
return []
def _parse_nslookup_output(self, output: str, record_type: str) -> List[str]:
"""Parse nslookup output to extract DNS records"""
records = []
if record_type == "MX":
# MX records format: "mail exchanger = 10 mail.example.com"
pattern = r'mail exchanger = \d+ (.+)'
matches = re.findall(pattern, output)
records = [match.strip().rstrip('.') for match in matches]
elif record_type == "NS":
# NS records format: "nameserver = ns1.example.com"
pattern = r'nameserver = (.+)'
matches = re.findall(pattern, output)
records = [match.strip().rstrip('.') for match in matches]
elif record_type == "TXT":
# TXT records format: "text = "v=spf1 ...""
pattern = r'text = "([^"]+)"'
matches = re.findall(pattern, output)
records = matches
return records
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env python3
"""
NetworkScanner - A tool for scanning networks to find open ports.
"""
import socket
import logging
from typing import Dict, List
logger = logging.getLogger(__name__)
class NetworkScanner:
"""
A class to scan for open ports on a target machine.
"""
def __init__(self, config: Dict):
"""
Initializes the NetworkScanner.
Args:
config (Dict): The configuration dictionary for the framework.
"""
self.config = config
self.common_ports = [
21, 22, 23, 25, 53, 80, 110, 111, 135, 139, 143, 443, 445,
993, 995, 1723, 3306, 3389, 5900, 8080
]
def scan(self, target: str) -> Dict:
"""
Scans a target for open ports.
Args:
target (str): The IP address or hostname to scan.
Returns:
Dict: A dictionary containing the list of open ports found.
"""
logger.info(f"Starting network scan on {target}")
open_ports = []
try:
target_ip = socket.gethostbyname(target)
logger.info(f"Resolved {target} to {target_ip}")
for port in self.common_ports:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.setdefaulttimeout(1)
result = sock.connect_ex((target_ip, port))
if result == 0:
logger.info(f"Port {port} is open on {target}")
open_ports.append(port)
sock.close()
except socket.gaierror:
logger.error(f"Hostname could not be resolved: {target}")
return {"error": "Hostname could not be resolved."}
except socket.error:
logger.error(f"Could not connect to server: {target}")
return {"error": "Could not connect to server."}
logger.info(f"Network scan finished. Found {len(open_ports)} open ports.")
return {"target": target, "open_ports": open_ports}
+147
View File
@@ -0,0 +1,147 @@
#!/usr/bin/env python3
"""
OSINTCollector - Collects Open Source Intelligence from various sources
"""
import logging
import re
import requests
from typing import Dict, List
import socket
logger = logging.getLogger(__name__)
class OSINTCollector:
"""
A class for collecting Open Source Intelligence from publicly available sources.
Collects information like WHOIS data, IP addresses, email patterns, and more.
"""
def __init__(self, config: Dict):
"""
Initializes the OSINTCollector.
Args:
config (Dict): The configuration dictionary for the framework.
"""
self.config = config
logger.info("OSINTCollector initialized")
def collect(self, target: str) -> Dict:
"""
Collects OSINT data for a given target.
Args:
target (str): The target (e.g., domain name, company name).
Returns:
Dict: A dictionary containing OSINT findings.
"""
logger.info(f"Starting OSINT collection for {target}")
results = {
"target": target,
"ip_addresses": self._get_ip_addresses(target),
"email_patterns": self._find_email_patterns(target),
"technologies": self._detect_technologies(target),
"social_media": self._find_social_media(target),
"metadata": "OSINT collection completed"
}
logger.info(f"OSINT collection completed for {target}")
return results
def _get_ip_addresses(self, target: str) -> List[str]:
"""Resolve target domain to IP addresses"""
try:
# Remove protocol if present
domain = target.replace('http://', '').replace('https://', '').split('/')[0]
ip_list = socket.gethostbyname_ex(domain)[2]
logger.info(f"Resolved {domain} to IPs: {ip_list}")
return ip_list
except socket.gaierror as e:
logger.warning(f"Could not resolve {target}: {e}")
return []
except Exception as e:
logger.error(f"Error resolving IP for {target}: {e}")
return []
def _find_email_patterns(self, target: str) -> List[str]:
"""Find common email patterns for the target domain"""
try:
domain = target.replace('http://', '').replace('https://', '').split('/')[0]
# Common email patterns
patterns = [
f"info@{domain}",
f"contact@{domain}",
f"admin@{domain}",
f"support@{domain}",
f"security@{domain}"
]
logger.info(f"Generated {len(patterns)} common email patterns for {domain}")
return patterns
except Exception as e:
logger.error(f"Error generating email patterns: {e}")
return []
def _detect_technologies(self, target: str) -> Dict:
"""Detect web technologies used by the target"""
try:
if not target.startswith('http'):
target = f"http://{target}"
response = requests.get(target, timeout=10, allow_redirects=True)
headers = response.headers
technologies = {
"server": headers.get('Server', 'Unknown'),
"powered_by": headers.get('X-Powered-By', 'Unknown'),
"framework": self._detect_framework(response.text, headers),
"status_code": response.status_code
}
logger.info(f"Detected technologies for {target}: {technologies}")
return technologies
except requests.RequestException as e:
logger.warning(f"Could not detect technologies for {target}: {e}")
return {"error": str(e)}
except Exception as e:
logger.error(f"Error detecting technologies: {e}")
return {"error": str(e)}
def _detect_framework(self, html_content: str, headers: Dict) -> str:
"""Detect web framework from HTML and headers"""
frameworks = {
'WordPress': ['wp-content', 'wp-includes'],
'Drupal': ['drupal.js', 'sites/default'],
'Joomla': ['joomla', 'option=com_'],
'Django': ['csrfmiddlewaretoken'],
'Laravel': ['laravel', '_token'],
'React': ['react', '__REACT'],
'Angular': ['ng-version', 'angular'],
'Vue': ['vue', '__VUE__']
}
for framework, indicators in frameworks.items():
for indicator in indicators:
if indicator.lower() in html_content.lower():
return framework
return "Unknown"
def _find_social_media(self, target: str) -> Dict:
"""Find potential social media accounts for the target"""
try:
domain = target.replace('http://', '').replace('https://', '').split('/')[0]
company_name = domain.split('.')[0]
social_media = {
"twitter": f"https://twitter.com/{company_name}",
"linkedin": f"https://linkedin.com/company/{company_name}",
"github": f"https://github.com/{company_name}",
"facebook": f"https://facebook.com/{company_name}"
}
logger.info(f"Generated social media URLs for {company_name}")
return social_media
except Exception as e:
logger.error(f"Error generating social media links: {e}")
return {}
+2857
View File
File diff suppressed because it is too large Load Diff
+127
View File
@@ -0,0 +1,127 @@
#!/usr/bin/env python3
"""
SubdomainFinder - Discovers subdomains using multiple techniques
"""
import logging
import requests
import socket
from typing import Dict, List, Set
import re
logger = logging.getLogger(__name__)
class SubdomainFinder:
"""
A class for finding subdomains of a given domain.
Uses Certificate Transparency logs, DNS brute-forcing, and common patterns.
"""
def __init__(self, config: Dict):
"""
Initializes the SubdomainFinder.
Args:
config (Dict): The configuration dictionary for the framework.
"""
self.config = config
self.common_subdomains = [
'www', 'mail', 'ftp', 'localhost', 'webmail', 'smtp', 'pop', 'ns1', 'ns2',
'webdisk', 'ns', 'cpanel', 'whm', 'autodiscover', 'autoconfig', 'test',
'dev', 'staging', 'api', 'admin', 'portal', 'beta', 'demo', 'vpn',
'blog', 'shop', 'store', 'forum', 'support', 'm', 'mobile', 'cdn',
'static', 'assets', 'img', 'images', 'git', 'jenkins', 'jira'
]
logger.info("SubdomainFinder initialized")
def find(self, target: str) -> List[str]:
"""
Finds subdomains for a given domain using multiple techniques.
Args:
target (str): The domain name to search subdomains for.
Returns:
List[str]: A list of found subdomains.
"""
logger.info(f"Starting subdomain enumeration for {target}")
# Remove protocol if present
domain = target.replace('http://', '').replace('https://', '').split('/')[0]
found_subdomains: Set[str] = set()
# Method 1: Certificate Transparency logs
ct_subdomains = self._check_crtsh(domain)
found_subdomains.update(ct_subdomains)
# Method 2: Common subdomain brute-forcing
brute_subdomains = self._brute_force_common(domain)
found_subdomains.update(brute_subdomains)
result = sorted(list(found_subdomains))
logger.info(f"Found {len(result)} subdomains for {domain}")
return result
def _check_crtsh(self, domain: str) -> List[str]:
"""
Query Certificate Transparency logs via crt.sh
"""
subdomains = []
try:
url = f"https://crt.sh/?q=%.{domain}&output=json"
logger.info(f"Querying crt.sh for {domain}")
response = requests.get(url, timeout=15)
if response.status_code == 200:
data = response.json()
for entry in data:
name_value = entry.get('name_value', '')
# Split by newlines (crt.sh returns multiple names per entry sometimes)
names = name_value.split('\n')
for name in names:
name = name.strip().lower()
# Remove wildcards
name = name.replace('*.', '')
# Only include valid subdomains for this domain
if name.endswith(domain) and name != domain:
subdomains.append(name)
logger.info(f"Found {len(subdomains)} subdomains from crt.sh")
else:
logger.warning(f"crt.sh returned status code {response.status_code}")
except requests.RequestException as e:
logger.warning(f"Error querying crt.sh: {e}")
except Exception as e:
logger.error(f"Unexpected error in crt.sh query: {e}")
return list(set(subdomains)) # Remove duplicates
def _brute_force_common(self, domain: str) -> List[str]:
"""
Brute-force common subdomain names
"""
found = []
logger.info(f"Brute-forcing common subdomains for {domain}")
for subdomain in self.common_subdomains:
full_domain = f"{subdomain}.{domain}"
if self._check_subdomain_exists(full_domain):
found.append(full_domain)
logger.debug(f"Found subdomain: {full_domain}")
logger.info(f"Found {len(found)} subdomains via brute-force")
return found
def _check_subdomain_exists(self, subdomain: str) -> bool:
"""
Check if a subdomain exists by attempting to resolve it
"""
try:
socket.gethostbyname(subdomain)
return True
except socket.gaierror:
return False
except Exception as e:
logger.debug(f"Error checking {subdomain}: {e}")
return False