Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 43a94884e4 | |||
| da02dcfd61 | |||
| baf058d1dc | |||
| 1c3f12744b | |||
| 55dc21f6e5 | |||
| b0873bbf13 |
@@ -1036,7 +1036,7 @@ detect_threats() {
|
|||||||
|
|
||||||
# Breakdown by attack type
|
# Breakdown by attack type
|
||||||
for attack_type in sqli xss path_traversal rce_upload info_disclosure login_bruteforce; do
|
for attack_type in sqli xss path_traversal rce_upload info_disclosure login_bruteforce; do
|
||||||
grep -F "|$attack_type" "$TEMP_DIR/attack_vectors_raw.txt" 2>/dev/null | grep -F "|$attack_type$" | \
|
grep -F "|$attack_type|" "$TEMP_DIR/attack_vectors_raw.txt" 2>/dev/null | \
|
||||||
awk -F'|' '{print $1"|"$2"|"$3"|"$4}' | \
|
awk -F'|' '{print $1"|"$2"|"$3"|"$4}' | \
|
||||||
sort | uniq -c | sort -rn > "$TEMP_DIR/${attack_type}_attempts.txt" || true
|
sort | uniq -c | sort -rn > "$TEMP_DIR/${attack_type}_attempts.txt" || true
|
||||||
done
|
done
|
||||||
@@ -1219,6 +1219,7 @@ calculate_bot_fingerprint() {
|
|||||||
awk -F'|' -v tmpdir="$TEMP_DIR" '
|
awk -F'|' -v tmpdir="$TEMP_DIR" '
|
||||||
BEGIN {
|
BEGIN {
|
||||||
# Initialize tracking arrays
|
# Initialize tracking arrays
|
||||||
|
fingerprint_file = tmpdir "/bot_fingerprints.txt"
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ip = $1
|
ip = $1
|
||||||
@@ -1306,10 +1307,10 @@ calculate_bot_fingerprint() {
|
|||||||
|
|
||||||
# Output fingerprint for high-confidence bots (score >= 60)
|
# Output fingerprint for high-confidence bots (score >= 60)
|
||||||
if (score >= 60) {
|
if (score >= 60) {
|
||||||
printf "%s|%d|%d\n", ip, score, signal_count > tmpdir "/bot_fingerprints.txt"
|
printf "%s|%d|%d\n", ip, score, signal_count > fingerprint_file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(tmpdir "/bot_fingerprints.txt")
|
close(fingerprint_file)
|
||||||
}
|
}
|
||||||
' < "$TEMP_DIR/parsed_logs.txt" 2>/dev/null || true
|
' < "$TEMP_DIR/parsed_logs.txt" 2>/dev/null || true
|
||||||
|
|
||||||
@@ -1356,7 +1357,7 @@ analyze_domain_targeting_percentage() {
|
|||||||
# Also create per-domain attack type breakdown
|
# Also create per-domain attack type breakdown
|
||||||
# Format: domain|attack_type|ip|count
|
# Format: domain|attack_type|ip|count
|
||||||
if [ -f "$TEMP_DIR/attack_vectors_raw.txt" ]; then
|
if [ -f "$TEMP_DIR/attack_vectors_raw.txt" ]; then
|
||||||
awk -F'|' '
|
awk -F'|' -v tmpdir="$TEMP_DIR" '
|
||||||
{
|
{
|
||||||
ip = $1
|
ip = $1
|
||||||
domain = $2
|
domain = $2
|
||||||
@@ -1368,7 +1369,6 @@ analyze_domain_targeting_percentage() {
|
|||||||
}
|
}
|
||||||
END {
|
END {
|
||||||
for (domain in attack_data) {
|
for (domain in attack_data) {
|
||||||
domain_file = tmpdir "/domain_attacks_" domain ".txt"
|
|
||||||
for (attack_type in attack_data[domain]) {
|
for (attack_type in attack_data[domain]) {
|
||||||
total = attack_totals[domain][attack_type]
|
total = attack_totals[domain][attack_type]
|
||||||
for (ip in attack_data[domain][attack_type]) {
|
for (ip in attack_data[domain][attack_type]) {
|
||||||
@@ -1378,7 +1378,7 @@ analyze_domain_targeting_percentage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
' -v tmpdir="$TEMP_DIR" < "$TEMP_DIR/attack_vectors_raw.txt"
|
' < "$TEMP_DIR/attack_vectors_raw.txt"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
print_success "Domain attack pattern analysis complete"
|
print_success "Domain attack pattern analysis complete"
|
||||||
@@ -1608,11 +1608,9 @@ is_excluded_ip() {
|
|||||||
return 0 # True - should be excluded
|
return 0 # True - should be excluded
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if it's the server's own IP
|
# Check if it's the server's own IP (using pre-loaded array for speed)
|
||||||
if [ -f "$TEMP_DIR/server_ips.txt" ]; then
|
if [ -n "${server_ips_array[$ip]}" ]; then
|
||||||
if grep -qFx "$ip" "$TEMP_DIR/server_ips.txt" 2>/dev/null; then
|
return 0 # True - should be excluded
|
||||||
return 0 # True - should be excluded
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 1 # False - should not be excluded
|
return 1 # False - should not be excluded
|
||||||
@@ -1656,45 +1654,62 @@ analyze_time_series() {
|
|||||||
calculate_threat_scores() {
|
calculate_threat_scores() {
|
||||||
print_info "Calculating threat scores..."
|
print_info "Calculating threat scores..."
|
||||||
|
|
||||||
# Pre-count requests per IP (MUCH faster than grepping for each IP)
|
# Pre-load server IPs for fast exclusion checking (avoids grep in loop)
|
||||||
|
declare -A server_ips_array
|
||||||
|
if [ -f "$TEMP_DIR/server_ips.txt" ]; then
|
||||||
|
while read -r ip; do
|
||||||
|
[ -n "$ip" ] && server_ips_array["$ip"]=1
|
||||||
|
done < "$TEMP_DIR/server_ips.txt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Pre-count requests per IP using mapfile (faster than while-read on large files)
|
||||||
declare -A ip_request_counts
|
declare -A ip_request_counts
|
||||||
while IFS='|' read -r ip rest; do
|
mapfile -t parsed_lines < "$TEMP_DIR/parsed_logs.txt"
|
||||||
|
for line in "${parsed_lines[@]}"; do
|
||||||
|
ip="${line%%|*}"
|
||||||
((ip_request_counts["$ip"]++))
|
((ip_request_counts["$ip"]++))
|
||||||
done < "$TEMP_DIR/parsed_logs.txt"
|
done
|
||||||
|
|
||||||
# Build hash tables from threat files for O(1) lookups
|
# Build hash tables from threat files for O(1) lookups
|
||||||
# OPTIMIZATION: Use awk instead of echo|awk|cut in loops (10x faster)
|
# OPTIMIZATION: Use awk instead of echo|awk|cut in loops (10x faster)
|
||||||
declare -A threat_ips_sqli threat_ips_xss threat_ips_path threat_ips_rce threat_ips_login
|
declare -A threat_ips_sqli threat_ips_xss threat_ips_path threat_ips_rce threat_ips_login
|
||||||
declare -A threat_ips_suspicious threat_ips_ddos threat_admin_count threat_404_count
|
declare -A threat_ips_suspicious threat_ips_ddos threat_admin_count threat_404_count
|
||||||
|
|
||||||
# Parse each threat file and build hash tables (optimized with awk)
|
# Parse each threat file and build hash tables (using mapfile to avoid subshells)
|
||||||
[ -f "$TEMP_DIR/sqli_attempts.txt" ] && while read -r ip; do
|
if [ -f "$TEMP_DIR/sqli_attempts.txt" ]; then
|
||||||
threat_ips_sqli["$ip"]=1
|
mapfile -t sqli_ips < <(awk '{print $2}' "$TEMP_DIR/sqli_attempts.txt" | cut -d'|' -f1)
|
||||||
done < <(awk '{print $2}' "$TEMP_DIR/sqli_attempts.txt" | cut -d'|' -f1)
|
for ip in "${sqli_ips[@]}"; do threat_ips_sqli["$ip"]=1; done
|
||||||
|
fi
|
||||||
|
|
||||||
[ -f "$TEMP_DIR/xss_attempts.txt" ] && while read -r ip; do
|
if [ -f "$TEMP_DIR/xss_attempts.txt" ]; then
|
||||||
threat_ips_xss["$ip"]=1
|
mapfile -t xss_ips < <(awk '{print $2}' "$TEMP_DIR/xss_attempts.txt" | cut -d'|' -f1)
|
||||||
done < <(awk '{print $2}' "$TEMP_DIR/xss_attempts.txt" | cut -d'|' -f1)
|
for ip in "${xss_ips[@]}"; do threat_ips_xss["$ip"]=1; done
|
||||||
|
fi
|
||||||
|
|
||||||
[ -f "$TEMP_DIR/path_traversal_attempts.txt" ] && while read -r ip; do
|
if [ -f "$TEMP_DIR/path_traversal_attempts.txt" ]; then
|
||||||
threat_ips_path["$ip"]=1
|
mapfile -t path_ips < <(awk '{print $2}' "$TEMP_DIR/path_traversal_attempts.txt" | cut -d'|' -f1)
|
||||||
done < <(awk '{print $2}' "$TEMP_DIR/path_traversal_attempts.txt" | cut -d'|' -f1)
|
for ip in "${path_ips[@]}"; do threat_ips_path["$ip"]=1; done
|
||||||
|
fi
|
||||||
|
|
||||||
[ -f "$TEMP_DIR/rce_upload_attempts.txt" ] && while read -r ip; do
|
if [ -f "$TEMP_DIR/rce_upload_attempts.txt" ]; then
|
||||||
threat_ips_rce["$ip"]=1
|
mapfile -t rce_ips < <(awk '{print $2}' "$TEMP_DIR/rce_upload_attempts.txt" | cut -d'|' -f1)
|
||||||
done < <(awk '{print $2}' "$TEMP_DIR/rce_upload_attempts.txt" | cut -d'|' -f1)
|
for ip in "${rce_ips[@]}"; do threat_ips_rce["$ip"]=1; done
|
||||||
|
fi
|
||||||
|
|
||||||
[ -f "$TEMP_DIR/login_bruteforce_attempts.txt" ] && while read -r ip; do
|
if [ -f "$TEMP_DIR/login_bruteforce_attempts.txt" ]; then
|
||||||
threat_ips_login["$ip"]=1
|
mapfile -t login_ips < <(awk '{print $2}' "$TEMP_DIR/login_bruteforce_attempts.txt" | cut -d'|' -f1)
|
||||||
done < <(awk '{print $2}' "$TEMP_DIR/login_bruteforce_attempts.txt" | cut -d'|' -f1)
|
for ip in "${login_ips[@]}"; do threat_ips_login["$ip"]=1; done
|
||||||
|
fi
|
||||||
|
|
||||||
[ -f "$TEMP_DIR/suspicious_ua.txt" ] && while read -r ip; do
|
if [ -f "$TEMP_DIR/suspicious_ua.txt" ]; then
|
||||||
threat_ips_suspicious["$ip"]=1
|
mapfile -t susp_ips < <(awk '{print $2}' "$TEMP_DIR/suspicious_ua.txt" | cut -d'|' -f1)
|
||||||
done < <(awk '{print $2}' "$TEMP_DIR/suspicious_ua.txt" | cut -d'|' -f1)
|
for ip in "${susp_ips[@]}"; do threat_ips_suspicious["$ip"]=1; done
|
||||||
|
fi
|
||||||
|
|
||||||
[ -f "$TEMP_DIR/rapid_fire_ips.txt" ] && while read -r ip; do
|
if [ -f "$TEMP_DIR/rapid_fire_ips.txt" ]; then
|
||||||
threat_ips_ddos["$ip"]=1
|
mapfile -t ddos_ips < <(awk '{print $2}' "$TEMP_DIR/rapid_fire_ips.txt")
|
||||||
done < <(awk '{print $2}' "$TEMP_DIR/rapid_fire_ips.txt")
|
for ip in "${ddos_ips[@]}"; do threat_ips_ddos["$ip"]=1; done
|
||||||
|
fi
|
||||||
|
|
||||||
# Parse count-based threat files
|
# Parse count-based threat files
|
||||||
[ -f "$TEMP_DIR/admin_probes.txt" ] && while read -r count ip; do
|
[ -f "$TEMP_DIR/admin_probes.txt" ] && while read -r count ip; do
|
||||||
|
|||||||
Reference in New Issue
Block a user