Subzy Cheat Sheet
"Clase de la hoja" id="copy-btn" class="copy-btn" onclick="copyAllCommands()" Copiar todos los comandos id="pdf-btn" class="pdf-btn" onclick="generatePDF()" Generar PDF seleccionado/button ■/div titulada
Sinopsis
Subzy es un escáner de vulnerabilidad de absorción de subdominios rápido que detecta registros DNS colgantes e identifica posibles oportunidades de subdominio. Soporta múltiples proveedores y servicios en la nube, lo que hace que sea esencial para evaluaciones integrales de seguridad de aplicaciones web modernas e infraestructura en la nube.
■ Características clave: Detección rápida de subdominios, soporte multiprovidente, escaneo simultáneo, digitalización personalizada, reportaje completo y formatos de salida amigables con la integración.
Instalación y configuración
Instalación binaria
# Download latest release for Linux
wget https://github.com/LukaSikic/subzy/releases/latest/download/subzy_linux_amd64.tar.gz
tar -xzf subzy_linux_amd64.tar.gz
sudo mv subzy /usr/local/bin/
# Download for macOS
wget https://github.com/LukaSikic/subzy/releases/latest/download/subzy_darwin_amd64.tar.gz
tar -xzf subzy_darwin_amd64.tar.gz
sudo mv subzy /usr/local/bin/
# Download for Windows
wget https://github.com/LukaSikic/subzy/releases/latest/download/subzy_windows_amd64.zip
unzip subzy_windows_amd64.zip
# Move subzy.exe to PATH
# Verify installation
subzy --version
# Check available options
subzy --help
Instalación
# Install via Go (requires Go 1.19+)
go install github.com/LukaSikic/subzy@latest
# Verify installation
subzy --version
# Update to latest version
go install github.com/LukaSikic/subzy@latest
# Install specific version
go install github.com/LukaSikic/subzy@v1.0.7
# Build from source
git clone https://github.com/LukaSikic/subzy.git
cd subzy
go build -o subzy main.go
sudo mv subzy /usr/local/bin/
Docker Instalación
# Pull official Docker image
docker pull lukasikic/subzy:latest
# Run Subzy in Docker
docker run --rm lukasikic/subzy:latest --version
# Run with volume mount for input/output
docker run --rm -v $(pwd):/app lukasikic/subzy:latest --targets /app/subdomains.txt
# Create alias for easier usage
echo 'alias subzy="docker run --rm -v $(pwd):/app lukasikic/subzy:latest"' >> ~/.bashrc
source ~/.bashrc
# Build custom Docker image
cat > Dockerfile << EOF
FROM lukasikic/subzy:latest
RUN apk add --no-cache curl jq
COPY custom-fingerprints.json /app/
EOF
docker build -t custom-subzy .
Paquete Manager Instalación
# Homebrew (macOS/Linux)
brew install subzy
# Arch Linux (AUR)
yay -S subzy-bin
# Snap package
sudo snap install subzy
# APT (Ubuntu/Debian) - via GitHub releases
curl -s https://api.github.com/repos/LukaSikic/subzy/releases/latest \
| grep "browser_download_url.*linux_amd64.deb" \
| cut -d '"' -f 4 \
| wget -qi -
sudo dpkg -i subzy_*.deb
# RPM (CentOS/RHEL/Fedora)
curl -s https://api.github.com/repos/LukaSikic/subzy/releases/latest \
| grep "browser_download_url.*linux_amd64.rpm" \
| cut -d '"' -f 4 \
| wget -qi -
sudo rpm -i subzy_*.rpm
Configuración y configuración
# Create configuration directory
mkdir -p ~/.subzy
# Create custom fingerprints file
cat > ~/.subzy/custom-fingerprints.json << 'EOF'
{
"fingerprints": [
{
"service": "Custom Service",
"cname": ["custom.example.com"],
"fingerprint": ["Custom error message"],
"nxdomain": false,
"discussion": "https://example.com/discussion"
}
]
}
EOF
# Create subdomain list for testing
cat > test-subdomains.txt << 'EOF'
subdomain1.example.com
subdomain2.example.com
subdomain3.example.com
api.example.com
admin.example.com
staging.example.com
dev.example.com
test.example.com
EOF
# Set environment variables
export SUBZY_CONFIG=~/.subzy/custom-fingerprints.json
export SUBZY_THREADS=50
export SUBZY_TIMEOUT=10
Uso básico y comandos
Escaneo de blanco único
# Basic subdomain takeover check
subzy run --target subdomain.example.com
# Check with verbose output
subzy run --target subdomain.example.com --verbose
# Check with custom timeout
subzy run --target subdomain.example.com --timeout 30
# Check with custom user agent
subzy run --target subdomain.example.com --user-agent "Custom Agent"
# Check with proxy
subzy run --target subdomain.example.com --proxy http://127.0.0.1:8080
# Check with custom DNS resolver
subzy run --target subdomain.example.com --resolver 8.8.8.8
# Check with HTTPS verification disabled
subzy run --target subdomain.example.com --https
# Save results to file
subzy run --target subdomain.example.com --output results.txt
Escaneo de objetivos múltiples
# Scan multiple targets from file
echo -e "sub1.example.com\nsub2.example.com" > targets.txt
subzy run --targets targets.txt
# Scan with threading
subzy run --targets targets.txt --concurrency 50
# Scan with custom output format
subzy run --targets targets.txt --output results.json
# Scan with verbose logging
subzy run --targets targets.txt --verbose --output detailed-results.txt
# Scan with custom fingerprints
subzy run --targets targets.txt --fingerprints custom-fingerprints.json
# Scan and save only vulnerable targets
subzy run --targets targets.txt --output vulnerable.txt --vulnerable-only
# Scan with rate limiting
subzy run --targets targets.txt --concurrency 10 --timeout 15
Opciones avanzadas de exploración
# Scan with all available checks
subzy run --targets targets.txt --verify-ssl --https --verbose
# Scan with custom DNS settings
subzy run --targets targets.txt --resolver 1.1.1.1 --timeout 20
# Scan with proxy and custom headers
subzy run --targets targets.txt \
--proxy http://127.0.0.1:8080 \
--user-agent "Mozilla/5.0 Custom Agent" \
--timeout 30
# Scan with output in different formats
subzy run --targets targets.txt --output results.json --format json
subzy run --targets targets.txt --output results.csv --format csv
subzy run --targets targets.txt --output results.xml --format xml
# Scan with custom fingerprint validation
subzy run --targets targets.txt --fingerprints custom.json --validate-fingerprints
# Scan with detailed error reporting
subzy run --targets targets.txt --verbose --debug --output debug-results.txt
Detección de subdominio avanzado
Desarrollo de huellas digitales personalizadas
# Create advanced custom fingerprints file
{
"fingerprints": [
{
"service": "AWS S3",
"cname": ["s3.amazonaws.com", "s3-website"],
"fingerprint": [
"NoSuchBucket",
"The specified bucket does not exist"
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
},
{
"service": "GitHub Pages",
"cname": ["github.io", "githubusercontent.com"],
"fingerprint": [
"There isn't a GitHub Pages site here.",
"For root URLs (like http://example.com/) you must provide an index.html file"
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
},
{
"service": "Heroku",
"cname": ["herokuapp.com", "herokussl.com"],
"fingerprint": [
"No such app",
"There's nothing here, yet."
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
},
{
"service": "Netlify",
"cname": ["netlify.com", "netlifyglobalcdn.com"],
"fingerprint": [
"Not Found - Request ID:",
"Site Not Found"
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
},
{
"service": "Azure",
"cname": ["azurewebsites.net", "cloudapp.net"],
"fingerprint": [
"404 Web Site not found",
"This site is stopped"
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
},
{
"service": "Shopify",
"cname": ["myshopify.com"],
"fingerprint": [
"Sorry, this shop is currently unavailable",
"Only one step left!"
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
},
{
"service": "Fastly",
"cname": ["fastly.com", "fastlylb.net"],
"fingerprint": [
"Fastly error: unknown domain",
"Please check that this domain has been added to a service"
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
},
{
"service": "CloudFront",
"cname": ["cloudfront.net"],
"fingerprint": [
"Bad Request: ERROR: The request could not be satisfied",
"The distribution does not exist"
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
},
{
"service": "Bitbucket",
"cname": ["bitbucket.org"],
"fingerprint": [
"Repository not found"
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
},
{
"service": "Tumblr",
"cname": ["tumblr.com"],
"fingerprint": [
"Whatever you were looking for doesn't currently exist at this address"
],
"nxdomain": false,
"discussion": "https://github.com/EdOverflow/can-i-take-over-xyz"
}
]
}
Detección de Subdominio Automatizado y Detección de Tomas
#!/usr/bin/env python3
# Comprehensive subdomain takeover detection automation
import subprocess
import json
import threading
import time
import dns.resolver
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib.parse import urlparse
import re
class SubdomainTakeoverScanner:
def __init__(self, max_workers=50, timeout=10):
self.max_workers = max_workers
self.timeout = timeout
self.results = []
self.lock = threading.Lock()
self.vulnerable_services = []
def discover_subdomains(self, domain, methods=['subfinder', 'amass', 'assetfinder']):
"""Discover subdomains using multiple tools"""
all_subdomains = set()
for method in methods:
try:
if method == 'subfinder':
result = subprocess.run(
['subfinder', '-d', domain, '-silent'],
capture_output=True, text=True, timeout=300
)
if result.returncode == 0:
subdomains = result.stdout.strip().split('\n')
all_subdomains.update([s for s in subdomains if s])
elif method == 'amass':
result = subprocess.run(
['amass', 'enum', '-d', domain, '-passive'],
capture_output=True, text=True, timeout=600
)
if result.returncode == 0:
subdomains = result.stdout.strip().split('\n')
all_subdomains.update([s for s in subdomains if s])
elif method == 'assetfinder':
result = subprocess.run(
['assetfinder', '--subs-only', domain],
capture_output=True, text=True, timeout=300
)
if result.returncode == 0:
subdomains = result.stdout.strip().split('\n')
all_subdomains.update([s for s in subdomains if s])
except subprocess.TimeoutExpired:
print(f"Timeout during {method} subdomain discovery")
except FileNotFoundError:
print(f"{method} not found, skipping...")
except Exception as e:
print(f"Error with {method}: {e}")
return list(all_subdomains)
def check_dns_record(self, subdomain):
"""Check DNS records for subdomain"""
dns_info = {
'subdomain': subdomain,
'a_records': [],
'cname_records': [],
'mx_records': [],
'ns_records': [],
'txt_records': [],
'nxdomain': False,
'error': None
}
try:
# Check A records
try:
answers = dns.resolver.resolve(subdomain, 'A')
dns_info['a_records'] = [str(rdata) for rdata in answers]
except dns.resolver.NXDOMAIN:
dns_info['nxdomain'] = True
except dns.resolver.NoAnswer:
pass
except Exception as e:
dns_info['error'] = str(e)
# Check CNAME records
try:
answers = dns.resolver.resolve(subdomain, 'CNAME')
dns_info['cname_records'] = [str(rdata) for rdata in answers]
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
pass
except Exception as e:
if not dns_info['error']:
dns_info['error'] = str(e)
# Check MX records
try:
answers = dns.resolver.resolve(subdomain, 'MX')
dns_info['mx_records'] = [str(rdata) for rdata in answers]
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
pass
except Exception:
pass
# Check NS records
try:
answers = dns.resolver.resolve(subdomain, 'NS')
dns_info['ns_records'] = [str(rdata) for rdata in answers]
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
pass
except Exception:
pass
# Check TXT records
try:
answers = dns.resolver.resolve(subdomain, 'TXT')
dns_info['txt_records'] = [str(rdata) for rdata in answers]
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
pass
except Exception:
pass
except Exception as e:
dns_info['error'] = str(e)
return dns_info
def check_http_response(self, subdomain):
"""Check HTTP response for takeover indicators"""
http_info = {
'subdomain': subdomain,
'status_code': None,
'response_body': '',
'headers': {},
'redirect_url': None,
'error': None,
'takeover_indicators': []
}
# Common takeover indicators
takeover_patterns = {
'aws_s3': [
'NoSuchBucket',
'The specified bucket does not exist'
],
'github_pages': [
"There isn't a GitHub Pages site here",
'For root URLs (like http://example.com/) you must provide an index.html file'
],
'heroku': [
'No such app',
"There's nothing here, yet"
],
'netlify': [
'Not Found - Request ID:',
'Site Not Found'
],
'azure': [
'404 Web Site not found',
'This site is stopped'
],
'shopify': [
'Sorry, this shop is currently unavailable',
'Only one step left!'
],
'fastly': [
'Fastly error: unknown domain',
'Please check that this domain has been added to a service'
],
'cloudfront': [
'Bad Request: ERROR: The request could not be satisfied',
'The distribution does not exist'
]
}
try:
# Try HTTPS first, then HTTP
for protocol in ['https', 'http']:
try:
url = f"{protocol}://{subdomain}"
response = requests.get(
url,
timeout=self.timeout,
allow_redirects=True,
verify=False
)
http_info['status_code'] = response.status_code
http_info['response_body'] = response.text[:5000] # Limit body size
http_info['headers'] = dict(response.headers)
if response.history:
http_info['redirect_url'] = response.url
# Check for takeover indicators
response_text = response.text.lower()
for service, patterns in takeover_patterns.items():
for pattern in patterns:
if pattern.lower() in response_text:
http_info['takeover_indicators'].append({
'service': service,
'pattern': pattern,
'confidence': 'high'
})
break # Success, no need to try other protocol
except requests.exceptions.SSLError:
if protocol == 'https':
continue # Try HTTP
else:
http_info['error'] = 'SSL Error'
except requests.exceptions.ConnectionError:
if protocol == 'https':
continue # Try HTTP
else:
http_info['error'] = 'Connection Error'
except requests.exceptions.Timeout:
http_info['error'] = 'Timeout'
break
except Exception as e:
http_info['error'] = str(e)
break
except Exception as e:
http_info['error'] = str(e)
return http_info
def run_subzy_scan(self, subdomain):
"""Run Subzy scan on subdomain"""
try:
result = subprocess.run(
['subzy', 'run', '--target', subdomain, '--timeout', str(self.timeout)],
capture_output=True, text=True, timeout=self.timeout + 10
)
subzy_result = {
'subdomain': subdomain,
'vulnerable': False,
'service': None,
'output': result.stdout,
'error': result.stderr if result.returncode != 0 else None
}
# Parse Subzy output for vulnerabilities
if 'VULNERABLE' in result.stdout.upper() or 'TAKEOVER' in result.stdout.upper():
subzy_result['vulnerable'] = True
# Try to extract service name
lines = result.stdout.split('\n')
for line in lines:
if 'service:' in line.lower() or 'provider:' in line.lower():
subzy_result['service'] = line.split(':')[-1].strip()
break
return subzy_result
except subprocess.TimeoutExpired:
return {
'subdomain': subdomain,
'vulnerable': False,
'service': None,
'output': '',
'error': 'Subzy scan timeout'
}
except Exception as e:
return {
'subdomain': subdomain,
'vulnerable': False,
'service': None,
'output': '',
'error': str(e)
}
def comprehensive_scan(self, subdomain):
"""Perform comprehensive subdomain takeover scan"""
print(f"Scanning: {subdomain}")
# Get DNS information
dns_info = self.check_dns_record(subdomain)
# Get HTTP response information
http_info = self.check_http_response(subdomain)
# Run Subzy scan
subzy_info = self.run_subzy_scan(subdomain)
# Combine results
scan_result = {
'subdomain': subdomain,
'timestamp': time.time(),
'dns': dns_info,
'http': http_info,
'subzy': subzy_info,
'vulnerable': False,
'confidence': 'low',
'risk_factors': []
}
# Analyze results for vulnerability indicators
risk_factors = []
# Check DNS indicators
if dns_info['nxdomain']:
risk_factors.append('NXDOMAIN response')
if dns_info['cname_records']:
for cname in dns_info['cname_records']:
# Check for common vulnerable services in CNAME
vulnerable_cnames = [
'github.io', 'herokuapp.com', 'netlify.com',
'azurewebsites.net', 's3.amazonaws.com', 'cloudfront.net'
]
for vcname in vulnerable_cnames:
if vcname in cname:
risk_factors.append(f'Vulnerable CNAME: {cname}')
# Check HTTP indicators
if http_info['takeover_indicators']:
for indicator in http_info['takeover_indicators']:
risk_factors.append(f"HTTP indicator: {indicator['service']} - {indicator['pattern']}")
# Check Subzy results
if subzy_info['vulnerable']:
risk_factors.append(f"Subzy detected vulnerability: {subzy_info['service']}")
scan_result['vulnerable'] = True
scan_result['confidence'] = 'high'
# Determine overall vulnerability status
if len(risk_factors) >= 2:
scan_result['vulnerable'] = True
scan_result['confidence'] = 'medium' if scan_result['confidence'] == 'low' else scan_result['confidence']
scan_result['risk_factors'] = risk_factors
with self.lock:
self.results.append(scan_result)
if scan_result['vulnerable']:
self.vulnerable_services.append(scan_result)
return scan_result
def scan_subdomains(self, subdomains):
"""Scan multiple subdomains concurrently"""
print(f"Starting comprehensive scan of {len(subdomains)} subdomains")
print(f"Max workers: {self.max_workers}")
print(f"Timeout: {self.timeout}s")
with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
# Submit all tasks
future_to_subdomain = {
executor.submit(self.comprehensive_scan, subdomain): subdomain
for subdomain in subdomains
}
# Process completed tasks
for future in as_completed(future_to_subdomain):
subdomain = future_to_subdomain[future]
try:
result = future.result()
if result['vulnerable']:
print(f"🚨 VULNERABLE: {subdomain} - {', '.join(result['risk_factors'])}")
else:
print(f"✓ Safe: {subdomain}")
except Exception as e:
print(f"✗ Error scanning {subdomain}: {e}")
return self.results
def generate_report(self, output_file='subdomain_takeover_report.json'):
"""Generate comprehensive report"""
# Calculate statistics
total_subdomains = len(self.results)
vulnerable_subdomains = len(self.vulnerable_services)
report = {
'scan_summary': {
'total_subdomains': total_subdomains,
'vulnerable_subdomains': vulnerable_subdomains,
'vulnerability_rate': (vulnerable_subdomains / total_subdomains * 100) if total_subdomains > 0 else 0,
'scan_date': time.strftime('%Y-%m-%d %H:%M:%S')
},
'vulnerable_subdomains': self.vulnerable_services,
'all_results': self.results
}
# Save report
with open(output_file, 'w') as f:
json.dump(report, f, indent=2)
print(f"\nReport saved to: {output_file}")
# Generate summary
print("\nScan Summary:")
print(f"Total subdomains: {total_subdomains}")
print(f"Vulnerable subdomains: {vulnerable_subdomains}")
print(f"Vulnerability rate: {report['scan_summary']['vulnerability_rate']:.1f}%")
if self.vulnerable_services:
print("\nVulnerable Subdomains:")
for vuln in self.vulnerable_services:
print(f"- {vuln['subdomain']}: {', '.join(vuln['risk_factors'])}")
return report
# Usage example
if __name__ == "__main__":
# Create scanner instance
scanner = SubdomainTakeoverScanner(max_workers=20, timeout=10)
# Discover subdomains
domain = "example.com"
print(f"Discovering subdomains for {domain}...")
subdomains = scanner.discover_subdomains(domain)
print(f"Found {len(subdomains)} subdomains")
# Scan for takeover vulnerabilities
results = scanner.scan_subdomains(subdomains)
# Generate report
report = scanner.generate_report('comprehensive_takeover_report.json')
Automatización e integración
CI/CD Integration
#!/bin/bash
# CI/CD script for subdomain takeover detection
set -e
DOMAIN="$1"
OUTPUT_DIR="$2"
THRESHOLD="$3"
| if [ -z "$DOMAIN" ] | | [ -z "$OUTPUT_DIR" ]; then |
echo "Usage: $0 <domain> <output_dir> [threshold]"
exit 1
fi
THRESHOLD=${THRESHOLD:-0} # Default: fail on any takeover found
echo "Starting subdomain takeover scan..."
echo "Domain: $DOMAIN"
echo "Output directory: $OUTPUT_DIR"
echo "Threshold: $THRESHOLD vulnerabilities"
mkdir -p "$OUTPUT_DIR"
# Discover subdomains
echo "Discovering subdomains..."
| subfinder -d "$DOMAIN" -silent > "$OUTPUT_DIR/subdomains.txt" 2>/dev/null | | echo "Subfinder not available" |
| amass enum -d "$DOMAIN" -passive >> "$OUTPUT_DIR/subdomains.txt" 2>/dev/null | | echo "Amass not available" |
| assetfinder --subs-only "$DOMAIN" >> "$OUTPUT_DIR/subdomains.txt" 2>/dev/null | | echo "Assetfinder not available" |
# Remove duplicates and empty lines
| sort "$OUTPUT_DIR/subdomains.txt" | uniq | grep -v '^$' > "$OUTPUT_DIR/unique_subdomains.txt" |
SUBDOMAIN_COUNT=$(wc -l < "$OUTPUT_DIR/unique_subdomains.txt")
echo "Found $SUBDOMAIN_COUNT unique subdomains"
# Run Subzy scan
echo "Running Subzy scan..."
subzy run --targets "$OUTPUT_DIR/unique_subdomains.txt" \
--concurrency 50 \
--timeout 15 \
--output "$OUTPUT_DIR/subzy_results.txt" \
--verbose
# Parse results
| VULN_COUNT=$(grep -c "VULNERABLE\ | TAKEOVER" "$OUTPUT_DIR/subzy_results.txt" | | echo "0") |
echo "Found $VULN_COUNT potential subdomain takeover vulnerabilities"
# Generate summary report
cat > "$OUTPUT_DIR/takeover-summary.txt" << EOF
Subdomain Takeover Scan Summary
==============================
Date: $(date)
Domain: $DOMAIN
Total Subdomains: $SUBDOMAIN_COUNT
Potential Vulnerabilities: $VULN_COUNT
Threshold: $THRESHOLD
Status: $(if [ "$VULN_COUNT" -le "$THRESHOLD" ]; then echo "PASS"; else echo "FAIL"; fi)
EOF
# Generate detailed report
python3 << 'PYTHON_EOF'
import sys
import json
import re
from datetime import datetime
output_dir = sys.argv[1]
domain = sys.argv[2]
# Read Subzy results
try:
with open(f"{output_dir}/subzy_results.txt", 'r') as f:
subzy_output = f.read()
except FileNotFoundError:
subzy_output = ""
# Parse vulnerabilities
vulnerabilities = []
lines = subzy_output.split('\n')
for line in lines:
if 'VULNERABLE' in line.upper() or 'TAKEOVER' in line.upper():
# Extract subdomain and service information
parts = line.split()
if len(parts) >= 2:
subdomain = parts[0] if '://' not in parts[0] else parts[0].split('://')[-1]
service = 'Unknown'
# Try to extract service name
for part in parts:
if any(svc in part.lower() for svc in ['aws', 'github', 'heroku', 'netlify', 'azure']):
service = part
break
vulnerability = {
'subdomain': subdomain,
'service': service,
'description': line.strip(),
'severity': 'High',
'risk': 'Subdomain takeover possible'
}
vulnerabilities.append(vulnerability)
# Create detailed report
report = {
'scan_info': {
'domain': domain,
'scanner': 'Subzy',
'scan_date': datetime.now().isoformat(),
'vulnerability_count': len(vulnerabilities)
},
'vulnerabilities': vulnerabilities,
'raw_output': subzy_output
}
# Save JSON report
with open(f"{output_dir}/subzy-report.json", 'w') as f:
json.dump(report, f, indent=2)
# Generate HTML report
html_content = f"""
<!DOCTYPE html>
<html>
<head>
<title>Subdomain Takeover Scan Report</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; }}
.header {{ background-color: #f0f0f0; padding: 20px; border-radius: 5px; }}
.vuln {{ margin: 10px 0; padding: 15px; border-left: 4px solid #dc3545; background-color: #f8f9fa; }}
.safe {{ color: #28a745; }}
.danger {{ color: #dc3545; }}
table {{ border-collapse: collapse; width: 100%; margin: 20px 0; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #f2f2f2; }}
.code {{ background-color: #f8f9fa; padding: 10px; border-radius: 3px; font-family: monospace; }}
</style>
</head>
<body>
<div class="header">
<h1>Subdomain Takeover Scan Report</h1>
<p><strong>Domain:</strong> {domain}</p>
<p><strong>Scan Date:</strong> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
<p><strong>Vulnerabilities Found:</strong> <span class="{'danger' if len(vulnerabilities) > 0 else 'safe'}">{len(vulnerabilities)}</span></p>
</div>
<h2>Vulnerability Details</h2>
"""
if vulnerabilities:
html_content += "<table><tr><th>Subdomain</th><th>Service</th><th>Risk</th><th>Description</th></tr>"
for vuln in vulnerabilities:
html_content += f"""
<tr>
<td>{vuln.get('subdomain', '')}</td>
<td>{vuln.get('service', '')}</td>
<td>{vuln.get('risk', '')}</td>
<td><div class="code">{vuln.get('description', '')}</div></td>
</tr>
"""
html_content += "</table>"
else:
html_content += "<p class='safe'>No subdomain takeover vulnerabilities detected.</p>"
html_content += """
<h2>Raw Output</h2>
<div class="code">
<pre>{}</pre>
</div>
</body>
</html>
""".format(subzy_output.replace('<', '<').replace('>', '>'))
with open(f"{output_dir}/subzy-report.html", 'w') as f:
f.write(html_content)
print(f"Detailed reports generated:")
print(f"- JSON: {output_dir}/subzy-report.json")
print(f"- HTML: {output_dir}/subzy-report.html")
PYTHON_EOF
# Check threshold and exit
if [ "$VULN_COUNT" -gt "$THRESHOLD" ]; then
echo "ERROR: Found $VULN_COUNT vulnerabilities, exceeds threshold of $THRESHOLD"
exit 1
else
echo "SUCCESS: Vulnerability count within acceptable threshold"
exit 0
fi
GitHub Actions Integration
# .github/workflows/subdomain-takeover-scan.yml
name: Subdomain Takeover Security Scan
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 4 * * 3' # Weekly scan on Wednesdays at 4 AM
jobs:
subdomain-takeover-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install subdomain discovery tools
run: |
# Install Subfinder
wget https: //github.com/projectdiscovery/subfinder/releases/latest/download/subfinder_2.6.3_linux_amd64.zip
unzip subfinder_2.6.3_linux_amd64.zip
sudo mv subfinder /usr/local/bin/
# Install Assetfinder
go install github.com/tomnomnom/assetfinder@latest
# Install Subzy
wget https: //github.com/LukaSikic/subzy/releases/latest/download/subzy_linux_amd64.tar.gz
tar -xzf subzy_linux_amd64.tar.gz
sudo mv subzy /usr/local/bin/
# Verify installations
subfinder -version
assetfinder --help
subzy --version
- name: Discover subdomains
run: |
mkdir -p scan-results
# Discover subdomains using multiple tools
subfinder -d ${{ vars.TARGET_DOMAIN }} -silent > scan-results/subfinder.txt
assetfinder --subs-only ${{ vars.TARGET_DOMAIN }} > scan-results/assetfinder.txt
# Combine and deduplicate
| cat scan-results/subfinder.txt scan-results/assetfinder.txt | sort | uniq > scan-results/all_subdomains.txt |
SUBDOMAIN_COUNT=$(wc -l < scan-results/all_subdomains.txt)
echo "SUBDOMAIN_COUNT=$SUBDOMAIN_COUNT" >> $GITHUB_ENV
echo "Found $SUBDOMAIN_COUNT unique subdomains"
- name: Run subdomain takeover scan
run: |
# Run Subzy scan
subzy run --targets scan-results/all_subdomains.txt \
--concurrency 30 \
--timeout 15 \
--output scan-results/subzy_results.txt \
--verbose
# Count vulnerabilities
| VULN_COUNT=$(grep -c "VULNERABLE\ | TAKEOVER" scan-results/subzy_results.txt | | echo "0") |
echo "VULN_COUNT=$VULN_COUNT" >> $GITHUB_ENV
# Generate summary
echo "Subdomain takeover vulnerabilities found: $VULN_COUNT" > scan-results/summary.txt
echo "Total subdomains scanned: $SUBDOMAIN_COUNT" >> scan-results/summary.txt
- name: Process scan results
run: |
# Extract vulnerable subdomains
| grep "VULNERABLE\ | TAKEOVER" scan-results/subzy_results.txt > scan-results/vulnerable_subdomains.txt | | touch scan-results/vulnerable_subdomains.txt |
# Create detailed summary
cat > scan-results/detailed_summary.txt << EOF
Subdomain Takeover Scan Results
==============================
Domain: ${{ vars.TARGET_DOMAIN }}
Scan Date: $(date)
Total Subdomains: $SUBDOMAIN_COUNT
Vulnerable Subdomains: $VULN_COUNT
Vulnerable Subdomains:
$(cat scan-results/vulnerable_subdomains.txt)
EOF
- name: Upload scan results
uses: actions/upload-artifact@v3
with:
name: subdomain-takeover-results
path: scan-results/
- name: Comment PR with results
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('scan-results/summary.txt', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Subdomain Takeover Scan Results\n\n\`\`\`\n${summary}\n\`\`\``
});
- name: Fail if vulnerabilities found
run: |
if [ "$VULN_COUNT" -gt "0" ]; then
echo "Subdomain takeover vulnerabilities detected! Check the scan results."
cat scan-results/vulnerable_subdomains.txt
exit 1
fi
Optimización del rendimiento y solución de problemas
Performance Tuning
# Optimize Subzy for different scenarios
# High-speed scanning
subzy run --targets subdomains.txt \
--concurrency 100 \
--timeout 5 \
--https
# Thorough scanning
subzy run --targets subdomains.txt \
--concurrency 20 \
--timeout 30 \
--verify-ssl \
--verbose
# Memory-efficient scanning for large lists
subzy run --targets large_subdomains.txt \
--concurrency 10 \
--timeout 15 \
--output results.txt
# Network-optimized scanning
subzy run --targets subdomains.txt \
--concurrency 50 \
--timeout 10 \
--resolver 8.8.8.8
# Performance monitoring script
#!/bin/bash
monitor_subzy_performance() {
local targets_file="$1"
local output_file="subzy-performance-$(date +%s).log"
echo "Starting performance monitoring for Subzy scan"
echo "Targets file: $targets_file"
echo "Log file: $output_file"
# Start monitoring in background
{
echo "Timestamp,CPU%,Memory(MB),Targets/sec"
start_time=$(date +%s)
while true; do
if pgrep -f "subzy" > /dev/null; then
local cpu=$(ps -p $(pgrep -f "subzy") -o %cpu --no-headers | awk '{sum+=$1} END {print sum}')
local mem=$(ps -p $(pgrep -f "subzy") -o rss --no-headers | awk '{sum+=$1} END {print sum/1024}')
local current_time=$(date +%s)
local elapsed=$((current_time - start_time))
| local targets_processed=$(wc -l < "$targets_file" 2>/dev/null | | echo "0") |
| local rate=$(echo "scale=2; $targets_processed / $elapsed" | bc -l 2>/dev/null | | echo "0") |
echo "$(date +%s),$cpu,$mem,$rate"
fi
sleep 5
done
} > "$output_file" &
local monitor_pid=$!
# Run Subzy scan
subzy run --targets "$targets_file" \
--concurrency 50 \
--timeout 15 \
--verbose \
--output "subzy-results-$(date +%s).txt"
# Stop monitoring
kill $monitor_pid 2>/dev/null
echo "Performance monitoring completed: $output_file"
}
# Usage
monitor_subzy_performance "subdomains.txt"
Problemas comunes
# Troubleshooting script for Subzy
troubleshoot_subzy() {
echo "Subzy Troubleshooting Guide"
echo "=========================="
# Check if Subzy is installed
if ! command -v subzy &> /dev/null; then
echo "❌ Subzy not found in PATH"
echo "Solution: Install Subzy using one of the installation methods"
return 1
fi
echo "✅ Subzy found: $(which subzy)"
echo "Version: $(subzy --version 2>&1)"
# Check network connectivity
if ! curl -s --connect-timeout 5 https://httpbin.org/get > /dev/null; then
echo "❌ Network connectivity issues"
echo "Solution: Check internet connection and proxy settings"
return 1
fi
echo "✅ Network connectivity OK"
# Test basic functionality
echo "Testing basic Subzy functionality..."
echo "test.example.com" > /tmp/test_subdomains.txt
if timeout 30 subzy run --targets /tmp/test_subdomains.txt --timeout 10 > /dev/null 2>&1; then
echo "✅ Basic functionality test passed"
else
echo "❌ Basic functionality test failed"
echo "Solution: Check Subzy installation and permissions"
return 1
fi
# Check DNS resolution
if ! nslookup google.com > /dev/null 2>&1; then
echo "❌ DNS resolution issues"
echo "Solution: Check DNS settings or use custom resolver"
echo "Example: subzy run --targets file.txt --resolver 8.8.8.8"
return 1
fi
echo "✅ DNS resolution OK"
# Check for common issues
echo "Checking for common configuration issues..."
# Check file permissions
if [ ! -r "/tmp/test_subdomains.txt" ]; then
echo "⚠️ File permission issues detected"
echo "Solution: Check read permissions on target files"
fi
# Check for proxy issues
| if [ -n "$HTTP_PROXY" ] | | [ -n "$HTTPS_PROXY" ]; then |
echo "⚠️ Proxy environment variables detected"
echo "Note: Use --proxy option if needed"
fi
# Clean up
rm -f /tmp/test_subdomains.txt
echo "Troubleshooting completed"
}
# Common error solutions
fix_common_subzy_errors() {
echo "Common Subzy Error Solutions"
echo "==========================="
echo "1. 'no such file or directory'"
echo " Solution: Check if targets file exists and is readable"
echo " Example: ls -la targets.txt"
echo ""
echo "2. 'connection timeout'"
echo " Solution: Increase timeout or reduce concurrency"
echo " Example: subzy run --targets file.txt --timeout 30 --concurrency 10"
echo ""
echo "3. 'too many open files'"
echo " Solution: Reduce concurrency or increase system limits"
echo " Example: ulimit -n 4096 && subzy run --targets file.txt --concurrency 20"
echo ""
echo "4. 'DNS resolution failed'"
echo " Solution: Use custom DNS resolver"
echo " Example: subzy run --targets file.txt --resolver 1.1.1.1"
echo ""
echo "5. 'SSL certificate verification failed'"
echo " Solution: Disable SSL verification (use with caution)"
echo " Example: subzy run --targets file.txt --https"
echo ""
echo "6. 'permission denied'"
echo " Solution: Check file permissions and run with appropriate privileges"
echo " Example: chmod +r targets.txt"
echo ""
echo "7. 'no vulnerabilities found' (potential false negatives)"
echo " Solution: Use verbose mode and custom fingerprints"
echo " Example: subzy run --targets file.txt --verbose --fingerprints custom.json"
}
# Run troubleshooting
troubleshoot_subzy
fix_common_subzy_errors
Recursos y documentación
Recursos oficiales
- Subzy GitHub Repository - Repositorio principal y documentación
- Release Notes - Actualizaciones y cambios
- Bug Reports - Registro de errores e informes de errores
- Docker Hub - Imágenes oficiales Docker
Recursos comunitarios
- ¿Puedo tomar sobre XYZ? - Guía de toma de posesión completa de subdominio
- Subdomain Takeover Scanner - Herramienta de escaneo alternativo
- Nuclei Templates - Plantillas de detección de tomas
- Bug Bounty Methodologies - Caza de subdominio
Investigación y aprendizaje
- OWASP Subdomain Takeover - Guía de pruebas OWASP
- Subdomain Takeover Vulnerabilities - Inmersión técnica profunda
- Cloud Security Research - Investigaciones históricas
- DNS Security Best Practices - Estrategias de prevención