BUG FIX #8: Multi-vector attack detection using stale individual IP files
ISSUE:
When an IP has a history of HTTP attacks (SQLI, XSS, RCE, etc.) and is later
detected performing a SYN flood attack, the code failed to recognize it as a
multi-vector/sophisticated attacker.
ROOT CAUSE:
Lines 2821 and 2852 were reading attack history from individual ip_* files:
if [ -f "$TEMP_DIR/ip_${ip//\./_}" ]; then
local existing_attacks=$(cut -d'|' -f4 "$TEMP_DIR/ip_${ip//\./_}" ...)
fi
But the individual ip_* file:
1. May not exist on FIRST SYN detection (created only after SYN detection written)
2. May be out of sync with centralized ip_data file
3. Is unnecessary - attack history was already loaded and parsed!
TIMELINE OF FAILURE:
1. IP performs HTTP attacks (SQLI) → stored in centralized ip_data
2. Script loads from ip_data: attacks="SQLI" (line 2597) ✓ Correct!
3. Code then IGNORES $attacks variable
4. Code checks if individual ip_* file exists → doesn't exist yet
5. Condition fails → has_other_traffic=0, multi_vector=0
6. Multi-vector bonus (+30) NOT applied
7. Spoofed source bonus (+20) incorrectly applied
IMPACT:
- Attacks by known sophisticated attackers (prior HTTP attacks) missed +30 bonus
- False positives for spoofed source detection on first SYN occurrence
- Historical attack context completely ignored on SYN detection
FIX:
Use the already-loaded and correct $attacks variable instead of attempting
file I/O on potentially non-existent or stale individual IP files.
LINES CHANGED:
- 2821: Read from $attacks instead of ip_file
- 2852: Read from $attacks instead of ip_file
VERIFICATION:
- Syntax: ✓ Pass
- Logic: ✓ Uses centralized data source (consistent with line 2597)
- Performance: ✓ Eliminates unnecessary file I/O
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2816,14 +2816,15 @@ monitor_network_attacks() {
|
|||||||
|
|
||||||
# 4. Spoofed source detection (high SYN, low other traffic)
|
# 4. Spoofed source detection (high SYN, low other traffic)
|
||||||
# Check if IP has ANY other traffic (HTTP requests, DNS, etc)
|
# Check if IP has ANY other traffic (HTTP requests, DNS, etc)
|
||||||
|
# CRITICAL FIX: Use already-loaded $attacks variable from ip_data (line 2597)
|
||||||
|
# Bug: was trying to read from individual ip_* file which may not exist
|
||||||
|
# If this is first SYN detection of an IP with prior HTTP attacks, file won't exist
|
||||||
|
# Result: has_other_traffic stays 0, missing indicator of multi-attack IP
|
||||||
local has_other_traffic=0
|
local has_other_traffic=0
|
||||||
if [ -f "$TEMP_DIR/ip_${ip//\./_}" ]; then
|
# If has HTTP attacks in history, not spoofed
|
||||||
local ip_attacks=$(cut -d'|' -f4 "$TEMP_DIR/ip_${ip//\./_}" 2>/dev/null || echo "")
|
if [[ "$attacks" =~ (SQLI|XSS|BRUTE|SCAN) ]]; then
|
||||||
# If has HTTP attacks, not spoofed
|
|
||||||
if [[ "$ip_attacks" =~ (SQLI|XSS|BRUTE|SCAN) ]]; then
|
|
||||||
has_other_traffic=1
|
has_other_traffic=1
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# High SYN but no other traffic = likely spoofed source
|
# High SYN but no other traffic = likely spoofed source
|
||||||
if [ "$has_other_traffic" -eq 0 ] && [ "$count" -ge 10 ] && [ "${hits:-0}" -ge 2 ]; then
|
if [ "$has_other_traffic" -eq 0 ] && [ "$count" -ge 10 ] && [ "${hits:-0}" -ge 2 ]; then
|
||||||
@@ -2843,18 +2844,15 @@ monitor_network_attacks() {
|
|||||||
|
|
||||||
# Multi-vector attack detection: Check if IP also has HTTP attacks
|
# Multi-vector attack detection: Check if IP also has HTTP attacks
|
||||||
# This indicates sophisticated attacker (SYN flood + application layer)
|
# This indicates sophisticated attacker (SYN flood + application layer)
|
||||||
|
# CRITICAL FIX: Use already-loaded $attacks variable from ip_data (line 2597)
|
||||||
|
# Bug: was trying to read from individual ip_* file which may not exist
|
||||||
|
# If this is first SYN detection of an IP with prior HTTP attacks, file won't exist
|
||||||
|
# Result: multi_vector stays 0, missing the sophisticated attacker indicator
|
||||||
local multi_vector=0
|
local multi_vector=0
|
||||||
if [ -f "$TEMP_DIR/ip_${ip//\./_}" ]; then
|
if [[ "$attacks" =~ (SQLI|XSS|RCE|LFI|RFI|WEBSHELL) ]]; then
|
||||||
# CRITICAL FIX: Parse pipe-delimited format correctly
|
|
||||||
# File format: score|hits|bot_type|attacks|ban_count|rep_score
|
|
||||||
# Bug: was trying to parse 'attacks=' key which doesn't exist
|
|
||||||
# Fixed: Use cut to extract 4th field (attacks)
|
|
||||||
local existing_attacks=$(cut -d'|' -f4 "$TEMP_DIR/ip_${ip//\./_}" 2>/dev/null || echo "")
|
|
||||||
if [[ "$existing_attacks" =~ (SQLI|XSS|RCE|LFI|RFI|WEBSHELL) ]]; then
|
|
||||||
multi_vector=1
|
multi_vector=1
|
||||||
conn_bonus=$((conn_bonus + 30)) # Multi-vector = very dangerous
|
conn_bonus=$((conn_bonus + 30)) # Multi-vector = very dangerous
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# Connection persistence bonus (repeated detections of same IP)
|
# Connection persistence bonus (repeated detections of same IP)
|
||||||
# This indicates sustained attack vs transient spike
|
# This indicates sustained attack vs transient spike
|
||||||
|
|||||||
Reference in New Issue
Block a user