#!/bin/bash # Versión del script VERSION="1.0.0" # Colores y símbolos RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' MAGENTA='\033[0;35m' CYAN='\033[0;36m' NC='\033[0m' CHECK_MARK="✓" CROSS_MARK="✗" WARN_MARK="⚠️" LOADING="⏳" SEARCH="🔍" VERBOSE=false STEALTH=false DELAY=0 SECURITY_SCORE=0 IS_SPOOFABLE=false SPF_STRICT=false DMARC_ENFORCED=false show_banner() { echo " ███████╗███╗ ███╗ █████╗ ██╗██╗ ██████╗ ███████╗██╗███╗ ██╗████████╗ ██╔════╝████╗ ████║██╔══██╗██║██║ ██╔═══██╗██╔════╝██║████╗ ██║╚══██╔══╝ █████╗ ██╔████╔██║███████║██║██║ ██║ ██║███████╗██║██╔██╗ ██║ ██║ ██╔══╝ ██║╚██╔╝██║██╔══██║██║██║ ██║ ██║╚════██║██║██║╚██╗██║ ██║ ███████╗██║ ╚═╝ ██║██║ ██║██║███████╗╚██████╔╝███████║██║██║ ╚████║ ██║ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ ╚══════╝╚═╝╚═╝ ╚═══╝ ╚═╝ " echo -e "${CYAN} Email OSINT Validator v$VERSION${NC}" echo -e "${YELLOW} Uso ético - Solo para investigación autorizada${NC}" echo } show_help() { echo "Uso: $0 [opciones] " echo echo "Opciones:" echo " -v, --verbose Modo verbose, muestra información detallada" echo " -s, --stealth Modo sigiloso, más lento pero menos detectable" echo " -d, --delay N Añade un delay de N segundos entre consultas" echo " -h, --help Muestra esta ayuda" echo " --version Muestra la versión" echo echo "Ejemplos:" echo " $0 usuario@dominio.com" echo " $0 -v usuario@dominio.com" echo " $0 -s -d 2 usuario@dominio.com" exit 0 } show_spinner() { local pid=$1 local delay=0.1 local spinstr='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏' printf "\r" while ps -p $pid > /dev/null 2>&1; do local temp=${spinstr#?} printf "\r[%c] " "$spinstr" local spinstr=$temp${spinstr%"$temp"} sleep $delay done printf "\r \r" } log() { local level=$1 local message=$2 if [[ $VERBOSE == true ]] || [[ $level != "DEBUG" ]]; then case $level in "INFO") echo -e "${GREEN}${CHECK_MARK}${NC} $message";; "WARN") echo -e "${YELLOW}${WARN_MARK}${NC} $message";; "ERROR") echo -e "${RED}${CROSS_MARK}${NC} $message";; "DEBUG") echo -e "${BLUE}${SEARCH}${NC} $message";; esac fi } analyze_mx_security() { local domain=$1 local security_features=() local vulnerabilities=() local spf_strict=false local dmarc_enforced=false local spoofable=false local security_score=0 local max_score=100 log "DEBUG" "Iniciando análisis de seguridad profundo para $domain" log "DEBUG" "Analizando registros SPF..." local spf_record=$(host -t TXT "$domain" | grep "v=spf1") if [ -n "$spf_record" ]; then security_features+=("SPF") security_score=$((security_score + 20)) if [[ $spf_record =~ "-all" ]]; then security_features+=("SPF_STRICT") spf_strict=true security_score=$((security_score + 15)) elif [[ $spf_record =~ "~all" ]]; then security_features+=("SPF_SOFT_FAIL") vulnerabilities+=("SPF no es estricto (usa ~all)") security_score=$((security_score + 10)) elif [[ $spf_record =~ "\?all" ]]; then vulnerabilities+=("SPF en modo neutral") security_score=$((security_score + 5)) elif [[ $spf_record =~ "\+all" ]]; then vulnerabilities+=("SPF permite cualquier remitente") spoofable=true fi else vulnerabilities+=("No se encontró registro SPF") spoofable=true fi log "DEBUG" "Analizando política DMARC..." local dmarc_record=$(host -t TXT "_dmarc.$domain" | grep "v=DMARC1") if [ -n "$dmarc_record" ]; then security_features+=("DMARC") security_score=$((security_score + 20)) if [[ $dmarc_record =~ "p=reject" ]]; then security_features+=("DMARC_ENFORCED") dmarc_enforced=true security_score=$((security_score + 15)) elif [[ $dmarc_record =~ "p=quarantine" ]]; then security_features+=("DMARC_QUARANTINE") security_score=$((security_score + 10)) elif [[ $dmarc_record =~ "p=none" ]]; then vulnerabilities+=("DMARC en modo monitoreo") security_score=$((security_score + 5)) fi if [[ $dmarc_record =~ "pct=100" ]] || [[ ! $dmarc_record =~ "pct=" ]]; then security_score=$((security_score + 5)) else local pct=$(echo "$dmarc_record" | grep -oP 'pct=\K[0-9]+') vulnerabilities+=("DMARC solo aplicado al $pct% del tráfico") fi else vulnerabilities+=("No se encontró registro DMARC") spoofable=true fi log "DEBUG" "Analizando configuración DKIM..." local dkim_selectors=("default" "google" "mail" "email" "key1" "selector1" "selector2") local dkim_found=false for selector in "${dkim_selectors[@]}"; do if host -t TXT "${selector}._domainkey.$domain" 2>/dev/null | grep -q "v=DKIM1"; then security_features+=("DKIM") security_score=$((security_score + 15)) dkim_found=true break fi done if ! $dkim_found; then vulnerabilities+=("No se encontró registro DKIM") fi log "DEBUG" "Verificando MTA-STS..." if host -t TXT "_mta-sts.$domain" 2>/dev/null | grep -q "v=STSv1"; then security_features+=("MTA-STS") security_score=$((security_score + 10)) else vulnerabilities+=("MTA-STS no configurado") fi if host -t TXT "_smtp._tls.$domain" 2>/dev/null | grep -q "v=TLSRPTv1"; then security_features+=("TLSRPT") security_score=$((security_score + 5)) fi if dig "$domain" +dnssec | grep -q "RRSIG"; then security_features+=("DNSSEC") security_score=$((security_score + 10)) fi cat << EOF ╔════════════════════════════════════════════════════════════════ ║ 🔒 Análisis de Seguridad para $domain ╠════════════════════════════════════════════════════════════════ ║ 📊 Puntuación de Seguridad: $security_score/$max_score EOF if [ ${#security_features[@]} -gt 0 ]; then cat << EOF ║ ║ ✅ Características de Seguridad Detectadas: EOF for feature in "${security_features[@]}"; do printf "║ - %s\n" "$feature" done fi if [ ${#vulnerabilities[@]} -gt 0 ]; then cat << EOF ║ ║ ⚠️ Vulnerabilidades Detectadas: EOF for vuln in "${vulnerabilities[@]}"; do printf "║ - %s\n" "$vuln" done fi cat << EOF ║ ║ 🎯 Estado de Protecciones: ║ - SPF Estricto: $(if $spf_strict; then echo "✅"; else echo "❌"; fi) ║ - DMARC Enforced: $(if $dmarc_enforced; then echo "✅"; else echo "❌"; fi) ║ - Spoofing Posible: $(if $spoofable; then echo "⚠️ SÍ"; else echo "✅ NO"; fi) ╚════════════════════════════════════════════════════════════════ EOF SECURITY_SCORE=$security_score IS_SPOOFABLE=$spoofable SPF_STRICT=$spf_strict DMARC_ENFORCED=$dmarc_enforced } fingerprint_server() { local response=$1 local server_info=$(echo "$response" | grep -i "^220" | head -n1) if [[ $server_info =~ "Microsoft" ]]; then log "INFO" "Servidor detectado: Microsoft Exchange/Office 365" [[ $VERBOSE == true ]] && log "DEBUG" "Sistema de correo empresarial Microsoft" elif [[ $server_info =~ "Google" ]]; then log "INFO" "Servidor detectado: Google Workspace" [[ $VERBOSE == true ]] && log "DEBUG" "Sistema de correo Google Workspace" elif [[ $server_info =~ "Postfix" ]]; then log "INFO" "Servidor detectado: Postfix" [[ $VERBOSE == true ]] && log "DEBUG" "Servidor de correo Postfix (Linux)" elif [[ $server_info =~ "Exim" ]]; then log "INFO" "Servidor detectado: Exim" [[ $VERBOSE == true ]] && log "DEBUG" "Servidor de correo Exim" elif [[ $server_info =~ "Sendmail" ]]; then log "INFO" "Servidor detectado: Sendmail" [[ $VERBOSE == true ]] && log "DEBUG" "Servidor de correo Sendmail" elif [[ $server_info =~ "Zimbra" ]]; then log "INFO" "Servidor detectado: Zimbra" [[ $VERBOSE == true ]] && log "DEBUG" "Suite de colaboración Zimbra" else log "INFO" "Servidor no identificado específicamente" [[ $VERBOSE == true ]] && log "DEBUG" "Banner del servidor: $server_info" fi } validate_email() { local email=$1 local domain=$(echo "$email" | cut -d "@" -f 2) local our_hostname="email-validator-osint.local" log "INFO" "Verificando correo: $email" if ! echo "$email" | grep -E "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$" >/dev/null; then log "ERROR" "Formato de correo inválido" return 1 fi log "INFO" "La sintaxis del correo es correcta" log "INFO" "Buscando registros MX..." local mx_output=$(host -t MX "$domain") if [ $? -ne 0 ]; then log "ERROR" "No se encontraron registros MX para $domain" return 1 fi log "INFO" "Registros MX encontrados:" local primary_mx="" local current_priority=999 while read -r line; do if [[ $line =~ "is handled by" ]]; then local server=$(echo "$line" | awk '{print $NF}' | sed 's/\.$//') local priority=$(echo "$line" | awk '{print $(NF-1)}') log "INFO" "MX record encontrado: $server (Prioridad $priority)" if [ -z "$primary_mx" ] || [ "$priority" -lt "$current_priority" ]; then primary_mx=$server current_priority=$priority fi fi done <<< "$mx_output" [[ $VERBOSE == true ]] && analyze_mx_security "$domain" if [ -n "$primary_mx" ]; then [[ $STEALTH == true ]] && sleep $DELAY echo -ne "${LOADING} Iniciando diálogo con $primary_mx " temp_commands=$(mktemp) { echo "EHLO $our_hostname" echo "MAIL FROM:" echo "RCPT TO:<$email>" echo "QUIT" } > "$temp_commands" nc -w 10 "$primary_mx" 25 < "$temp_commands" > response.tmp 2>&1 & nc_pid=$! show_spinner $nc_pid wait $nc_pid rm -f "$temp_commands" echo -e "\r${CHECK_MARK} Diálogo con $primary_mx completado " log "INFO" "Respuestas del servidor:" local email_status="válido" local problem_description="" local valid_response=false while read -r line; do if [[ $line =~ ^[0-9]{3} ]]; then echo " $line" local code=${line:0:3} valid_response=true if [[ $code == "220" ]] && [[ $VERBOSE == true ]]; then fingerprint_server "$line" fi case $code in 250) if [[ $line =~ "RCPT" ]]; then email_status="válido" log "INFO" "Correo verificado exitosamente" fi ;; 421) email_status="no verificable" problem_description="El servidor no está disponible temporalmente" log "WARN" "$problem_description" ;; 450|452) email_status="temporalmente no disponible" problem_description="Buzón temporalmente no disponible" log "WARN" "$problem_description" ;; 500|501|502|503|504) if [[ $VERBOSE == true ]]; then log "DEBUG" "Código $code: Error de protocolo (normal durante la negociación)" fi ;; 550) if [[ $line =~ "RCPT" ]] || [[ $line =~ "user" ]] || [[ $line =~ "recipient" ]]; then email_status="no válido" problem_description="La dirección de correo no existe" log "ERROR" "$problem_description" fi ;; 551|553) email_status="no válido" problem_description="La dirección de correo no está permitida" log "ERROR" "$problem_description" ;; 554) email_status="no válido" problem_description="Transacción fallida" log "ERROR" "$problem_description" ;; esac fi done < response.tmp rm -f response.tmp if [[ "$email_status" == "válido" ]]; then log "INFO" "El correo $email es válido" return 0 elif [[ "$email_status" == "no válido" ]]; then log "ERROR" "El correo $email no es válido" [ -n "$problem_description" ] && log "ERROR" "Razón: $problem_description" return 1 else log "WARN" "Estado del correo $email: $email_status" [ -n "$problem_description" ] && log "WARN" "Razón: $problem_description" return 1 fi fi } for cmd in host nc timeout dig bc mktemp; do if ! command -v $cmd &> /dev/null; then echo -e "${RED}${CROSS_MARK} Error: El comando '$cmd' no está instalado.${NC}" echo " Instala las dependencias necesarias con:" echo " sudo pacman -S bind-tools openbsd-netcat coreutils bc" echo " o" echo " sudo apt install bind9-host netcat coreutils bc" exit 1 fi done while [[ $# -gt 0 ]]; do case $1 in -v|--verbose) VERBOSE=true; shift;; -s|--stealth) STEALTH=true; shift;; -d|--delay) DELAY="$2"; shift 2;; -h|--help) show_help;; --version) echo "Email Validator OSINT v$VERSION"; exit 0;; *) EMAIL="$1"; shift;; esac done if [ -z "$EMAIL" ]; then show_help fi show_banner validate_email "$EMAIL" exit_code=$? if [[ $VERBOSE == true ]] && [[ $exit_code -eq 0 ]]; then echo -e "\n${GREEN}🎉 Análisis completado exitosamente${NC}" if [[ $SECURITY_SCORE -ge 80 ]]; then echo -e "${GREEN}🛡️ El dominio tiene buenas protecciones de seguridad${NC}" elif [[ $SECURITY_SCORE -ge 50 ]]; then echo -e "${YELLOW}⚠️ El dominio tiene protecciones moderadas${NC}" else echo -e "${RED}⚠️ El dominio tiene protecciones débiles${NC}" fi fi exit $exit_code