Files
fn_registry/bash/functions/cybersecurity/enumerate_subdomains.sh
T
egutierrez 7c3f01c9eb feat: add bash cybersecurity audit and hardening functions
12 funciones Bash del dominio cybersecurity: auditoria de red y servicios
(analyze_dns, audit_http_headers, inspect_ssl_cert, list_active_connections,
enumerate_subdomains, geolocate_ip), auditoria de sistema (audit_ssh_config,
check_firewall, detect_suspicious_users), y utilidades crypto (encrypt_file,
generate_password, verify_file_hash). Dominio nuevo en bash/functions/.
2026-04-12 13:54:25 +02:00

135 lines
4.9 KiB
Bash

#!/usr/bin/env bash
# enumerate_subdomains
# --------------------
# Enumera subdominios de un dominio objetivo usando un diccionario integrado de
# ~100 subdominios comunes. Detecta tanto registros A (IP directa) como CNAME.
# Opcionalmente guarda el resultado en un archivo.
#
# USO (directo):
# enumerate_subdomains <dominio> [archivo_salida]
# enumerate_subdomains example.com
# enumerate_subdomains example.com /tmp/resultado.txt
#
# Depende de: dig (dnsutils)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../shell/bash_colors.sh"
source "$SCRIPT_DIR/../shell/bash_log.sh"
bash_colors
bash_log_init
# ─── Diccionario integrado ─────────────────────────────────────────────────────
_SUBDOMAIN_WORDLIST=(
www mail ftp api dev admin vpn ssh git gitlab github jenkins ci cd
staging prod test demo beta alpha app web portal intranet extranet
remote desktop files cdn static assets media img images upload
db database mysql postgres redis mongo smtp pop imap webmail mx
ns1 ns2 dns autodiscover autoconfig crm erp shop store payment
backup old legacy v1 v2 v3 internal corp office support helpdesk
wiki docs doc status monitor grafana kibana elastic search
registry docker k8s kubernetes auth sso login oauth api2 mobile
)
# ─── Funciones puras ──────────────────────────────────────────────────────────
_sub_is_valid_domain() {
[[ -n "$1" && "$1" =~ ^[a-zA-Z0-9._-]+\.[a-zA-Z]{2,}$ ]]
}
_sub_build_fqdn() {
local sub="$1"
local domain="$2"
echo "${sub}.${domain}"
}
# ─── Funciones de efecto ──────────────────────────────────────────────────────
_sub_resolve_a() {
local fqdn="$1"
dig +short A "$fqdn" 2>/dev/null | grep -E '^[0-9]+\.' | head -1 || true
}
_sub_resolve_cname() {
local fqdn="$1"
dig +short CNAME "$fqdn" 2>/dev/null | head -1 || true
}
# ─── Punto de entrada ─────────────────────────────────────────────────────────
enumerate_subdomains() {
local domain="$1"
local output_file="${2:-}"
if [[ -z "$domain" ]]; then
error "enumerate_subdomains: se requiere un dominio como argumento" >&2
return 1
fi
if ! _sub_is_valid_domain "$domain"; then
error "enumerate_subdomains: dominio no válido: '$domain'" >&2
return 1
fi
if ! command -v dig &>/dev/null; then
error "enumerate_subdomains: 'dig' no está instalado (sudo apt install dnsutils)" >&2
return 1
fi
local total="${#_SUBDOMAIN_WORDLIST[@]}"
local found=0
local checked=0
info "Probando ${total} subdominios en ${domain}..."
echo ""
if [[ -n "$output_file" ]]; then
echo "# Subdominios encontrados en ${domain} -- $(date)" > "$output_file"
fi
for sub in "${_SUBDOMAIN_WORDLIST[@]}"; do
local fqdn
fqdn="$(_sub_build_fqdn "$sub" "$domain")"
checked=$((checked + 1))
local ip
ip="$(_sub_resolve_a "$fqdn")"
if [[ -n "$ip" ]]; then
echo -e " ${GREEN}[ok]${NC} ${fqdn} -> ${CYAN}${ip}${NC}"
[[ -n "$output_file" ]] && echo "${fqdn} -> ${ip}" >> "$output_file"
found=$((found + 1))
else
local cname
cname="$(_sub_resolve_cname "$fqdn")"
if [[ -n "$cname" ]]; then
echo -e " ${YELLOW}[cn]${NC} ${fqdn} -> CNAME: ${cname}"
[[ -n "$output_file" ]] && echo "${fqdn} -> CNAME: ${cname}" >> "$output_file"
found=$((found + 1))
fi
fi
# Progreso cada 20 subdominios
if (( checked % 20 == 0 )); then
echo -e " ${DIM_GRAY}[${checked}/${total} probados, ${found} encontrados]${NC}"
fi
done
echo ""
echo -e "${PURPLE}════════════════════════════════════════════════════════════${NC}"
if [[ $found -eq 0 ]]; then
info "No se encontraron subdominios en el diccionario"
else
success "Total encontrados: ${found} de ${total} probados"
[[ -n "$output_file" ]] && info "Resultado guardado en: ${output_file}"
fi
echo -e "${PURPLE}════════════════════════════════════════════════════════════${NC}"
}
# Ejecutar si se llama directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
enumerate_subdomains "$@"
fi