CRITICAL FIX: Skip scoring for whitelisted IPs but STILL write/track
Bug #3 (CRITICAL): Whitelisting checks used 'continue' which skipped: - All scoring logic - hits increment - Final write to persistent storage Result: Legitimate IPs or IPs with 20+ established connections NEVER accumulate hits, breaking adaptive threshold system permanently. Fix: Instead of 'continue' (skip everything), use skip_scoring flag to: 1. Skip threat intelligence gathering 2. Skip SYN_FLOOD attack scoring 3. Skip reputation bonuses 4. BUT STILL increment hits 5. AND STILL write to persistent storage This way: - Whitelisted IPs don't get scored/blocked - But their hits still increment for historical tracking - On next attempt, if whitelist is removed, they're blocked with higher hits - Adaptive threshold still works Example: Legitimate IP with 25 established connections Scan 1: Load hits=0, passes threshold, skip_scoring=1 (whitelisted) Don't score, but increment hits 0→1, write hits=1 Scan 2: Load hits=1, passes threshold, skip_scoring=1 (still whitelisted) Don't score, but increment hits 1→2, write hits=2 ... Scan 5: Load hits=4, threshold now 2 (lowered), skip_scoring=1 Don't score, increment hits 4→5, write hits=5 If in scan 6 whitelist is removed: Load hits=5, threshold=1, DO score, and since hits=5, will be blocked! Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2652,23 +2652,30 @@ monitor_network_attacks() {
|
|||||||
if [ -z "${ALERT_SENT[$ip]}" ]; then
|
if [ -z "${ALERT_SENT[$ip]}" ]; then
|
||||||
ALERT_SENT[$ip]=1
|
ALERT_SENT[$ip]=1
|
||||||
|
|
||||||
# Smart whitelisting: Skip IPs with MANY successful established connections
|
# Smart whitelisting: Skip SCORING for IPs with MANY successful established connections
|
||||||
|
# But still track them - don't skip the write!
|
||||||
# Only whitelist if IP has 20+ established connections (highly unlikely for attacker)
|
# Only whitelist if IP has 20+ established connections (highly unlikely for attacker)
|
||||||
# CRITICAL FIX: Use -w flag to match whole word (prevent partial IP matches)
|
# CRITICAL FIX: Use -w flag to match whole word (prevent partial IP matches)
|
||||||
# Example: "1.1.1.1" should not match "11.1.1.1" or "119.1.1.1"
|
# Example: "1.1.1.1" should not match "11.1.1.1" or "119.1.1.1"
|
||||||
local established_conns=$(ss -tn state established 2>/dev/null | grep -w "$ip" | wc -l)
|
local established_conns=$(ss -tn state established 2>/dev/null | grep -w "$ip" | wc -l)
|
||||||
[ -z "$established_conns" ] && established_conns=0
|
[ -z "$established_conns" ] && established_conns=0
|
||||||
|
local skip_scoring=0
|
||||||
if [ "$established_conns" -ge 20 ]; then
|
if [ "$established_conns" -ge 20 ]; then
|
||||||
# IP has 20+ established connections = highly likely legitimate user
|
# IP has 20+ established connections = highly likely legitimate user
|
||||||
continue # Now safe - hits already persisted
|
# Skip scoring but STILL write/track (for historical hits)
|
||||||
|
skip_scoring=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if whitelisted service
|
||||||
|
if [ "$skip_scoring" -eq 0 ] && [ "${hits:-0}" -eq 1 ]; then
|
||||||
|
# Only check whitelist on first detection, and only if not already skipped
|
||||||
|
if is_whitelisted_service "$ip" 2>/dev/null; then
|
||||||
|
skip_scoring=1 # Skip scoring but STILL write/track
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Enhanced threat intelligence on first detection
|
# Enhanced threat intelligence on first detection
|
||||||
if [ "${hits:-0}" -eq 1 ]; then
|
if [ "$skip_scoring" -eq 0 ] && [ "${hits:-0}" -eq 1 ]; then
|
||||||
# Check if whitelisted service first
|
|
||||||
if is_whitelisted_service "$ip" 2>/dev/null; then
|
|
||||||
continue # Now safe - hits already persisted
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get threat intelligence in background to avoid slowdown
|
# Get threat intelligence in background to avoid slowdown
|
||||||
(
|
(
|
||||||
@@ -2737,15 +2744,17 @@ monitor_network_attacks() {
|
|||||||
http_attack_bonus=25 # Already known attacker, very suspicious
|
http_attack_bonus=25 # Already known attacker, very suspicious
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Record attack intelligence
|
# Only do scoring/tracking if not whitelisted
|
||||||
record_attack_timestamp "$ip"
|
if [ "$skip_scoring" -eq 0 ]; then
|
||||||
record_attack_vector "$ip" "NETWORK"
|
# Record attack intelligence
|
||||||
track_subnet_attack "$ip"
|
record_attack_timestamp "$ip"
|
||||||
|
record_attack_vector "$ip" "NETWORK"
|
||||||
|
track_subnet_attack "$ip"
|
||||||
|
|
||||||
# Add SYN_FLOOD to attacks if not already present
|
# Add SYN_FLOOD to attacks if not already present
|
||||||
if [[ ! "$attacks" =~ SYN_FLOOD ]]; then
|
if [[ ! "$attacks" =~ SYN_FLOOD ]]; then
|
||||||
[ -z "$attacks" ] && attacks="SYN_FLOOD" || attacks="${attacks},SYN_FLOOD"
|
[ -z "$attacks" ] && attacks="SYN_FLOOD" || attacks="${attacks},SYN_FLOOD"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Progressive scoring based on connection count
|
# Progressive scoring based on connection count
|
||||||
# 20-50 conns: +15 pts, 50-100: +25 pts, 100+: +40 pts
|
# 20-50 conns: +15 pts, 50-100: +25 pts, 100+: +40 pts
|
||||||
@@ -2924,8 +2933,9 @@ monitor_network_attacks() {
|
|||||||
block_reasons="${block_reasons}${timing_reason}"
|
block_reasons="${block_reasons}${timing_reason}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Cap at 100
|
# Cap at 100
|
||||||
[ "$score" -gt 100 ] && score=100
|
[ "$score" -gt 100 ] && score=100
|
||||||
|
fi # End of skip_scoring check
|
||||||
|
|
||||||
# INCREMENT HITS AFTER ALL SCORING
|
# INCREMENT HITS AFTER ALL SCORING
|
||||||
# Moved from before whitelisting to ensure we have complete data
|
# Moved from before whitelisting to ensure we have complete data
|
||||||
|
|||||||
Reference in New Issue
Block a user