diff --git a/modules/security/bot-analyzer.sh b/modules/security/bot-analyzer.sh index 75ce99e..6838a12 100755 --- a/modules/security/bot-analyzer.sh +++ b/modules/security/bot-analyzer.sh @@ -1667,34 +1667,41 @@ calculate_threat_scores() { 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 - # Parse each threat file and build hash tables (optimized with awk) - [ -f "$TEMP_DIR/sqli_attempts.txt" ] && while read -r ip; do - threat_ips_sqli["$ip"]=1 - done < <(awk '{print $2}' "$TEMP_DIR/sqli_attempts.txt" | cut -d'|' -f1) + # Parse each threat file and build hash tables (using mapfile to avoid subshells) + if [ -f "$TEMP_DIR/sqli_attempts.txt" ]; then + mapfile -t sqli_ips < <(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 - threat_ips_xss["$ip"]=1 - done < <(awk '{print $2}' "$TEMP_DIR/xss_attempts.txt" | cut -d'|' -f1) + if [ -f "$TEMP_DIR/xss_attempts.txt" ]; then + mapfile -t xss_ips < <(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 - threat_ips_path["$ip"]=1 - done < <(awk '{print $2}' "$TEMP_DIR/path_traversal_attempts.txt" | cut -d'|' -f1) + if [ -f "$TEMP_DIR/path_traversal_attempts.txt" ]; then + mapfile -t path_ips < <(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 - threat_ips_rce["$ip"]=1 - done < <(awk '{print $2}' "$TEMP_DIR/rce_upload_attempts.txt" | cut -d'|' -f1) + if [ -f "$TEMP_DIR/rce_upload_attempts.txt" ]; then + mapfile -t rce_ips < <(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 - threat_ips_login["$ip"]=1 - done < <(awk '{print $2}' "$TEMP_DIR/login_bruteforce_attempts.txt" | cut -d'|' -f1) + if [ -f "$TEMP_DIR/login_bruteforce_attempts.txt" ]; then + mapfile -t login_ips < <(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 - threat_ips_suspicious["$ip"]=1 - done < <(awk '{print $2}' "$TEMP_DIR/suspicious_ua.txt" | cut -d'|' -f1) + if [ -f "$TEMP_DIR/suspicious_ua.txt" ]; then + mapfile -t susp_ips < <(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 - threat_ips_ddos["$ip"]=1 - done < <(awk '{print $2}' "$TEMP_DIR/rapid_fire_ips.txt") + if [ -f "$TEMP_DIR/rapid_fire_ips.txt" ]; then + mapfile -t ddos_ips < <(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 [ -f "$TEMP_DIR/admin_probes.txt" ] && while read -r count ip; do