@@ -49,8 +49,8 @@ PANEL_EVENTS="$TMP_DIR/panel_events_$$.txt"
SUDO_EVENTS = " $TMP_DIR /sudo_events_ $$ .txt "
SUDO_EVENTS = " $TMP_DIR /sudo_events_ $$ .txt "
SUSPICIOUS_IPS = " $TMP_DIR /suspicious_ips_ $$ .txt "
SUSPICIOUS_IPS = " $TMP_DIR /suspicious_ips_ $$ .txt "
# Baseline storage (persistent across runs)
# Baseline storage (persistent across runs, within toolkit directory )
BASELINE_DIR = "/var/lib /suspicious-login-monitor"
BASELINE_DIR = " $TOOLKIT_ROOT /data /suspicious-login-monitor"
BASELINE_FILE = " $BASELINE_DIR /baseline.dat "
BASELINE_FILE = " $BASELINE_DIR /baseline.dat "
mkdir -p " $BASELINE_DIR " 2>/dev/null
mkdir -p " $BASELINE_DIR " 2>/dev/null
@@ -1494,6 +1494,188 @@ check_who_made_change() {
return 1
return 1
}
}
#
# PHASE 2A FALSE POSITIVE REDUCTION - Additional correlation checks
#
check_tty_session( ) {
local user = ${ 1 :- root }
local timestamp = ${ 2 :- $( date +%s) }
# Check if user has an active TTY/PTY session
# Real admin sessions have TTY, automated scripts don't
# Check currently logged in users
local tty_info = $( w -h 2>/dev/null | awk -v user = " $user " '$1 == user {print $2}' )
if [ -n " $tty_info " ] ; then
echo " tty-session: $tty_info "
return 0
fi
# Check recent TTY allocations in /var/log/secure (within last hour)
if [ -f /var/log/secure ] ; then
local recent_tty = $( awk -v user = " $user " '
/pam_unix.*session opened/ && $0 ~ user {
if ($0 ~ /pts\/[0-9]+/) {
match($0, /pts\/[0-9]+/)
tty = substr($0, RSTART, RLENGTH)
print tty
exit
}
}
' /var/log/secure 2>/dev/null | tail -1)
if [ -n " $recent_tty " ] ; then
echo " recent-tty: $recent_tty "
return 0
fi
fi
echo "no-tty"
return 1
}
check_recent_login( ) {
local user = $1
local event_time = ${ 2 :- $( date +%s) }
# Check if user logged in within last 2 hours
# If yes, their changes are likely legitimate
if [ -z " $user " ] ; then
echo "unknown:0"
return 1
fi
# Use 'last' command to get recent logins
local last_login = $( last -F " $user " 2>/dev/null | head -1)
if [ -z " $last_login " ] || echo " $last_login " | grep -q " ^ $" ; then
echo "no-login:0"
return 1
fi
# Parse login time from last command output
# Format: user pts/0 ip Mon Feb 3 14:30:00 2026 - 16:45:00 (2:15)
local login_time = $( echo " $last_login " | awk '{
# Extract timestamp: Mon Feb 3 14:30:00 2026
month = $4
day = $5
time = $6
year = $7
# Convert to date command format
timestamp = month " " day " " year " " time
cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
cmd | getline epoch
close(cmd)
if (epoch > 0) {
print epoch
}
}' )
if [ -z " $login_time " ] || [ " $login_time " = "0" ] ; then
echo "no-login:0"
return 1
fi
# Calculate hours since login
local seconds_since = $(( event_time - login_time ))
local hours_since = $(( seconds_since / 3600 ))
# If negative or within last 2 hours, return as recent
if [ " $hours_since " -lt 0 ] || [ " $hours_since " -le 2 ] ; then
local hours_display = $( echo " scale=1; $seconds_since / 3600 " | bc 2>/dev/null || echo " $hours_since " )
echo " recent-login: ${ hours_display } h "
return 0
fi
echo " old-login: ${ hours_since } h "
return 1
}
check_package_ownership( ) {
local file = $1
# Check if file belongs to an installed package
# Helps catch package operations not detected in logs
if [ ! -f " $file " ] && [ ! -d " $file " ] ; then
echo "not-found"
return 1
fi
# Try RPM-based systems (RHEL, CentOS, AlmaLinux, Rocky, Fedora)
if command -v rpm >/dev/null 2>& 1; then
local pkg = $( rpm -qf " $file " 2>/dev/null)
if [ $? -eq 0 ] && [ " $pkg " != " file $file is not owned by any package " ] ; then
# Extract just package name without version
local pkg_name = $( echo " $pkg " | sed 's/-[0-9].*//' )
echo " pkg-owned: $pkg_name "
return 0
fi
fi
# Try DEB-based systems (Debian, Ubuntu)
if command -v dpkg >/dev/null 2>& 1; then
local pkg = $( dpkg -S " $file " 2>/dev/null | cut -d: -f1)
if [ -n " $pkg " ] ; then
echo " pkg-owned: $pkg "
return 0
fi
fi
echo "not-owned"
return 1
}
check_maintenance_mode( ) {
# Check for various maintenance mode indicators
local indicators = ""
# Check for /etc/nologin (standard maintenance file)
if [ -f /etc/nologin ] ; then
indicators = " ${ indicators } nologin "
fi
# Check for custom maintenance flags
if [ -f /var/run/maintenance.flag ] ; then
indicators = " ${ indicators } maintenance.flag "
fi
if [ -f /root/.maintenance ] ; then
indicators = " ${ indicators } root-maintenance "
fi
# Check cPanel maintenance mode
if [ -f /usr/local/cpanel/bin/whmapi1 ] ; then
local cpanel_maint = $( whmapi1 get_tweaksetting key = maintenance_mode 2>/dev/null | grep -A1 "value:" | tail -1 | awk '{print $2}' )
if [ " $cpanel_maint " = "1" ] ; then
indicators = " ${ indicators } cpanel-maint "
fi
fi
# Check /etc/motd or /etc/issue for maintenance notices
if grep -qi "maintenance" /etc/motd 2>/dev/null; then
indicators = " ${ indicators } motd-notice "
fi
if grep -qi "maintenance" /etc/issue 2>/dev/null; then
indicators = " ${ indicators } issue-notice "
fi
if [ -n " $indicators " ] ; then
echo " maintenance-mode: $( echo $indicators | sed 's/ $//' ) "
return 0
fi
echo "no-maintenance"
return 1
}
#
#
# COMPROMISE DETECTION - Check for actual root compromise indicators
# COMPROMISE DETECTION - Check for actual root compromise indicators
#
#
@@ -1544,6 +1726,22 @@ check_recent_password_changes() {
details = " ${ details } [ $admin_session ] "
details = " ${ details } [ $admin_session ] "
fi
fi
# PHASE 2A: Check for TTY session (real terminal vs automated)
local tty_session = $( check_tty_session "root" )
local has_tty = 0
if [ [ " $tty_session " = ~ ^tty-session: ] ] || [ [ " $tty_session " = ~ ^recent-tty: ] ] ; then
has_tty = 1
details = " ${ details } [ $tty_session ] "
fi
# PHASE 2A: Check for recent login (within 2 hours)
local recent_login = $( check_recent_login "root" )
local login_recent = 0
if [ [ " $recent_login " = ~ ^recent-login: ] ] ; then
login_recent = 1
details = " ${ details } [ $recent_login ] "
fi
# Check if in safe time window (reduce risk)
# Check if in safe time window (reduce risk)
local safe_window = 0
local safe_window = 0
if is_safe_time_window; then
if is_safe_time_window; then
@@ -1551,6 +1749,14 @@ check_recent_password_changes() {
details = " ${ details } [safe-window] "
details = " ${ details } [safe-window] "
fi
fi
# PHASE 2A: Check for maintenance mode
local maint_mode = $( check_maintenance_mode)
local in_maintenance = 0
if [ [ " $maint_mode " = ~ ^maintenance-mode: ] ] ; then
in_maintenance = 1
details = " ${ details } [ $maint_mode ] "
fi
# FALSE POSITIVE REDUCTION: Check if this is mass change (more suspicious)
# FALSE POSITIVE REDUCTION: Check if this is mass change (more suspicious)
if [ " $filtered_count " -lt " $FP_PASSWORD_CHANGE_THRESHOLD " ] ; then
if [ " $filtered_count " -lt " $FP_PASSWORD_CHANGE_THRESHOLD " ] ; then
# Small number of password changes - likely legitimate
# Small number of password changes - likely legitimate
@@ -1567,6 +1773,12 @@ check_recent_password_changes() {
[ " $FP_IGNORE_BUSINESS_HOURS " = "yes" ] && is_business_hours && base_risk = $(( base_risk - 10 ))
[ " $FP_IGNORE_BUSINESS_HOURS " = "yes" ] && is_business_hours && base_risk = $(( base_risk - 10 ))
# Reduce if safe window
# Reduce if safe window
[ " $safe_window " -eq 1 ] && base_risk = $(( base_risk - 10 ))
[ " $safe_window " -eq 1 ] && base_risk = $(( base_risk - 10 ))
# PHASE 2A: Reduce if TTY session present (real admin at terminal)
[ " $has_tty " -eq 1 ] && base_risk = $(( base_risk - 7 ))
# PHASE 2A: Reduce if recent login (logged in within 2h)
[ " $login_recent " -eq 1 ] && base_risk = $(( base_risk - 8 ))
# PHASE 2A: Reduce if maintenance mode
[ " $in_maintenance " -eq 1 ] && base_risk = $(( base_risk - 14 ))
risk = $(( risk + base_risk))
risk = $(( risk + base_risk))
elif [ " $filtered_count " -eq 1 ] ; then
elif [ " $filtered_count " -eq 1 ] ; then
@@ -1574,6 +1786,9 @@ check_recent_password_changes() {
local base_risk = 5
local base_risk = 5
[ " $admin_active " -eq 1 ] && base_risk = 2
[ " $admin_active " -eq 1 ] && base_risk = 2
[ " $safe_window " -eq 1 ] && base_risk = 2
[ " $safe_window " -eq 1 ] && base_risk = 2
[ " $has_tty " -eq 1 ] && [ " $base_risk " -gt 1 ] && base_risk = $(( base_risk - 1 ))
[ " $login_recent " -eq 1 ] && [ " $base_risk " -gt 1 ] && base_risk = $(( base_risk - 1 ))
[ " $in_maintenance " -eq 1 ] && [ " $base_risk " -gt 1 ] && base_risk = $(( base_risk - 1 ))
risk = $(( risk + base_risk))
risk = $(( risk + base_risk))
details = " ${ details } Single-user: $filtered_users "
details = " ${ details } Single-user: $filtered_users "
else
else
@@ -1581,6 +1796,9 @@ check_recent_password_changes() {
local base_risk = 10
local base_risk = 10
[ " $admin_active " -eq 1 ] && base_risk = 5
[ " $admin_active " -eq 1 ] && base_risk = 5
[ " $safe_window " -eq 1 ] && base_risk = 5
[ " $safe_window " -eq 1 ] && base_risk = 5
[ " $has_tty " -eq 1 ] && base_risk = $(( base_risk - 2 ))
[ " $login_recent " -eq 1 ] && base_risk = $(( base_risk - 2 ))
[ " $in_maintenance " -eq 1 ] && base_risk = $(( base_risk - 3 ))
risk = $(( risk + base_risk))
risk = $(( risk + base_risk))
details = " ${ details } $filtered_count -users: $filtered_users "
details = " ${ details } $filtered_count -users: $filtered_users "
fi
fi
@@ -1591,6 +1809,10 @@ check_recent_password_changes() {
# Even with admin active, mass changes are suspicious
# Even with admin active, mass changes are suspicious
local base_risk = 45
local base_risk = 45
[ " $admin_active " -eq 1 ] && base_risk = $(( base_risk - 10 ))
[ " $admin_active " -eq 1 ] && base_risk = $(( base_risk - 10 ))
# PHASE 2A: Reduce slightly if TTY/login/maintenance (still suspicious, but less)
[ " $has_tty " -eq 1 ] && base_risk = $(( base_risk - 5 ))
[ " $login_recent " -eq 1 ] && base_risk = $(( base_risk - 5 ))
[ " $in_maintenance " -eq 1 ] && base_risk = $(( base_risk - 8 ))
risk = $(( risk + base_risk))
risk = $(( risk + base_risk))
fi
fi
fi
fi
@@ -1674,6 +1896,19 @@ check_recent_user_changes() {
admin_active = 1
admin_active = 1
fi
fi
# PHASE 2A: Check for TTY session, recent login, maintenance mode
local tty_session = $( check_tty_session "root" )
local has_tty = 0
[ [ " $tty_session " = ~ ^tty-session: ] ] || [ [ " $tty_session " = ~ ^recent-tty: ] ] && has_tty = 1
local recent_login = $( check_recent_login "root" )
local login_recent = 0
[ [ " $recent_login " = ~ ^recent-login: ] ] && login_recent = 1
local maint_mode = $( check_maintenance_mode)
local in_maintenance = 0
[ [ " $maint_mode " = ~ ^maintenance-mode: ] ] && in_maintenance = 1
if [ " $cpanel_activity " = "cpanel_account_creation" ] && [ " $filtered_new_count " -le 3 ] ; then
if [ " $cpanel_activity " = "cpanel_account_creation" ] && [ " $filtered_new_count " -le 3 ] ; then
# Likely legitimate cPanel hosting account
# Likely legitimate cPanel hosting account
findings = " ${ findings } New-Users: $filtered_new_users [cpanel] "
findings = " ${ findings } New-Users: $filtered_new_users [cpanel] "
@@ -1686,11 +1921,19 @@ check_recent_user_changes() {
local base_risk = 15
local base_risk = 15
[ " $admin_active " -eq 1 ] && base_risk = 8
[ " $admin_active " -eq 1 ] && base_risk = 8
is_business_hours && base_risk = $(( base_risk - 3 ))
is_business_hours && base_risk = $(( base_risk - 3 ))
# PHASE 2A: Additional reductions
[ " $has_tty " -eq 1 ] && base_risk = $(( base_risk - 3 ))
[ " $login_recent " -eq 1 ] && base_risk = $(( base_risk - 3 ))
[ " $in_maintenance " -eq 1 ] && base_risk = $(( base_risk - 4 ))
risk = $(( risk + base_risk))
risk = $(( risk + base_risk))
else
else
# Multiple users
# Multiple users
local base_risk = 25
local base_risk = 25
[ " $admin_active " -eq 1 ] && base_risk = 15
[ " $admin_active " -eq 1 ] && base_risk = 15
# PHASE 2A: Additional reductions
[ " $has_tty " -eq 1 ] && base_risk = $(( base_risk - 4 ))
[ " $login_recent " -eq 1 ] && base_risk = $(( base_risk - 4 ))
[ " $in_maintenance " -eq 1 ] && base_risk = $(( base_risk - 5 ))
risk = $(( risk + base_risk))
risk = $(( risk + base_risk))
fi
fi
fi
fi
@@ -1849,16 +2092,38 @@ check_system_file_tampering() {
safe_window = 1
safe_window = 1
fi
fi
# PHASE 2A: Check TTY, recent login, maintenance mode
local tty_session = $( check_tty_session "root" )
local has_tty = 0
[ [ " $tty_session " = ~ ^tty-session: ] ] || [ [ " $tty_session " = ~ ^recent-tty: ] ] && has_tty = 1
local recent_login = $( check_recent_login "root" )
local login_recent = 0
[ [ " $recent_login " = ~ ^recent-login: ] ] && login_recent = 1
local maint_mode = $( check_maintenance_mode)
local in_maintenance = 0
[ [ " $maint_mode " = ~ ^maintenance-mode: ] ] && in_maintenance = 1
# Check /etc/passwd modification time (recent changes suspicious)
# Check /etc/passwd modification time (recent changes suspicious)
local passwd_age = $(( $( date +%s) - $( stat -c %Y /etc/passwd 2>/dev/null) ))
local passwd_age = $(( $( date +%s) - $( stat -c %Y /etc/passwd 2>/dev/null) ))
if [ " $passwd_age " -lt 86400 ] ; then # Modified in last 24 hours
if [ " $passwd_age " -lt 86400 ] ; then # Modified in last 24 hours
local passwd_hours = $(( passwd_age / 3600 ))
local passwd_hours = $(( passwd_age / 3600 ))
# PHASE 2A: Check package ownership
local pkg_owned = $( check_package_ownership "/etc/passwd" )
local is_pkg_owned = 0
[ [ " $pkg_owned " = ~ ^pkg-owned: ] ] && is_pkg_owned = 1
# Build context string
# Build context string
local context = ""
local context = ""
[ " $pkg_activity " != "none" ] && context = " ${ context } $pkg_activity , "
[ " $pkg_activity " != "none" ] && context = " ${ context } $pkg_activity , "
[ " $admin_active " -eq 1 ] && context = " ${ context } admin-active, "
[ " $admin_active " -eq 1 ] && context = " ${ context } admin-active, "
[ " $safe_window " -eq 1 ] && context = " ${ context } safe-window, "
[ " $safe_window " -eq 1 ] && context = " ${ context } safe-window, "
[ " $has_tty " -eq 1 ] && context = " ${ context } tty-session, "
[ " $login_recent " -eq 1 ] && context = " ${ context } recent-login, "
[ " $in_maintenance " -eq 1 ] && context = " ${ context } maintenance, "
[ " $is_pkg_owned " -eq 1 ] && context = " ${ context } $pkg_owned , "
context = ${ context %, } # Remove trailing comma
context = ${ context %, } # Remove trailing comma
# Calculate risk
# Calculate risk
@@ -1869,6 +2134,13 @@ check_system_file_tampering() {
base_risk = 12 # Admin was logged in
base_risk = 12 # Admin was logged in
fi
fi
[ " $safe_window " -eq 1 ] && base_risk = $(( base_risk / 2 ))
[ " $safe_window " -eq 1 ] && base_risk = $(( base_risk / 2 ))
# PHASE 2A: Additional reductions
[ " $has_tty " -eq 1 ] && base_risk = $(( base_risk - 3 ))
[ " $login_recent " -eq 1 ] && base_risk = $(( base_risk - 3 ))
[ " $in_maintenance " -eq 1 ] && base_risk = $(( base_risk - 5 ))
[ " $is_pkg_owned " -eq 1 ] && base_risk = $(( base_risk - 4 ))
# Ensure minimum risk
[ " $base_risk " -lt 0 ] && base_risk = 0
if [ -n " $context " ] ; then
if [ -n " $context " ] ; then
findings = " ${ findings } /etc/passwd-Modified- ${ passwd_hours } h-ago[ $context ] "
findings = " ${ findings } /etc/passwd-Modified- ${ passwd_hours } h-ago[ $context ] "
@@ -1883,6 +2155,22 @@ check_system_file_tampering() {
if [ " $shadow_age " -lt 86400 ] ; then
if [ " $shadow_age " -lt 86400 ] ; then
local shadow_hours = $(( shadow_age / 3600 ))
local shadow_hours = $(( shadow_age / 3600 ))
# PHASE 2A: Check package ownership
local pkg_owned_shadow = $( check_package_ownership "/etc/shadow" )
local is_pkg_owned_shadow = 0
[ [ " $pkg_owned_shadow " = ~ ^pkg-owned: ] ] && is_pkg_owned_shadow = 1
# Build context string for shadow
local context_shadow = ""
[ " $pkg_activity " != "none" ] && context_shadow = " ${ context_shadow } $pkg_activity , "
[ " $admin_active " -eq 1 ] && context_shadow = " ${ context_shadow } admin-active, "
[ " $safe_window " -eq 1 ] && context_shadow = " ${ context_shadow } safe-window, "
[ " $has_tty " -eq 1 ] && context_shadow = " ${ context_shadow } tty-session, "
[ " $login_recent " -eq 1 ] && context_shadow = " ${ context_shadow } recent-login, "
[ " $in_maintenance " -eq 1 ] && context_shadow = " ${ context_shadow } maintenance, "
[ " $is_pkg_owned_shadow " -eq 1 ] && context_shadow = " ${ context_shadow } $pkg_owned_shadow , "
context_shadow = ${ context_shadow %, }
local base_risk = 25
local base_risk = 25
if [ " $pkg_activity " != "none" ] ; then
if [ " $pkg_activity " != "none" ] ; then
base_risk = 5
base_risk = 5
@@ -1890,9 +2178,15 @@ check_system_file_tampering() {
base_risk = 12
base_risk = 12
fi
fi
[ " $safe_window " -eq 1 ] && base_risk = $(( base_risk / 2 ))
[ " $safe_window " -eq 1 ] && base_risk = $(( base_risk / 2 ))
# PHASE 2A: Additional reductions
[ " $has_tty " -eq 1 ] && base_risk = $(( base_risk - 3 ))
[ " $login_recent " -eq 1 ] && base_risk = $(( base_risk - 3 ))
[ " $in_maintenance " -eq 1 ] && base_risk = $(( base_risk - 5 ))
[ " $is_pkg_owned_shadow " -eq 1 ] && base_risk = $(( base_risk - 4 ))
[ " $base_risk " -lt 0 ] && base_risk = 0
if [ -n " $context " ] ; then
if [ -n " $context_shadow " ] ; then
findings = " ${ findings } /etc/shadow-Modified- ${ shadow_hours } h-ago[ $context ] "
findings = " ${ findings } /etc/shadow-Modified- ${ shadow_hours } h-ago[ $context_shadow ] "
else
else
findings = " ${ findings } /etc/shadow-Modified- ${ shadow_hours } h-ago "
findings = " ${ findings } /etc/shadow-Modified- ${ shadow_hours } h-ago "
fi
fi
@@ -1904,6 +2198,22 @@ check_system_file_tampering() {
if [ " $group_age " -lt 86400 ] ; then
if [ " $group_age " -lt 86400 ] ; then
local group_hours = $(( group_age / 3600 ))
local group_hours = $(( group_age / 3600 ))
# PHASE 2A: Check package ownership
local pkg_owned_group = $( check_package_ownership "/etc/group" )
local is_pkg_owned_group = 0
[ [ " $pkg_owned_group " = ~ ^pkg-owned: ] ] && is_pkg_owned_group = 1
# Build context string for group
local context_group = ""
[ " $pkg_activity " != "none" ] && context_group = " ${ context_group } $pkg_activity , "
[ " $admin_active " -eq 1 ] && context_group = " ${ context_group } admin-active, "
[ " $safe_window " -eq 1 ] && context_group = " ${ context_group } safe-window, "
[ " $has_tty " -eq 1 ] && context_group = " ${ context_group } tty-session, "
[ " $login_recent " -eq 1 ] && context_group = " ${ context_group } recent-login, "
[ " $in_maintenance " -eq 1 ] && context_group = " ${ context_group } maintenance, "
[ " $is_pkg_owned_group " -eq 1 ] && context_group = " ${ context_group } $pkg_owned_group , "
context_group = ${ context_group %, }
local base_risk = 20
local base_risk = 20
if [ " $pkg_activity " != "none" ] ; then
if [ " $pkg_activity " != "none" ] ; then
base_risk = 3
base_risk = 3
@@ -1911,9 +2221,15 @@ check_system_file_tampering() {
base_risk = 10
base_risk = 10
fi
fi
[ " $safe_window " -eq 1 ] && base_risk = $(( base_risk / 2 ))
[ " $safe_window " -eq 1 ] && base_risk = $(( base_risk / 2 ))
# PHASE 2A: Additional reductions
[ " $has_tty " -eq 1 ] && base_risk = $(( base_risk - 2 ))
[ " $login_recent " -eq 1 ] && base_risk = $(( base_risk - 2 ))
[ " $in_maintenance " -eq 1 ] && base_risk = $(( base_risk - 4 ))
[ " $is_pkg_owned_group " -eq 1 ] && base_risk = $(( base_risk - 3 ))
[ " $base_risk " -lt 0 ] && base_risk = 0
if [ -n " $context " ] ; then
if [ -n " $context_group " ] ; then
findings = " ${ findings } /etc/group-Modified- ${ group_hours } h-ago[ $context ] "
findings = " ${ findings } /etc/group-Modified- ${ group_hours } h-ago[ $context_group ] "
else
else
findings = " ${ findings } /etc/group-Modified- ${ group_hours } h-ago "
findings = " ${ findings } /etc/group-Modified- ${ group_hours } h-ago "
fi
fi
@@ -1952,7 +2268,7 @@ check_system_file_tampering() {
# System accounts
# System accounts
if ($1 == "sync" || $1 == "shutdown" || $1 == "halt" || $1 == "operator") next
if ($1 == "sync" || $1 == "shutdown" || $1 == "halt" || $1 == "operator") next
# cPanel shells
# cPanel shells
if (shell ~ /\/noshell$/) next
if (shell ~ /\/noshell$/ || shell ~ /\/jailshell$/ ) next
# If we get here, shell is suspicious
# If we get here, shell is suspicious
print $1":"shell
print $1":"shell
}' /etc/passwd 2>/dev/null)
}' /etc/passwd 2>/dev/null)
@@ -2344,12 +2660,18 @@ perform_compromise_detection() {
trigger_automated_response( ) {
trigger_automated_response( ) {
local ip = $1
local ip = $1
local risk_score = $2
local risk_score = ${ 2 :- 0 }
local username = $3
local username = $3
local panel = $4
local panel = $4
# Skip if risk_score is not a valid number
if ! [ [ " $risk_score " = ~ ^[ 0-9] +$ ] ] ; then
echo " Warning: Invalid risk_score ' $risk_score ', skipping automated response " >& 2
return 1
fi
# CRITICAL: 85-100
# CRITICAL: 85-100
if [ $risk_score -ge $RISK_CRITICAL ] && [ " $SUSPICIOUS_LOGIN_AUTO_BLOCK " = "yes" ] ; then
if [ " $risk_score " -ge " $RISK_CRITICAL " ] && [ " $SUSPICIOUS_LOGIN_AUTO_BLOCK " = "yes" ] ; then
echo -e " \n ${ RED } 🚨 CRITICAL RISK: Triggering automated response ${ NC } "
echo -e " \n ${ RED } 🚨 CRITICAL RISK: Triggering automated response ${ NC } "
# 1. Block IP
# 1. Block IP
@@ -2390,7 +2712,7 @@ trigger_automated_response() {
fi
fi
# HIGH: 70-84
# HIGH: 70-84
elif [ $risk_score -ge $RISK_HIGH ] ; then
elif [ " $risk_score " -ge " $RISK_HIGH " ] ; then
echo -e " \n ${ YELLOW } ⚠️ HIGH RISK: Manual review recommended ${ NC } "
echo -e " \n ${ YELLOW } ⚠️ HIGH RISK: Manual review recommended ${ NC } "
if [ " $SUSPICIOUS_LOGIN_AUTO_BLOCK " = "yes" ] && command -v csf & >/dev/null; then
if [ " $SUSPICIOUS_LOGIN_AUTO_BLOCK " = "yes" ] && command -v csf & >/dev/null; then
@@ -2403,7 +2725,7 @@ trigger_automated_response() {
echo " [2/2] Schedule security scan for review"
echo " [2/2] Schedule security scan for review"
# MEDIUM: 50-69
# MEDIUM: 50-69
elif [ $risk_score -ge $RISK_MEDIUM ] ; then
elif [ " $risk_score " -ge " $RISK_MEDIUM " ] ; then
echo -e " \n ${ BLUE } ℹ ️ MEDIUM RISK: Monitoring recommended${ NC } "
echo -e " \n ${ BLUE } ℹ ️ MEDIUM RISK: Monitoring recommended${ NC } "
# LOW: <50
# LOW: <50