diff --git a/01_bash/check_abuseipdb.sh b/01_bash/check_abuseipdb.sh new file mode 100644 index 0000000..0d28125 --- /dev/null +++ b/01_bash/check_abuseipdb.sh @@ -0,0 +1,204 @@ +#!/usr/bin/env bash + +# Script: check_abuseipdb.sh +# Descripción: Este script automatiza la comprobación de direcciones IP contra +# la base de datos AbuseIPDB. Para cada IP proporcionada, el script +# obtiene información sobre su abuso potencial, utilizando la API +# de AbuseIPDB. Registra los resultados en un archivo de log. +# Además, proporciona detalles sobre el país, ISP, tipo de uso y +# categorías de ataque asociadas con la IP. Los resultados se +# clasifican como "Sospechosa" o "No sospechosa" basándose en +# el puntaje de abuso. +# Requisitos: +# - jq, curl. +# - Añadir la API key de AbuseIPDB en la variable de entorno API_KEY_ipabuse o +# introducirla al inicio del script. Conseguir API en plan individual Free: +# https://www.abuseipdb.com/pricing +# - Añadir la lista de IPs a comprobar en la variable de entorno IPS_LIST_abuseipdb +# o introducirlas al inicio del script (una IP por línea). +# Author: Manuel Vergara +# Web: https://vergaracarmona.es +# + +set -euo pipefail + +# Variables de configuración +MAX_AGE_DAYS=90 # Número de días de historial a comprobar +SLEEP_BETWEEN=1 # Tiempo de espera entre las comprobaciones de IPs +THRESHOLD=50 # Umbral de score para considerar una IP sospechosa + +# Colores para salida +COLOR_RED='\e[31m' # Color para mensajes de error +COLOR_GREEN='\e[32m' # Color para mensajes exitosos +COLOR_YELLOW='\e[33m' # Color para mensajes informativos +COLOR_BLUE='\e[34m' # Color para títulos y encabezados +COLOR_RESET='\e[0m' # Resetea el color al valor predeterminado + +# Archivo de log (cambiar la ubicación a un directorio accesible) +LOG_FILE="./check_ips_script.log" # Cambiado a un directorio accesible para el usuario + +# Función para manejar la salida con Ctrl + C +function ctrl_c() { + echo -e "${COLOR_RED}\n\n[!] Saliendo... \n${COLOR_RESET}" + tput cnorm + log_message "El script se ha detenido debido a una interrupción del usuario." + exit 1 +} + +# Configurar Ctrl+C para detener el script +trap ctrl_c SIGINT + +# Función para registrar mensajes en el archivo de log +function log_message() { + local message="$1" + echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >>"$LOG_FILE" +} + +# Función para imprimir títulos con formato y colores +function print_title { + local title="$1" + local title_length=${#title} + local total_length=22 + local margin_length=$(((total_length - title_length - 4) / 2)) + local left_padding=$((margin_length)) + local right_padding=$((margin_length + (title_length % 2))) + + echo -e "${COLOR_BLUE}\n$(printf '#%.0s' $(seq 1 $left_padding))#### $title ####$(printf '#%.0s' $(seq 1 $right_padding))\n${COLOR_RESET}" +} + +# Comprobación de dependencias necesarias +for cmd in jq curl; do + if ! command -v "$cmd" >/dev/null 2>&1; then + echo -e "${COLOR_RED}Error: '$cmd' no está instalado. Instálalo y vuelve a ejecutar.${COLOR_RESET}" >&2 + log_message "Error: '$cmd' no está instalado." + exit 2 + fi +done + +log_message "Iniciando el script de comprobación de IPs." + +# Leer API_KEY desde variable de entorno o pedir al usuario +API_KEY="${API_KEY_ipabuse:-}" +if [[ -z "$API_KEY" ]]; then + read -rp "Introduce tu API key de AbuseIPDB: " API_KEY + if [[ -z "$API_KEY" ]]; then + echo -e "${COLOR_RED}Error: la API key es obligatoria.${COLOR_RESET}" >&2 + log_message "Error: No se proporcionó API Key." + exit 1 + fi +fi + +# Leer lista de IPs desde variable de entorno o pedir al usuario +IPS_LIST="${IPS_LIST_abuseipdb:-}" +if [[ -z "$IPS_LIST" ]]; then + echo -e "${COLOR_YELLOW}Introduce el listado de IPs (una por línea). Finaliza con Ctrl+D:${COLOR_RESET}" + IPS_LIST="$(cat)" + if [[ -z "$IPS_LIST" ]]; then + echo -e "${COLOR_RED}Error: no se proporcionaron IPs.${COLOR_RESET}" >&2 + log_message "Error: No se proporcionaron IPs." + exit 1 + fi +fi + +# Convertir lista de IPs multilínea a array para procesar cada IP +mapfile -t iterator <<< "$IPS_LIST" + +# Imprimir el título principal del script +print_title "Comprobando IPs en AbuseIPDB" + +# Procesar cada IP +for ip in "${iterator[@]}"; do + ip=$(echo "$ip" | xargs) # Eliminar espacios en blanco extra + [[ -z "$ip" ]] && continue # Saltar si la IP está vacía + + echo -e "${COLOR_BLUE}=== IP: $ip ===${COLOR_RESET}" + + # Hacer la solicitud a la API de AbuseIPDB + resp=$(curl -sS -G "https://api.abuseipdb.com/api/v2/check" \ + --data-urlencode "ipAddress=$ip" \ + --data-urlencode "maxAgeInDays=$MAX_AGE_DAYS" \ + --data-urlencode "verbose=true" \ + -H "Key: $API_KEY" \ + -H "Accept: application/json") + + # Controlar si no se obtiene respuesta de la API + if [[ -z "$resp" ]]; then + echo -e "${COLOR_RED}❌ Sin respuesta de la API.${COLOR_RESET}" + log_message "Error: No se recibió respuesta para la IP $ip." + continue + fi + + # Verificar si hay errores en la respuesta de la API + if echo "$resp" | jq -e '.errors? != null' >/dev/null; then + echo -e "${COLOR_RED}❌ Error de API:${COLOR_RESET}" + echo "$resp" | jq '.errors' + log_message "Error de API para la IP $ip: $(echo "$resp" | jq -r '.errors')" + continue + fi + + # Extraer datos importantes de la respuesta JSON + abuseScore=$(echo "$resp" | jq -r '.data.abuseConfidenceScore // 0') + totalReports=$(echo "$resp" | jq -r '.data.totalReports // 0') + lastReported=$(echo "$resp" | jq -r '.data.lastReportedAt // "N/A"') + country=$(echo "$resp" | jq -r '.data.countryCode // "N/A"') + isp=$(echo "$resp" | jq -r '.data.isp // "N/A"') + usage=$(echo "$resp" | jq -r '.data.usageType // "N/A"') + + # Mostrar los resultados de la IP + echo " País: $country" + echo " ISP: $isp" + echo " Uso: $usage" + echo " Total reportes: $totalReports" + echo " Último reporte: $lastReported" + echo " Score abuso: $abuseScore" + + # Contar categorías de ataques reportados + if (( totalReports > 0 )); then + echo -e "${COLOR_YELLOW} Categorías reportadas:${COLOR_RESET}" + declare -A category_map=( + [3]="Fraude en pedidos" + [4]="Ataque DDoS" + [5]="Fuerza bruta FTP" + [6]="Ping of Death" + [7]="Phishing" + [8]="Fraude VoIP" + [9]="Proxy abierto" + [10]="Spam en web" + [11]="Spam por email" + [12]="Spam en blogs" + [13]="VPN" + [14]="Escaneo de puertos" + [15]="Hacking" + [16]="SQL Injection" + [17]="Spoofing" + [18]="Fuerza bruta" + [19]="Bot malicioso" + [20]="Host explotado" + [21]="Ataque a app web" + [22]="Acceso SSH" + [23]="Objetivo IoT" + ) + + # Mostrar las categorías de ataque reportadas + echo "$resp" | jq -r '.data.reports[].categories[]' | sort | uniq -c | sort -rn | while read -r count cat; do + description="${category_map[$cat]:-Desconocida}" + echo " - $description (Categoría $cat): $count veces" + done + fi + + # Evaluar si la IP es sospechosa en base al score + if (( abuseScore >= THRESHOLD )); then + echo -e "${COLOR_RED} 🔴 Resultado: SOSPECHOSA (score >= $THRESHOLD)${COLOR_RESET}" + log_message "IP: $ip - Resultado: SOSPECHOSA (score >= $THRESHOLD)" + else + echo -e "${COLOR_GREEN} 🟢 Resultado: OK / No sospechosa (score < $THRESHOLD)${COLOR_RESET}" + log_message "IP: $ip - Resultado: OK / No sospechosa (score < $THRESHOLD)" + fi + + echo + sleep "$SLEEP_BETWEEN" # Pausar entre cada consulta de IP +done + +# Mensaje final de éxito +echo -e "${COLOR_GREEN}✅ Comprobación finalizada.${COLOR_RESET}" +log_message "El script se ejecutó correctamente."