SEVO/sevo

436 lines
15 KiB
Plaintext
Raw Permalink Normal View History

2024-11-16 12:47:53 -06:00
#!/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] <email>"
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:<validator@$our_hostname>"
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