mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-02-12 14:02:45 +00:00
128 lines
4.5 KiB
Python
128 lines
4.5 KiB
Python
#!/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
|