From d72f824aea6741b36376c4d678d98b85317ab83a Mon Sep 17 00:00:00 2001 From: Developer Date: Fri, 20 Mar 2026 18:32:31 -0400 Subject: [PATCH] CRITICAL FIXES: Scan script integrity and reliability improvements FIXES: - Create log/results directories before use (prevents all append operations from failing) - Add error checking for RKHunter database/baseline updates - Background Maldet scans with proper PID tracking and wait validation - Add PID validation before all wait commands (ImunifyAV, ClamAV) - Remove unused TOTAL_MALDET_HITS variable - Rename FILES_SCANNED to context-specific names (CLAMAV/MALDET) for clarity IMPACT: - Fixes log file failures that were silently discarding scanner output - Improves diagnostics with proper error logging for RKHunter initialization - Enables parallel execution of Maldet scans across multiple paths - Prevents wait command failures from invalid PIDs - Eliminates variable naming confusion across scanner implementations These fixes address all 7 critical issues found in audit pass 4. --- modules/security/malware-scanner.sh | 89 ++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/modules/security/malware-scanner.sh b/modules/security/malware-scanner.sh index 79855ad..ca3384a 100755 --- a/modules/security/malware-scanner.sh +++ b/modules/security/malware-scanner.sh @@ -676,6 +676,9 @@ SCAN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" LOG_DIR="$SCAN_DIR/logs" RESULTS_DIR="$SCAN_DIR/results" +# Create log and results directories +mkdir -p "$LOG_DIR" "$RESULTS_DIR" + # Session info SESSION_LOG="$LOG_DIR/session.log" SUMMARY_FILE="$RESULTS_DIR/summary.txt" @@ -827,8 +830,16 @@ else log_message "RKHunter: Installing via yum..." if yum install -y rkhunter &>/dev/null; then # Update definitions and initialize baseline - rkhunter --update &>/dev/null - rkhunter --propupd &>/dev/null + if rkhunter --update &>/dev/null; then + log_message "RKHunter: Database update successful" + else + log_message "WARNING: RKHunter database update failed" + fi + if rkhunter --propupd &>/dev/null; then + log_message "RKHunter: Property baseline created" + else + log_message "WARNING: RKHunter property baseline creation failed" + fi AVAILABLE_SCANNERS+=("rkhunter") RKHUNTER_TEMP_INSTALLED=true @@ -842,8 +853,16 @@ else log_message "RKHunter: Installing via apt-get..." if apt-get update &>/dev/null && apt-get install -y rkhunter &>/dev/null; then # Update definitions and initialize baseline - rkhunter --update &>/dev/null - rkhunter --propupd &>/dev/null + if rkhunter --update &>/dev/null; then + log_message "RKHunter: Database update successful" + else + log_message "WARNING: RKHunter database update failed" + fi + if rkhunter --propupd &>/dev/null; then + log_message "RKHunter: Property baseline created" + else + log_message "WARNING: RKHunter property baseline creation failed" + fi AVAILABLE_SCANNERS+=("rkhunter") RKHUNTER_TEMP_INSTALLED=true @@ -1007,8 +1026,13 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do IMUNIFY_PID=$! # Monitor with simple timeout (don't try to parse imunify status which hangs) - wait $IMUNIFY_PID - IMUNIFY_EXIT=$? + if [ -n "$IMUNIFY_PID" ] && kill -0 "$IMUNIFY_PID" 2>/dev/null; then + wait "$IMUNIFY_PID" + IMUNIFY_EXIT=$? + else + log_message "ERROR: ImunifyAV PID not found for $path" + IMUNIFY_EXIT=1 + fi if [ "$IMUNIFY_EXIT" -eq 124 ]; then log_message "ERROR: ImunifyAV scan timed out after 2 hours for $path" @@ -1127,8 +1151,13 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do done # Wait for scan to complete and get exit code - wait $CLAM_PID - CLAM_EXIT=$? + if [ -n "$CLAM_PID" ] && kill -0 "$CLAM_PID" 2>/dev/null; then + wait "$CLAM_PID" + CLAM_EXIT=$? + else + log_message "ERROR: ClamAV PID not found (scan process may have exited prematurely)" + CLAM_EXIT=1 + fi echo "" # New line after spinner if [ "$CLAM_EXIT" -eq 124 ]; then @@ -1153,17 +1182,17 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do grep "FOUND" "$LOG_DIR/clamav.log" 2>/dev/null | cut -d: -f1 >> "$INFECTED_LIST" 2>/dev/null || true # Get scan stats from log (FIXED Issue 1B: robust number extraction independent of column position) - FILES_SCANNED=$(grep "Scanned files:" "$LOG_DIR/clamav.log" 2>/dev/null | tail -1 | grep -oE '[0-9]+' | head -1 || echo "0") + CLAMAV_FILES_SCANNED=$(grep "Scanned files:" "$LOG_DIR/clamav.log" 2>/dev/null | tail -1 | grep -oE '[0-9]+' | head -1 || echo "0") CLAM_INFECTED=$(grep -c "FOUND" "$LOG_DIR/clamav.log" 2>/dev/null) || CLAM_INFECTED=0 # Validate numbers (ensure they're numeric) - if ! [[ "$FILES_SCANNED" =~ ^[0-9]+$ ]]; then - FILES_SCANNED=0 + if ! [[ "$CLAMAV_FILES_SCANNED" =~ ^[0-9]+$ ]]; then + CLAMAV_FILES_SCANNED=0 fi SCAN_END=$(date +%s) DURATION=$((SCAN_END - SCAN_START)) - echo " ✓ Scanned $FILES_SCANNED files" + echo " ✓ Scanned $CLAMAV_FILES_SCANNED files" echo " ⏱️ Duration: ${DURATION}s" echo "" echo "✓ ClamAV scan complete - Found: $CLAM_INFECTED | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE" @@ -1189,8 +1218,7 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do # Note: -a flag scans all files regardless of modification time # Cannot combine -a with -f (file-list), so we loop through paths MALDET_EXIT=0 - TOTAL_MALDET_FILES=0 - TOTAL_MALDET_HITS=0 + MALDET_PIDS=() for path in "${SCAN_PATHS[@]}"; do if [ ! -d "$path" ]; then @@ -1201,16 +1229,23 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do log_message "Maldet: Scanning $path with -a (all files)" # Run with -a (scan-all) for comprehensive scanning - # Timeout after 2 hours per path - timeout 7200 maldet -b -a "$path" &>> "$LOG_DIR/maldet.log" - exit_code=$? + # Timeout after 2 hours per path, run in background for better progress tracking + timeout 7200 maldet -b -a "$path" &>> "$LOG_DIR/maldet.log" & + MALDET_PIDS+=($!) - if [ "$exit_code" -ne 0 ]; then - MALDET_EXIT=$exit_code + # Give scan a moment to start + sleep 1 + done + + # Wait for all maldet scans to complete and collect exit codes + for pid in "${MALDET_PIDS[@]}"; do + if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then + wait "$pid" + exit_code=$? + if [ "$exit_code" -ne 0 ]; then + MALDET_EXIT=$exit_code + fi fi - - # Give scan a moment to complete - sleep 2 done echo "" # New line after progress @@ -1244,20 +1279,20 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do event_log=$(find /opt -name "*maldet*event_log" -type f 2>/dev/null | head -1) fi - FILES_SCANNED="0" + MALDET_FILES_SCANNED="0" MALDET_HITS="0" if [ -f "$event_log" ]; then # Use -E instead of -P for portability (BSD grep doesn't support -P) # FIXED Issue 2A: Robust parsing independent of format variations last_line=$(grep "scan completed" "$event_log" 2>/dev/null | tail -1) - FILES_SCANNED=$(echo "$last_line" | grep -oE '[0-9]+ files' 2>/dev/null | grep -oE '^[0-9]+' || echo "0") + MALDET_FILES_SCANNED=$(echo "$last_line" | grep -oE '[0-9]+ files' 2>/dev/null | grep -oE '^[0-9]+' || echo "0") MALDET_HITS=$(echo "$last_line" | grep -oE '[0-9]+ (malware hits|malicious)' 2>/dev/null | grep -oE '^[0-9]+' || echo "0") fi # Validate numbers - if ! [[ "$FILES_SCANNED" =~ ^[0-9]+$ ]]; then - FILES_SCANNED=0 + if ! [[ "$MALDET_FILES_SCANNED" =~ ^[0-9]+$ ]]; then + MALDET_FILES_SCANNED=0 fi if ! [[ "$MALDET_HITS" =~ ^[0-9]+$ ]]; then MALDET_HITS=0 @@ -1265,7 +1300,7 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do SCAN_END=$(date +%s) DURATION=$((SCAN_END - SCAN_START)) - echo " ✓ Scanned $FILES_SCANNED files" + echo " ✓ Scanned $MALDET_FILES_SCANNED files" echo " ⏱️ Duration: ${DURATION}s" echo "" echo "✓ Maldet scan complete - Found: ${MALDET_HITS:-0} | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE"