#!/bin/bash # # Suspicious Login Monitor - Integrated Security Analysis # Detects suspicious login patterns and correlates with web attack activity # Supports: cPanel, Plesk, InterWorx, Standalone # # Get script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TOOLKIT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" # Configuration SUSPICIOUS_LOGIN_AUTO_BLOCK="${SUSPICIOUS_LOGIN_AUTO_BLOCK:-yes}" SUSPICIOUS_LOGIN_AUTO_SCAN="${SUSPICIOUS_LOGIN_AUTO_SCAN:-yes}" SUSPICIOUS_LOGIN_EMAIL_ALERTS="${SUSPICIOUS_LOGIN_EMAIL_ALERTS:-no}" # Risk thresholds RISK_CRITICAL=85 RISK_HIGH=70 RISK_MEDIUM=50 # Integration paths BOT_ANALYZER="$TOOLKIT_ROOT/modules/security/bot-analyzer.sh" MALWARE_SCANNER="$TOOLKIT_ROOT/modules/security/malware-scanner.sh" IP_REPUTATION_LIB="$TOOLKIT_ROOT/lib/ip-reputation.sh" THREAT_INTEL_LIB="$TOOLKIT_ROOT/lib/threat-intelligence.sh" # Temp files TMP_DIR="/tmp" REPORT_FILE="$TMP_DIR/suspicious_login_report_$(date +%Y%m%d_%H%M%S).txt" SSH_EVENTS="$TMP_DIR/ssh_events_$$.txt" PANEL_EVENTS="$TMP_DIR/panel_events_$$.txt" SUSPICIOUS_IPS="$TMP_DIR/suspicious_ips_$$.txt" # Analysis period (default: last 24 hours) HOURS="${1:-24}" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # Cleanup on exit trap cleanup EXIT cleanup() { rm -f "$SSH_EVENTS" "$PANEL_EVENTS" "$SUSPICIOUS_IPS" 2>/dev/null } # Detect control panel detect_panel() { if [ -d /usr/local/cpanel ]; then echo "cpanel" elif [ -d /usr/local/psa ]; then echo "plesk" elif [ -d /home/interworx ]; then echo "interworx" else echo "standalone" fi } # Get server IPs to exclude get_server_ips() { { echo "127.0.0.1" echo "::1" ip addr | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v "^127\." ip addr | grep -oP '(?<=inet6\s)[0-9a-f:]+' | grep -v "^::1" } | sort -u } # # SSH LOG PARSING # parse_ssh_logins() { local hours=$1 local secure_log="/var/log/secure" # Use auth.log on Debian-based systems if [ ! -f "$secure_log" ] && [ -f "/var/log/auth.log" ]; then secure_log="/var/log/auth.log" fi if [ ! -f "$secure_log" ]; then return 0 fi echo " Parsing SSH login attempts..." >&2 # Parse successful SSH logins awk -v hours="$hours" ' BEGIN { # Calculate time threshold cmd = "date -d \"" hours " hours ago\" +%s" cmd | getline threshold close(cmd) } /sshd.*Accepted/ { # Parse timestamp timestamp = $1 " " $2 " " $3 cmd = "date -d \"" timestamp "\" +%s 2>/dev/null" cmd | getline epoch close(cmd) if (epoch < threshold) next # Extract details user = "" ip = "" method = "" # Accepted password for user from ip if (match($0, /Accepted (password|publickey) for ([^ ]+) from ([^ ]+)/)) { method = (index($0, "publickey") > 0) ? "key" : "password" for (i=1; i<=NF; i++) { if ($i == "for") user = $(i+1) if ($i == "from") ip = $(i+1) } } if (user != "" && ip != "") { print timestamp "|" user "|" ip "|ssh|" method "|success" } } /sshd.*Failed/ { # Parse timestamp timestamp = $1 " " $2 " " $3 cmd = "date -d \"" timestamp "\" +%s 2>/dev/null" cmd | getline epoch close(cmd) if (epoch < threshold) next # Extract details user = "" ip = "" # Failed password for user from ip if (match($0, /Failed password for/)) { for (i=1; i<=NF; i++) { if ($i == "for") user = $(i+1) if ($i == "from") ip = $(i+1) } } if (user != "" && ip != "") { print timestamp "|" user "|" ip "|ssh|password|failed" } } ' "$secure_log" > "$SSH_EVENTS" } # # CPANEL LOG PARSING # parse_cpanel_logins() { local hours=$1 local whm_log="/usr/local/cpanel/logs/access_log" local cpanel_log="/usr/local/cpanel/logs/login_log" echo " Parsing cPanel/WHM logins..." >&2 # WHM access log if [ -f "$whm_log" ]; then awk -v hours="$hours" ' BEGIN { cmd = "date -d \"" hours " hours ago\" +%s" cmd | getline threshold close(cmd) } { # Parse timestamp [01/Feb/2026:19:30:00] if (match($4, /\[([0-9]{2})\/([A-Za-z]{3})\/([0-9]{4}):([0-9:]+)\]/)) { timestamp_str = substr($4, 2) cmd = "date -d \"" timestamp_str "\" +\"%b %d %H:%M:%S\" 2>/dev/null" cmd | getline timestamp close(cmd) cmd = "date -d \"" timestamp_str "\" +%s 2>/dev/null" cmd | getline epoch close(cmd) if (epoch < threshold) next # Extract IP (first field) ip = $1 # Check for WHM login if (match($0, /POST \/login\//) || match($0, /GET \/cpsess/)) { # Extract user from URL if possible user = "root" # WHM is root access status = "success" if ($9 ~ /^(40|50)/) status = "failed" print timestamp "|" user "|" ip "|whm|web|" status } } } ' "$whm_log" >> "$PANEL_EVENTS" fi # cPanel login log if [ -f "$cpanel_log" ]; then awk -v hours="$hours" ' BEGIN { cmd = "date -d \"" hours " hours ago\" +%s" cmd | getline threshold close(cmd) } { # Parse timestamp timestamp = $1 " " $2 " " $3 cmd = "date -d \"" timestamp "\" +%s 2>/dev/null" cmd | getline epoch close(cmd) if (epoch < threshold) next # Extract user and IP if (match($0, /user: ([^ ]+).*ip: ([^ ]+)/)) { for (i=1; i<=NF; i++) { if ($i == "user:") user = $(i+1) if ($i == "ip:") ip = $(i+1) } status = (match($0, /FAILED/) || match($0, /failed/)) ? "failed" : "success" if (user != "" && ip != "") { print timestamp "|" user "|" ip "|cpanel|web|" status } } } ' "$cpanel_log" >> "$PANEL_EVENTS" fi } # # PLESK LOG PARSING # parse_plesk_logins() { local hours=$1 local plesk_log="/var/log/plesk/panel.log" # Try alternative location if [ ! -f "$plesk_log" ]; then plesk_log="/usr/local/psa/var/log/panel.log" fi if [ ! -f "$plesk_log" ]; then return 0 fi echo " Parsing Plesk panel logins..." >&2 awk -v hours="$hours" ' BEGIN { cmd = "date -d \"" hours " hours ago\" +%s" cmd | getline threshold close(cmd) } /login/ { # Parse timestamp (ISO format: 2026-02-02 19:30:00) timestamp = $1 " " $2 cmd = "date -d \"" timestamp "\" +%s 2>/dev/null" cmd | getline epoch close(cmd) if (epoch < threshold) next # Extract user and IP user = "" ip = "" status = "success" if (match($0, /user=([^ ]+)/)) { for (i=1; i<=NF; i++) { if (match($i, /user=/)) { gsub(/user=/, "", $i) user = $i } if (match($i, /ip=/)) { gsub(/ip=/, "", $i) ip = $i } } } if (match($0, /failed/)) status = "failed" if (user != "" && ip != "") { print timestamp "|" user "|" ip "|plesk|web|" status } } ' "$plesk_log" >> "$PANEL_EVENTS" } # # INTERWORX LOG PARSING # parse_interworx_logins() { local hours=$1 local iworx_log="/home/interworx/var/log/iworx.log" local siteworx_log="/home/interworx/var/log/siteworx.log" if [ ! -f "$iworx_log" ]; then return 0 fi echo " Parsing InterWorx logins..." >&2 # Parse NodeWorx (admin) logins awk -v hours="$hours" ' BEGIN { cmd = "date -d \"" hours " hours ago\" +%s" cmd | getline threshold close(cmd) } /login/ { timestamp = $1 " " $2 cmd = "date -d \"" timestamp "\" +%s 2>/dev/null" cmd | getline epoch close(cmd) if (epoch < threshold) next # Extract details user = "" ip = "" status = "success" for (i=1; i<=NF; i++) { if (match($i, /user=/)) { gsub(/user=/, "", $i) user = $i } if (match($i, /ip=/)) { gsub(/ip=/, "", $i) ip = $i } } if (match($0, /failed/)) status = "failed" if (user != "" && ip != "") { print timestamp "|" user "|" ip "|interworx|web|" status } } ' "$iworx_log" >> "$PANEL_EVENTS" } # # ANOMALY DETECTION # detect_anomalies() { echo " Analyzing login patterns..." >&2 # Combine all events cat "$SSH_EVENTS" "$PANEL_EVENTS" 2>/dev/null | \ awk -F'|' -v server_ips="$(get_server_ips | tr '\n' '|')" ' { timestamp = $1 user = $2 ip = $3 service = $4 method = $5 status = $6 # Skip server IPs if (index(server_ips, ip "|") > 0) next # Skip cPanel internal IPs if (match(ip, /^(208\.74\.123\.|184\.94\.197\.)/)) next # Track all events by IP ip_events[ip]++ ip_users[ip] = ip_users[ip] (ip_users[ip] ? "," : "") user # Track failed attempts if (status == "failed") { failed[ip]++ failed_users[ip] = failed_users[ip] (failed_users[ip] ? "," : "") user } # Track successful logins if (status == "success") { successful[ip]++ successful_users[ip] = successful_users[ip] (successful_users[ip] ? "," : "") user successful_services[ip] = successful_services[ip] (successful_services[ip] ? "," : "") service # Track root access if (user == "root") { root_logins[ip]++ root_methods[ip] = root_methods[ip] (root_methods[ip] ? "," : "") method } # Track password vs key auth if (method == "password") { password_auth[ip]++ } else if (method == "key") { key_auth[ip]++ } } # Store first and last seen if (first_seen[ip] == "") { first_seen[ip] = timestamp } last_seen[ip] = timestamp } END { for (ip in ip_events) { risk = 0 reasons = "" # Root access risk if (root_logins[ip] > 0) { risk += 20 reasons = reasons "Root-Access " # Password auth for root (higher risk) if (index(root_methods[ip], "password") > 0) { risk += 10 reasons = reasons "Root-Password-Auth " } } # Failed login risk if (failed[ip] > 0) { fail_score = failed[ip] * 5 if (fail_score > 25) fail_score = 25 risk += fail_score reasons = reasons "Failed-Attempts(" failed[ip] ") " # Failed root attempts (very suspicious) if (index(failed_users[ip], "root") > 0) { risk += 15 reasons = reasons "Failed-Root " } } # Brute force detection if (failed[ip] >= 5) { risk += 20 reasons = reasons "Brute-Force " } # Multiple users from same IP (potential attack) split(ip_users[ip], user_arr, ",") unique_users = 0 for (u in user_arr) unique_users++ if (unique_users > 3) { risk += 15 reasons = reasons "Multiple-Users(" unique_users ") " } # Password auth risk (should use keys) if (password_auth[ip] > 0 && key_auth[ip] == 0) { risk += 5 reasons = reasons "Password-Only " } # Cap at 100 if (risk > 100) risk = 100 # Only report suspicious IPs (risk >= 30) if (risk >= 30) { print ip "|" risk "|" reasons "|" successful[ip] "|" failed[ip] "|" root_logins[ip] "|" ip_users[ip] "|" successful_services[ip] } } } ' | sort -t'|' -k2 -nr > "$SUSPICIOUS_IPS" } # # BOT ANALYZER INTEGRATION # correlate_with_access_logs() { local ip=$1 local risk_score=$2 # Find most recent bot analyzer report local latest_report=$(ls -t "$TOOLKIT_ROOT"/tmp/bot_analysis_report_*.txt /tmp/bot_analysis_report_*.txt 2>/dev/null | head -n1) if [ -z "$latest_report" ]; then echo "0|No bot analyzer data available" return 0 fi # Check if this IP appears in bot analyzer results local ip_data=$(grep -F "$ip" "$latest_report" 2>/dev/null || echo "") if [ -z "$ip_data" ]; then echo "0|No access log activity" return 0 fi # Extract attack vectors from bot analyzer report local attack_vectors="" local additional_risk=0 # Look for attack patterns in the report around this IP local context=$(grep -A 5 -B 5 "$ip" "$latest_report" 2>/dev/null) # Check for specific attack types if echo "$context" | grep -qi "RCE/Upload"; then attack_vectors="$attack_vectors RCE/Upload" additional_risk=$((additional_risk + 25)) fi if echo "$context" | grep -qi "SQLi\|SQL injection"; then attack_vectors="$attack_vectors SQLi" additional_risk=$((additional_risk + 20)) fi if echo "$context" | grep -qi "Admin.*prob\|wp-login\|admin login"; then attack_vectors="$attack_vectors Admin-Probe" additional_risk=$((additional_risk + 15)) fi if echo "$context" | grep -qi "Login.*Brute\|brute.*force"; then attack_vectors="$attack_vectors Login-Bruteforce" additional_risk=$((additional_risk + 15)) fi if echo "$context" | grep -qi "Info.*Disclosure\|info disclosure"; then attack_vectors="$attack_vectors Info-Disclosure" additional_risk=$((additional_risk + 10)) fi if echo "$context" | grep -qi "XSS"; then attack_vectors="$attack_vectors XSS" additional_risk=$((additional_risk + 10)) fi # Cap at 100 local new_risk=$((risk_score + additional_risk)) [ $new_risk -gt 100 ] && new_risk=100 echo "$additional_risk|$attack_vectors" } # # IP REPUTATION CHECK # check_ip_reputation() { local ip=$1 local risk_score=$2 # Source IP reputation library if available if [ ! -f "$IP_REPUTATION_LIB" ]; then echo "0|IP reputation library not available" return 0 fi source "$IP_REPUTATION_LIB" local additional_risk=0 local notes="" # Check whitelist if is_whitelisted "$ip" 2>/dev/null; then echo "-30|Whitelisted IP" return 0 fi # Check blacklist if is_blacklisted "$ip" 2>/dev/null; then additional_risk=$((additional_risk + 20)) notes="$notes Previously-Blacklisted" fi # Check reputation score local reputation=$(get_ip_reputation "$ip" 2>/dev/null) if [ -n "$reputation" ] && [ "$reputation" -lt 40 ]; then additional_risk=$((additional_risk + 15)) notes="$notes Poor-Reputation($reputation)" fi echo "$additional_risk|$notes" } # # THREAT INTELLIGENCE CORRELATION # correlate_with_threat_intel() { local ip=$1 # Source threat intelligence library if available if [ ! -f "$THREAT_INTEL_LIB" ]; then echo "0|Threat intelligence not available" return 0 fi source "$THREAT_INTEL_LIB" local additional_risk=0 local notes="" # Check known botnets if is_known_botnet "$ip" 2>/dev/null; then additional_risk=$((additional_risk + 30)) notes="$notes Known-Botnet" fi # GeoIP check (if available) if command -v geoiplookup &>/dev/null; then local country=$(geoiplookup "$ip" 2>/dev/null | awk -F': ' '{print $2}' | head -n1) if [ -n "$country" ]; then notes="$notes Country:$country" # High-risk countries case "$country" in *China*|*Russia*|*North\ Korea*) additional_risk=$((additional_risk + 10)) notes="$notes High-Risk-Geo" ;; esac fi fi echo "$additional_risk|$notes" } # # AUTOMATED RESPONSE # trigger_automated_response() { local ip=$1 local risk_score=$2 local username=$3 local panel=$4 # CRITICAL: 85-100 if [ $risk_score -ge $RISK_CRITICAL ] && [ "$SUSPICIOUS_LOGIN_AUTO_BLOCK" = "yes" ]; then echo -e "\n${RED}🚨 CRITICAL RISK: Triggering automated response${NC}" # 1. Block IP if command -v csf &>/dev/null; then echo " [1/3] Blocking IP via CSF..." if csf -d "$ip" "Suspicious login (risk: $risk_score)" 2>/dev/null; then echo -e " ${GREEN}✓ IP blocked via CSF${NC}" else echo -e " ${RED}✗ CSF block failed${NC}" fi else echo " [1/3] Blocking IP via iptables..." if iptables -I INPUT -s "$ip" -j DROP 2>/dev/null; then echo -e " ${GREEN}✓ IP blocked via iptables${NC}" else echo -e " ${RED}✗ iptables block failed${NC}" fi fi # 2. Trigger rkhunter scan if [ "$SUSPICIOUS_LOGIN_AUTO_SCAN" = "yes" ] && [ -f "$MALWARE_SCANNER" ]; then echo " [2/3] Triggering rootkit scan..." # Run in background with timeout timeout 300 bash "$MALWARE_SCANNER" --scanner rkhunter --quick &>/dev/null & local scan_pid=$! echo -e " ${GREEN}✓ Rootkit scan initiated (PID: $scan_pid)${NC}" else echo " [2/3] Rootkit scan (skipped - not configured)" fi # 3. CSI recommendation (cPanel only) if [ "$panel" = "cpanel" ]; then echo " [3/3] CSI scan recommended" echo "" echo " Run comprehensive security scan:" echo " wget https://raw.githubusercontent.com/CpanelInc/tech-CSI/master/csi.pl" echo " perl csi.pl --full" fi # HIGH: 70-84 elif [ $risk_score -ge $RISK_HIGH ]; then echo -e "\n${YELLOW}âš ī¸ HIGH RISK: Manual review recommended${NC}" if [ "$SUSPICIOUS_LOGIN_AUTO_BLOCK" = "yes" ] && command -v csf &>/dev/null; then echo " [1/2] Adding temporary rate limit..." if csf -tr "$ip" 300 "Rate limit: suspicious login" 2>/dev/null; then echo -e " ${GREEN}✓ Rate limited for 5 minutes${NC}" fi fi echo " [2/2] Schedule security scan for review" # MEDIUM: 50-69 elif [ $risk_score -ge $RISK_MEDIUM ]; then echo -e "\n${BLUE}â„šī¸ MEDIUM RISK: Monitoring recommended${NC}" # LOW: <50 else echo -e "\n${GREEN}✓ LOW RISK: Logged for analysis${NC}" fi } # # REPORTING # generate_report() { local panel=$1 echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}" echo -e "${CYAN} SUSPICIOUS LOGIN MONITOR - Integrated Security Report${NC}" echo -e "${CYAN} Generated: $(date '+%Y-%m-%d %H:%M:%S')${NC}" echo -e "${CYAN} Scanning: Last $HOURS hours${NC}" echo -e "${CYAN} Panel: $panel${NC}" echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}" echo "" # Count total events local total_events=$(cat "$SSH_EVENTS" "$PANEL_EVENTS" 2>/dev/null | wc -l) local successful=$(cat "$SSH_EVENTS" "$PANEL_EVENTS" 2>/dev/null | grep -c "|success$") local failed=$(cat "$SSH_EVENTS" "$PANEL_EVENTS" 2>/dev/null | grep -c "|failed$") local root_count=$(cat "$SSH_EVENTS" "$PANEL_EVENTS" 2>/dev/null | grep -c "|root|") if [ ! -s "$SUSPICIOUS_IPS" ]; then echo -e "${GREEN}✓ No suspicious login activity detected${NC}" echo "" echo "SUMMARY:" echo " Total Login Events: $total_events" echo " Successful: $successful" echo " Failed: $failed" echo " Root Logins: $root_count" echo "" return 0 fi local critical_count=$(awk -F'|' -v thresh=$RISK_CRITICAL '$2 >= thresh' "$SUSPICIOUS_IPS" | wc -l) local high_count=$(awk -F'|' -v crit=$RISK_CRITICAL -v high=$RISK_HIGH '$2 >= high && $2 < crit' "$SUSPICIOUS_IPS" | wc -l) if [ $critical_count -gt 0 ]; then echo -e "${RED}🚨 CRITICAL ALERTS ($critical_count):${NC}" echo "" awk -F'|' -v thresh=$RISK_CRITICAL '$2 >= thresh' "$SUSPICIOUS_IPS" | head -n 5 | while IFS='|' read -r ip risk reasons successful failed root users services; do echo -e " ${RED}[CRITICAL] $ip - Risk: $risk/100${NC}" echo " ┌─────────────────────────────────────────────────────────" echo " │ LOGIN EVENT" echo " ├─────────────────────────────────────────────────────────" echo " │ IP: $ip" echo " │ Successful logins: ${successful:-0}" echo " │ Failed attempts: ${failed:-0}" echo " │ Root logins: ${root_count:-0}" echo " │ Users: $users" echo " │ Services: $services" echo " │ Initial Risk Factors: $reasons" echo " │ Initial Risk: $risk/100" echo " │" # Cross-reference with bot analyzer echo " ├─────────────────────────────────────────────────────────" echo " │ ACCESS LOG CORRELATION (bot-analyzer.sh)" echo " ├─────────────────────────────────────────────────────────" local correlation=$(correlate_with_access_logs "$ip" "$risk") local corr_risk=$(echo "$correlation" | cut -d'|' -f1) local corr_attacks=$(echo "$correlation" | cut -d'|' -f2-) if [ "$corr_risk" != "0" ] && [ -n "$corr_attacks" ]; then echo " │ âš ī¸ Web attack activity detected:" for attack in $corr_attacks; do echo " │ - $attack" done risk=$((risk + corr_risk)) [ $risk -gt 100 ] && risk=100 else echo " │ $corr_attacks" fi echo " │" # Check IP reputation echo " ├─────────────────────────────────────────────────────────" echo " │ IP REPUTATION" echo " ├─────────────────────────────────────────────────────────" local rep_result=$(check_ip_reputation "$ip" "$risk") local rep_risk=$(echo "$rep_result" | cut -d'|' -f1) local rep_notes=$(echo "$rep_result" | cut -d'|' -f2-) if [ "$rep_risk" != "0" ]; then echo " │ $rep_notes" risk=$((risk + rep_risk)) [ $risk -gt 100 ] && risk=100 else echo " │ $rep_notes" fi echo " │" # Threat intelligence echo " ├─────────────────────────────────────────────────────────" echo " │ THREAT INTELLIGENCE" echo " ├─────────────────────────────────────────────────────────" local threat_result=$(correlate_with_threat_intel "$ip") local threat_risk=$(echo "$threat_result" | cut -d'|' -f1) local threat_notes=$(echo "$threat_result" | cut -d'|' -f2-) if [ "$threat_risk" != "0" ]; then echo " │ âš ī¸ $threat_notes" risk=$((risk + threat_risk)) [ $risk -gt 100 ] && risk=100 else echo " │ $threat_notes" fi echo " │" echo " ├─────────────────────────────────────────────────────────" echo -e " │ ${RED}FINAL RISK SCORE: $risk/100 - CRITICAL${NC}" echo " └─────────────────────────────────────────────────────────" # Trigger automated response trigger_automated_response "$ip" "$risk" "$(echo "$users" | cut -d',' -f1)" "$panel" echo "" done fi if [ $high_count -gt 0 ]; then echo -e "${YELLOW}âš ī¸ HIGH ALERTS ($high_count):${NC}" echo "" awk -F'|' -v crit=$RISK_CRITICAL -v high=$RISK_HIGH '$2 >= high && $2 < crit' "$SUSPICIOUS_IPS" | head -n 5 | while IFS='|' read -r ip risk reasons successful failed root users services; do echo -e " ${YELLOW}[HIGH] $ip - Risk: $risk/100${NC}" echo " Successful: ${successful:-0} | Failed: ${failed:-0} | Root: ${root:-0}" echo " Reasons: $reasons" # Quick correlation local correlation=$(correlate_with_access_logs "$ip" "$risk") local corr_attacks=$(echo "$correlation" | cut -d'|' -f2-) if [ -n "$corr_attacks" ] && [ "$corr_attacks" != "No access log activity" ]; then echo " Web attacks: $corr_attacks" fi echo "" done fi echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}" echo "SUMMARY:" echo "" echo " Total Login Events: $total_events" echo " Successful: $successful" echo " Failed: $failed" echo " Root Logins: $root_count" echo "" echo " Suspicious IPs: $(wc -l < "$SUSPICIOUS_IPS")" echo " Critical Risk: $critical_count" echo " High Risk: $high_count" echo "" # Integration status echo " Integration Status:" local bot_report=$(ls -t "$TOOLKIT_ROOT"/tmp/bot_analysis_report_*.txt /tmp/bot_analysis_report_*.txt 2>/dev/null | head -n1) [ -n "$bot_report" ] && echo " ✓ Bot Analyzer: Available" || echo " ✗ Bot Analyzer: No recent data" [ -f "$IP_REPUTATION_LIB" ] && echo " ✓ IP Reputation: Available" || echo " ✗ IP Reputation: Not available" [ -f "$THREAT_INTEL_LIB" ] && echo " ✓ Threat Intelligence: Available" || echo " ✗ Threat Intelligence: Not available" echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}" } # # MAIN # main() { echo -e "${CYAN}Starting Suspicious Login Monitor...${NC}" echo "" # Detect panel local panel=$(detect_panel) echo "Detected panel: $panel" echo "" # Parse logs parse_ssh_logins "$HOURS" case "$panel" in cpanel) parse_cpanel_logins "$HOURS" ;; plesk) parse_plesk_logins "$HOURS" ;; interworx) parse_interworx_logins "$HOURS" ;; esac # Analyze detect_anomalies # Generate report generate_report "$panel" | tee "$REPORT_FILE" echo "" echo "Report saved to: $REPORT_FILE" } # Run main function main exit 0