#!/usr/bin/env bash # detect_suspicious_users # ----------------------- # Revisa el sistema en busca de usuarios potencialmente sospechosos: # UIDs 0 extras, shells válidas, homes en rutas inusuales, grupos privilegiados # y sesiones activas. # # USO (directo): # detect_suspicious_users # # Depende de: /etc/passwd, getent, w, lastlog 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 # ─── Constantes ─────────────────────────────────────────────────────────────── _SUSPICIOUS_VALID_SHELLS=("/bin/bash" "/bin/sh" "/bin/zsh" "/bin/fish" "/usr/bin/bash" "/usr/bin/zsh" "/usr/bin/fish") _SUSPICIOUS_PRIVILEGED_GROUPS=("sudo" "wheel" "docker" "adm" "lxd" "libvirt" "kvm" "disk" "shadow") _SUSPICIOUS_SYSTEM_USERS_MAX_UID=999 # ─── Funciones puras ────────────────────────────────────────────────────────── _sus_is_valid_shell() { local shell="$1" for s in "${_SUSPICIOUS_VALID_SHELLS[@]}"; do [[ "$shell" == "$s" ]] && return 0 done return 1 } _sus_is_system_user() { local uid="$1" [[ "$uid" -le $_SUSPICIOUS_SYSTEM_USERS_MAX_UID ]] } _sus_is_unusual_home() { local home="$1" [[ ! "$home" =~ ^(/home|/root|/var|/srv|/nonexistent|/tmp) ]] } # ─── Funciones de efecto ────────────────────────────────────────────────────── _sus_show_uid0_users() { echo -e "${PURPLE}════════ Usuarios con UID 0 (root) ═════════════${NC}" echo "" local found=0 while IFS=: read -r username _ uid _; do if [[ "$uid" -eq 0 ]]; then if [[ "$username" == "root" ]]; then echo -e " ${GREEN}[ok]${NC} root (esperado)" else echo -e " ${RED}[x]${NC} ${username} tiene UID 0 -- SOSPECHOSO" fi found=$((found + 1)) fi done < /etc/passwd if [[ $found -eq 1 ]]; then echo "" success "Solo root tiene UID 0" fi echo "" } _sus_show_users_with_shell() { echo -e "${PURPLE}════════ Usuarios con shell de login válida ═════${NC}" echo "" echo -e " ${GRAY}(excluye usuarios de sistema con UID <= ${_SUSPICIOUS_SYSTEM_USERS_MAX_UID})${NC}" echo "" local found=0 while IFS=: read -r username _ uid _ _ home shell; do if ! _sus_is_system_user "$uid" && _sus_is_valid_shell "$shell"; then echo -e " ${CYAN}*${NC} ${username} (UID ${uid}) -- shell: ${shell} -- home: ${home}" found=$((found + 1)) fi done < /etc/passwd [[ $found -eq 0 ]] && info "No se encontraron usuarios normales con shell válida" echo "" } _sus_show_unusual_homes() { echo -e "${PURPLE}════════ Usuarios con home inusual ══════════════${NC}" echo "" local found=0 while IFS=: read -r username _ uid _ _ home shell; do if _sus_is_valid_shell "$shell" && _sus_is_unusual_home "$home"; then echo -e " ${YELLOW}[!]${NC} ${username} -- home: ${home}" found=$((found + 1)) fi done < /etc/passwd [[ $found -eq 0 ]] && success "No se detectaron homes en rutas inusuales" echo "" } _sus_show_privileged_groups() { echo -e "${PURPLE}════════ Grupos privilegiados y sus miembros ════${NC}" echo "" for group in "${_SUSPICIOUS_PRIVILEGED_GROUPS[@]}"; do local members members="$(getent group "$group" 2>/dev/null | cut -d: -f4 || true)" if [[ -n "$members" ]]; then echo -e " ${YELLOW}*${NC} ${group}: ${members}" fi done echo "" } _sus_show_active_sessions() { echo -e "${PURPLE}════════ Sesiones activas ═══════════════════════${NC}" echo "" w 2>/dev/null | while IFS= read -r line; do echo -e " ${DIM_GRAY}${line}${NC}" done echo "" } _sus_show_last_logins() { echo -e "${PURPLE}════════ Últimos logins por usuario ═════════════${NC}" echo "" if command -v lastlog &>/dev/null; then lastlog 2>/dev/null | awk 'NR==1 || $NF != "logged" { if (NR==1 || $2 != "**Never") printf " %-16s %-10s %s\n", $1, $2, $NF }' | grep -v "^$" | while IFS= read -r line; do echo -e " ${DIM_GRAY}${line}${NC}" done else warning "lastlog no disponible" fi echo "" } # ─── Punto de entrada ───────────────────────────────────────────────────────── detect_suspicious_users() { _sus_show_uid0_users _sus_show_users_with_shell _sus_show_unusual_homes _sus_show_privileged_groups _sus_show_last_logins _sus_show_active_sessions } # Ejecutar si se llama directamente if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then detect_suspicious_users "$@" fi