Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 50001c2e4a | |||
| 94e3ca42c1 | |||
| 0598bbd5ff | |||
| 3ad46ae607 | |||
| 3daa8f5b06 | |||
| 854594a577 | |||
| de46a77728 | |||
| 448f1ed1d5 | |||
| 18f4d93c17 | |||
| 7e48aa26f0 | |||
| 2e785ff55e | |||
| 4194a529cc |
@@ -603,6 +603,9 @@ cleanup_on_exit() {
|
|||||||
local exit_code=$?
|
local exit_code=$?
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
# Remove running marker file
|
||||||
|
rm -f "$SCAN_DIR/.scan_running"
|
||||||
|
|
||||||
# Only log if session log exists
|
# Only log if session log exists
|
||||||
if [ -f "$SESSION_LOG" ]; then
|
if [ -f "$SESSION_LOG" ]; then
|
||||||
log_message "Cleanup triggered (exit code: $exit_code)"
|
log_message "Cleanup triggered (exit code: $exit_code)"
|
||||||
@@ -651,6 +654,9 @@ echo ""
|
|||||||
|
|
||||||
log_message "Scan session started"
|
log_message "Scan session started"
|
||||||
|
|
||||||
|
# Create marker file to indicate scan is running
|
||||||
|
touch "$SCAN_DIR/.scan_running"
|
||||||
|
|
||||||
# Detect available scanners
|
# Detect available scanners
|
||||||
AVAILABLE_SCANNERS=()
|
AVAILABLE_SCANNERS=()
|
||||||
|
|
||||||
@@ -803,6 +809,21 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do
|
|||||||
|
|
||||||
case "$scanner" in
|
case "$scanner" in
|
||||||
imunify)
|
imunify)
|
||||||
|
# ImunifyAV has built-in exclusions that prevent comprehensive system scanning
|
||||||
|
# Only use ImunifyAV for user-focused scans (not full server scans)
|
||||||
|
if [ "${#SCAN_PATHS[@]}" -eq 1 ] && [ "${SCAN_PATHS[0]}" = "/" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "ℹ️ Skipping ImunifyAV for full server scan"
|
||||||
|
echo " Reason: ImunifyAV has built-in exclusions that skip system directories"
|
||||||
|
echo " ClamAV and Maldet will provide comprehensive coverage instead"
|
||||||
|
echo ""
|
||||||
|
log_message "ImunifyAV: Skipped (not suitable for full server scans - use ClamAV/Maldet instead)"
|
||||||
|
{
|
||||||
|
echo "⊘ ImunifyAV scan skipped (not suitable for full system scans)"
|
||||||
|
} >> "$SUMMARY_FILE"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
SCAN_START=$(date +%s)
|
SCAN_START=$(date +%s)
|
||||||
log_message "ImunifyAV: Updating signatures"
|
log_message "ImunifyAV: Updating signatures"
|
||||||
|
|
||||||
@@ -811,13 +832,16 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do
|
|||||||
echo "⚠️ WARNING: Signature update failed, using existing signatures"
|
echo "⚠️ WARNING: Signature update failed, using existing signatures"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log_message "ImunifyAV: Starting on-demand scan (synchronous)"
|
log_message "ImunifyAV: Starting on-demand scan"
|
||||||
|
|
||||||
# Use on-demand start with background monitoring for progress
|
# Use on-demand start with background monitoring for progress
|
||||||
LAST_SCAN=""
|
LAST_SCAN=""
|
||||||
TOTAL_FILES_SCANNED=0
|
TOTAL_FILES_SCANNED=0
|
||||||
|
|
||||||
for path in "${SCAN_PATHS[@]}"; do
|
# For user-focused scans, use paths as-is
|
||||||
|
local IMUNIFY_SCAN_PATHS=("${SCAN_PATHS[@]}")
|
||||||
|
|
||||||
|
for path in "${IMUNIFY_SCAN_PATHS[@]}"; do
|
||||||
if [ -d "$path" ]; then
|
if [ -d "$path" ]; then
|
||||||
log_message "ImunifyAV: Scanning $path"
|
log_message "ImunifyAV: Scanning $path"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -854,9 +878,9 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do
|
|||||||
current_status=$(echo "$scan_info" | awk '{print $7}') # Field 7 is SCAN_STATUS
|
current_status=$(echo "$scan_info" | awk '{print $7}') # Field 7 is SCAN_STATUS
|
||||||
|
|
||||||
# Check if this is our scan (created after we started)
|
# Check if this is our scan (created after we started)
|
||||||
if [ "$created_time" -ge "$SCAN_START" ]; then
|
if [[ "$created_time" =~ ^[0-9]+$ ]] && [ "$created_time" -ge "$SCAN_START" ]; then
|
||||||
# Check if scan is complete (COMPLETED field has timestamp)
|
# Check if scan is complete (COMPLETED field has timestamp)
|
||||||
if [ -n "$completed_time" ] && [ "$completed_time" != "COMPLETED" ] && [ "$completed_time" -gt 0 ]; then
|
if [ -n "$completed_time" ] && [ "$completed_time" != "COMPLETED" ] && [[ "$completed_time" =~ ^[0-9]+$ ]] && [ "$completed_time" -gt 0 ]; then
|
||||||
scan_running=false
|
scan_running=false
|
||||||
echo "" # New line after progress
|
echo "" # New line after progress
|
||||||
log_message "ImunifyAV scan finished for $path (status: $current_status)"
|
log_message "ImunifyAV scan finished for $path (status: $current_status)"
|
||||||
@@ -1035,34 +1059,46 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do
|
|||||||
echo "⚠️ WARNING: Signature update failed, using existing signatures"
|
echo "⚠️ WARNING: Signature update failed, using existing signatures"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create temp path list
|
|
||||||
TEMP_PATHLIST="/tmp/maldet_paths_$$.txt"
|
|
||||||
printf '%s\n' "${SCAN_PATHS[@]}" > "$TEMP_PATHLIST"
|
|
||||||
|
|
||||||
log_message "Maldet: Starting scan with live progress"
|
log_message "Maldet: Starting scan with live progress"
|
||||||
echo ""
|
echo ""
|
||||||
echo " 📁 Scanning path(s): ${SCAN_PATHS[*]}"
|
echo " 📁 Scanning path(s): ${SCAN_PATHS[*]}"
|
||||||
echo " ⏳ Scanner: Maldet/LMD (Linux-specific malware detection...)"
|
echo " ⏳ Scanner: Maldet/LMD (Linux-specific malware detection...)"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Run with --progress for real-time percentage updates
|
# Scan each path individually with -a (scan-all) flag
|
||||||
# Timeout after 2 hours
|
# Note: -a flag scans all files regardless of modification time
|
||||||
timeout 7200 maldet -b -f "$TEMP_PATHLIST" 2>&1 | tee -a "$LOG_DIR/maldet.log" | while IFS= read -r line; do
|
# Cannot combine -a with -f (file-list), so we loop through paths
|
||||||
# Parse progress lines: "files: 1234 (45%)"
|
MALDET_EXIT=0
|
||||||
if [[ "$line" =~ files:\ ([0-9]+)\ \(([0-9]+)%\) ]]; then
|
TOTAL_MALDET_FILES=0
|
||||||
files_so_far="${BASH_REMATCH[1]}"
|
TOTAL_MALDET_HITS=0
|
||||||
percent="${BASH_REMATCH[2]}"
|
|
||||||
printf "\r Progress: %3d%% (%s files scanned) " "$percent" "$files_so_far"
|
for path in "${SCAN_PATHS[@]}"; do
|
||||||
|
if [ ! -d "$path" ]; then
|
||||||
|
log_message "Maldet: Skipping non-existent path: $path"
|
||||||
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
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=$?
|
||||||
|
|
||||||
|
if [ "$exit_code" -ne 0 ]; then
|
||||||
|
MALDET_EXIT=$exit_code
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Give scan a moment to complete
|
||||||
|
sleep 2
|
||||||
done
|
done
|
||||||
MALDET_EXIT=$?
|
|
||||||
echo "" # New line after progress
|
echo "" # New line after progress
|
||||||
|
|
||||||
if [ "$MALDET_EXIT" -eq 124 ]; then
|
if [ "$MALDET_EXIT" -eq 124 ]; then
|
||||||
log_message "ERROR: Maldet scan timed out after 2 hours"
|
log_message "ERROR: Maldet scan timed out after 2 hours"
|
||||||
echo " ⏱️ Scan timed out (exceeded 2 hour limit)"
|
echo " ⏱️ Scan timed out (exceeded 2 hour limit)"
|
||||||
echo "Maldet scan timed out" >> "$SUMMARY_FILE"
|
echo "Maldet scan timed out" >> "$SUMMARY_FILE"
|
||||||
rm -f "$TEMP_PATHLIST"
|
|
||||||
SCAN_END=$(date +%s)
|
SCAN_END=$(date +%s)
|
||||||
DURATION=$((SCAN_END - SCAN_START))
|
DURATION=$((SCAN_END - SCAN_START))
|
||||||
echo ""
|
echo ""
|
||||||
@@ -1071,16 +1107,16 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do
|
|||||||
log_message "ERROR: Maldet scan failed with exit code $MALDET_EXIT"
|
log_message "ERROR: Maldet scan failed with exit code $MALDET_EXIT"
|
||||||
echo " ✗ Scan failed (exit code: $MALDET_EXIT) - check logs"
|
echo " ✗ Scan failed (exit code: $MALDET_EXIT) - check logs"
|
||||||
echo "Maldet scan failed (exit code: $MALDET_EXIT)" >> "$SUMMARY_FILE"
|
echo "Maldet scan failed (exit code: $MALDET_EXIT)" >> "$SUMMARY_FILE"
|
||||||
rm -f "$TEMP_PATHLIST"
|
|
||||||
SCAN_END=$(date +%s)
|
SCAN_END=$(date +%s)
|
||||||
DURATION=$((SCAN_END - SCAN_START))
|
DURATION=$((SCAN_END - SCAN_START))
|
||||||
echo ""
|
echo ""
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Extract scan results
|
# Extract scan results from event log (more reliable than parsing output)
|
||||||
FILES_SCANNED=$(grep "files scanned" "$LOG_DIR/maldet.log" | tail -1 | awk '{print $1}')
|
# Maldet logs to /usr/local/maldetect/logs/event_log
|
||||||
MALDET_HITS=$(grep "malware hits" "$LOG_DIR/maldet.log" | tail -1 | awk '{print $1}')
|
FILES_SCANNED=$(grep "scan completed" /usr/local/maldetect/logs/event_log | tail -1 | grep -oP 'files \K[0-9]+' || echo 0)
|
||||||
|
MALDET_HITS=$(grep "scan completed" /usr/local/maldetect/logs/event_log | tail -1 | grep -oP 'malware hits \K[0-9]+' || echo 0)
|
||||||
|
|
||||||
# Validate numbers
|
# Validate numbers
|
||||||
if ! [[ "$FILES_SCANNED" =~ ^[0-9]+$ ]]; then
|
if ! [[ "$FILES_SCANNED" =~ ^[0-9]+$ ]]; then
|
||||||
@@ -1090,8 +1126,6 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do
|
|||||||
MALDET_HITS=0
|
MALDET_HITS=0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f "$TEMP_PATHLIST"
|
|
||||||
|
|
||||||
SCAN_END=$(date +%s)
|
SCAN_END=$(date +%s)
|
||||||
DURATION=$((SCAN_END - SCAN_START))
|
DURATION=$((SCAN_END - SCAN_START))
|
||||||
echo " ✓ Scanned $FILES_SCANNED files"
|
echo " ✓ Scanned $FILES_SCANNED files"
|
||||||
@@ -1365,6 +1399,72 @@ else
|
|||||||
echo "⚠️ Scan Validation: $validation_issues issue(s) found - review logs" >> "$SUMMARY_FILE"
|
echo "⚠️ Scan Validation: $validation_issues issue(s) found - review logs" >> "$SUMMARY_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Generate client report automatically (inline to work in standalone scripts)
|
||||||
|
log_message "Generating client-facing security report"
|
||||||
|
|
||||||
|
# Check if function exists, if not generate inline
|
||||||
|
if declare -f generate_client_report > /dev/null 2>&1; then
|
||||||
|
generate_client_report "$SCAN_DIR" > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
# Inline client report generation for standalone scripts
|
||||||
|
client_report_file="$RESULTS_DIR/client_report.txt"
|
||||||
|
|
||||||
|
# Extract scan info
|
||||||
|
scan_date=$(grep "Started:" "$SUMMARY_FILE" | head -1 | sed 's/Started: //' || echo "Unknown")
|
||||||
|
scan_paths=$(sed -n '/^Paths:/,/^$/p' "$SUMMARY_FILE" | tail -n +2 | grep -v "^$" | tr '\n' ', ' | sed 's/, $//' || echo "/home")
|
||||||
|
|
||||||
|
# Analyze infected files for false positives
|
||||||
|
real_threats_count=0
|
||||||
|
false_positives_list=""
|
||||||
|
real_threats_list=""
|
||||||
|
|
||||||
|
if [ -f "$RESULTS_DIR/infected_files.txt" ] && [ -s "$RESULTS_DIR/infected_files.txt" ]; then
|
||||||
|
while IFS= read -r file; do
|
||||||
|
if [[ "$file" =~ /logs?/.*\.(log|gz|bz2)$ ]] || \
|
||||||
|
[[ "$file" =~ /awstats/ ]] || \
|
||||||
|
[[ "$file" =~ /tmp/.*\.txt$ ]] || \
|
||||||
|
[[ "$file" =~ \.log\.[0-9]+$ ]]; then
|
||||||
|
false_positives_list="${false_positives_list} • $file"$'\n'
|
||||||
|
else
|
||||||
|
real_threats_list="${real_threats_list}📁 $file"$'\n'
|
||||||
|
((real_threats_count++))
|
||||||
|
fi
|
||||||
|
done < "$RESULTS_DIR/infected_files.txt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate report
|
||||||
|
{
|
||||||
|
echo "MALWARE SCAN REPORT - $scan_date"
|
||||||
|
echo "═══════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo "Scanned with: ImunifyAV, ClamAV, Linux Maldet, RKHunter"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$real_threats_count" -eq 0 ]; then
|
||||||
|
echo "RESULT: ✅ No malware found - your server is clean"
|
||||||
|
else
|
||||||
|
echo "RESULT: ⚠️ $real_threats_count infected file(s) detected"
|
||||||
|
echo ""
|
||||||
|
echo "INFECTED FILES:"
|
||||||
|
echo "$real_threats_list"
|
||||||
|
echo "NEXT STEPS:"
|
||||||
|
echo " 1. Remove infected files immediately"
|
||||||
|
echo " 2. Change all passwords"
|
||||||
|
echo " 3. Update WordPress/plugins to latest versions"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$false_positives_list" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "───────────────────────────────────────────────────────────"
|
||||||
|
echo "NOTE: Attack attempts were detected in your server logs."
|
||||||
|
echo "These were successfully blocked. No action needed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Scan ID: $(basename $SCAN_DIR)"
|
||||||
|
} > "$client_report_file"
|
||||||
|
fi
|
||||||
|
|
||||||
# Display completion
|
# Display completion
|
||||||
clear
|
clear
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
@@ -1377,6 +1477,9 @@ echo "Results saved to:"
|
|||||||
echo " Summary: $SUMMARY_FILE"
|
echo " Summary: $SUMMARY_FILE"
|
||||||
echo " Logs: $LOG_DIR/"
|
echo " Logs: $LOG_DIR/"
|
||||||
echo ""
|
echo ""
|
||||||
|
echo -e "${CYAN}Client Report (copy/paste for tickets):${NC}"
|
||||||
|
echo " $RESULTS_DIR/client_report.txt"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Show summary
|
# Show summary
|
||||||
cat "$SUMMARY_FILE"
|
cat "$SUMMARY_FILE"
|
||||||
@@ -1384,6 +1487,9 @@ cat "$SUMMARY_FILE"
|
|||||||
echo ""
|
echo ""
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo ""
|
echo ""
|
||||||
|
echo -e "${CYAN}TIP:${NC} To view the client-friendly report:"
|
||||||
|
echo " cat $RESULTS_DIR/client_report.txt"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Prompt for cleanup (RKHunter cleanup handled by trap)
|
# Prompt for cleanup (RKHunter cleanup handled by trap)
|
||||||
read -p "Delete scan script? (Logs and results will be preserved) (yes/no): " cleanup_choice
|
read -p "Delete scan script? (Logs and results will be preserved) (yes/no): " cleanup_choice
|
||||||
@@ -1623,9 +1729,10 @@ launch_standalone_scanner_menu() {
|
|||||||
if [ -n "$preset_scope" ]; then
|
if [ -n "$preset_scope" ]; then
|
||||||
case "$preset_scope" in
|
case "$preset_scope" in
|
||||||
server) scope_choice=1 ;;
|
server) scope_choice=1 ;;
|
||||||
user) scope_choice=2 ;;
|
all_users) scope_choice=2 ;;
|
||||||
domain) scope_choice=3 ;;
|
user) scope_choice=3 ;;
|
||||||
custom) scope_choice=4 ;;
|
domain) scope_choice=4 ;;
|
||||||
|
custom) scope_choice=5 ;;
|
||||||
*) scope_choice=0 ;;
|
*) scope_choice=0 ;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
@@ -1667,6 +1774,34 @@ launch_standalone_scanner_menu() {
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
2)
|
2)
|
||||||
|
# All user accounts
|
||||||
|
echo ""
|
||||||
|
echo "Scanning all user home directories..."
|
||||||
|
|
||||||
|
# Determine user base directory based on control panel
|
||||||
|
local user_base_dir
|
||||||
|
case "$CONTROL_PANEL" in
|
||||||
|
plesk)
|
||||||
|
user_base_dir="/var/www/vhosts"
|
||||||
|
;;
|
||||||
|
cpanel|interworx|standalone)
|
||||||
|
user_base_dir="/home"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
user_base_dir="/home"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Add the user base directory to scan paths
|
||||||
|
scan_paths=("$user_base_dir")
|
||||||
|
scan_description="all user accounts in $user_base_dir"
|
||||||
|
|
||||||
|
echo "Control Panel: ${CONTROL_PANEL^}"
|
||||||
|
echo "User directory: $user_base_dir"
|
||||||
|
echo "Scan scope: All user home directories"
|
||||||
|
;;
|
||||||
|
|
||||||
|
3)
|
||||||
# Specific user
|
# Specific user
|
||||||
echo ""
|
echo ""
|
||||||
echo "Available users:"
|
echo "Available users:"
|
||||||
@@ -1695,7 +1830,7 @@ launch_standalone_scanner_menu() {
|
|||||||
echo "Found ${#scan_paths[@]} docroots for $SELECTED_USER"
|
echo "Found ${#scan_paths[@]} docroots for $SELECTED_USER"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
3)
|
4)
|
||||||
# Specific domain
|
# Specific domain
|
||||||
echo ""
|
echo ""
|
||||||
read -p "Enter domain name: " domain
|
read -p "Enter domain name: " domain
|
||||||
@@ -1723,7 +1858,7 @@ launch_standalone_scanner_menu() {
|
|||||||
echo "Found docroot: ${scan_paths[0]}"
|
echo "Found docroot: ${scan_paths[0]}"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
4)
|
5)
|
||||||
# Custom path
|
# Custom path
|
||||||
echo ""
|
echo ""
|
||||||
read -p "Enter path to scan: " custom_path
|
read -p "Enter path to scan: " custom_path
|
||||||
@@ -1799,8 +1934,9 @@ check_standalone_status() {
|
|||||||
for dir in "${standalone_dirs[@]}"; do
|
for dir in "${standalone_dirs[@]}"; do
|
||||||
local session_name=$(basename "$dir")
|
local session_name=$(basename "$dir")
|
||||||
|
|
||||||
# Check if still running
|
# Check if still running by looking for bash process executing scan.sh
|
||||||
if pgrep -f "$dir/scan.sh" > /dev/null 2>&1; then
|
# Use pgrep with exact match to avoid false positives from viewers/editors
|
||||||
|
if pgrep -f "bash $dir/scan.sh" > /dev/null 2>&1 || [ -f "$dir/.scan_running" ]; then
|
||||||
echo -e " ${GREEN}●${NC} $session_name [RUNNING]"
|
echo -e " ${GREEN}●${NC} $session_name [RUNNING]"
|
||||||
((running_count++))
|
((running_count++))
|
||||||
|
|
||||||
@@ -1865,7 +2001,7 @@ delete_standalone_sessions() {
|
|||||||
local session_name=$(basename "$dir")
|
local session_name=$(basename "$dir")
|
||||||
local status="completed"
|
local status="completed"
|
||||||
|
|
||||||
if pgrep -f "$dir/scan.sh" > /dev/null 2>&1; then
|
if pgrep -f "bash $dir/scan.sh" > /dev/null 2>&1 || [ -f "$dir/.scan_running" ]; then
|
||||||
status="${GREEN}running${NC}"
|
status="${GREEN}running${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1967,19 +2103,20 @@ show_scan_menu() {
|
|||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo -e "${CYAN}Create New Scan:${NC}"
|
echo -e "${CYAN}Create New Scan:${NC}"
|
||||||
echo " 1. Scan entire server"
|
echo " 1. Scan entire server (ClamAV, Maldet, RKHunter)"
|
||||||
echo " 2. Scan specific user"
|
echo " 2. Scan all user accounts (All scanners - recommended)"
|
||||||
echo " 3. Scan specific domain"
|
echo " 3. Scan specific user account (All scanners)"
|
||||||
echo " 4. Scan custom path"
|
echo " 4. Scan specific domain (All scanners)"
|
||||||
|
echo " 5. Scan custom path (All scanners)"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Monitor & Manage:${NC}"
|
echo -e "${CYAN}Monitor & Manage:${NC}"
|
||||||
echo " 5. Check scan status"
|
echo " 6. Check scan status"
|
||||||
echo " 6. View scan results"
|
echo " 7. View scan results"
|
||||||
echo " 7. Delete scan sessions"
|
echo " 8. Delete scan sessions"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Configuration:${NC}"
|
echo -e "${CYAN}Configuration:${NC}"
|
||||||
echo " 8. Install all scanners"
|
echo " 9. Install all scanners"
|
||||||
echo " 9. Scanner settings"
|
echo " 10. Scanner settings"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " ${RED}0.${NC} Back"
|
echo -e " ${RED}0.${NC} Back"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -1988,14 +2125,15 @@ show_scan_menu() {
|
|||||||
|
|
||||||
case $choice in
|
case $choice in
|
||||||
1) launch_standalone_scanner_menu "server" ;;
|
1) launch_standalone_scanner_menu "server" ;;
|
||||||
2) launch_standalone_scanner_menu "user" ;;
|
2) launch_standalone_scanner_menu "all_users" ;;
|
||||||
3) launch_standalone_scanner_menu "domain" ;;
|
3) launch_standalone_scanner_menu "user" ;;
|
||||||
4) launch_standalone_scanner_menu "custom" ;;
|
4) launch_standalone_scanner_menu "domain" ;;
|
||||||
5) check_standalone_status ;;
|
5) launch_standalone_scanner_menu "custom" ;;
|
||||||
6) view_scan_results ;;
|
6) check_standalone_status ;;
|
||||||
7) delete_standalone_sessions ;;
|
7) view_scan_results ;;
|
||||||
8) install_all_scanners ;;
|
8) delete_standalone_sessions ;;
|
||||||
9) scanner_settings ;;
|
9) install_all_scanners ;;
|
||||||
|
10) scanner_settings ;;
|
||||||
0) return 0 ;;
|
0) return 0 ;;
|
||||||
*) echo -e "${RED}Invalid option${NC}"; sleep 1 ;;
|
*) echo -e "${RED}Invalid option${NC}"; sleep 1 ;;
|
||||||
esac
|
esac
|
||||||
@@ -2146,6 +2284,27 @@ view_scan_results() {
|
|||||||
|
|
||||||
echo "View full logs:"
|
echo "View full logs:"
|
||||||
echo " tail -f $selected_dir/logs/session.log"
|
echo " tail -f $selected_dir/logs/session.log"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Offer to generate client report
|
||||||
|
echo -e "${CYAN}Actions:${NC}"
|
||||||
|
echo " 1. Generate client-facing security report"
|
||||||
|
echo " 0. Back to menu"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Select action (or press Enter to continue): " action_choice
|
||||||
|
|
||||||
|
case "$action_choice" in
|
||||||
|
1)
|
||||||
|
generate_client_report "$selected_dir"
|
||||||
|
;;
|
||||||
|
0|"")
|
||||||
|
# Continue
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Invalid option${NC}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
;;
|
;;
|
||||||
|
|
||||||
0)
|
0)
|
||||||
@@ -2177,6 +2336,105 @@ scanner_settings() {
|
|||||||
read -p "Press Enter to continue..."
|
read -p "Press Enter to continue..."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Generate client-facing security report
|
||||||
|
generate_client_report() {
|
||||||
|
local scan_dir="$1"
|
||||||
|
|
||||||
|
if [ ! -d "$scan_dir" ]; then
|
||||||
|
echo -e "${RED}Scan directory not found${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local summary_file="$scan_dir/results/summary.txt"
|
||||||
|
local infected_file="$scan_dir/results/infected_files.txt"
|
||||||
|
local clamav_log="$scan_dir/logs/clamav.log"
|
||||||
|
local session_log="$scan_dir/logs/session.log"
|
||||||
|
local report_file="$scan_dir/results/client_report.txt"
|
||||||
|
|
||||||
|
if [ ! -f "$summary_file" ]; then
|
||||||
|
echo -e "${RED}Summary file not found - scan may not be complete${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract scan info
|
||||||
|
local session_name=$(basename "$scan_dir")
|
||||||
|
local scan_date=$(grep "Started:" "$summary_file" | head -1 | sed 's/Started: //')
|
||||||
|
local scan_paths=$(sed -n '/^Paths:/,/^$/p' "$summary_file" | tail -n +2 | grep -v "^$" | tr '\n' ', ' | sed 's/, $//')
|
||||||
|
|
||||||
|
# Count threats
|
||||||
|
local total_threats=0
|
||||||
|
local imunify_count=$(grep -o "ImunifyAV:.*[0-9]* threats" "$summary_file" | grep -o "[0-9]*" || echo "0")
|
||||||
|
local clamav_count=$(grep -o "ClamAV:.*[0-9]* infected" "$summary_file" | grep -o "[0-9]*" || echo "0")
|
||||||
|
local maldet_hits=$(grep -o "Maldet:.*[0-9]* hits" "$summary_file" | grep -o "[0-9]*" || echo "0")
|
||||||
|
|
||||||
|
# Calculate total (only real malware, not rootkit warnings)
|
||||||
|
total_threats=$((imunify_count + clamav_count + maldet_hits))
|
||||||
|
|
||||||
|
# Analyze infected files for false positives
|
||||||
|
local real_threats=()
|
||||||
|
local false_positives=()
|
||||||
|
|
||||||
|
if [ -f "$infected_file" ] && [ -s "$infected_file" ]; then
|
||||||
|
while IFS= read -r file; do
|
||||||
|
# Check if likely false positive (logs, stats, cache)
|
||||||
|
if [[ "$file" =~ /logs?/.*\.(log|gz|bz2)$ ]] || \
|
||||||
|
[[ "$file" =~ /awstats/ ]] || \
|
||||||
|
[[ "$file" =~ /tmp/.*\.txt$ ]] || \
|
||||||
|
[[ "$file" =~ \.log\.[0-9]+$ ]]; then
|
||||||
|
false_positives+=("$file")
|
||||||
|
else
|
||||||
|
real_threats+=("$file")
|
||||||
|
fi
|
||||||
|
done < "$infected_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate report
|
||||||
|
{
|
||||||
|
echo "MALWARE SCAN REPORT - $scan_date"
|
||||||
|
echo "═══════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo "Scanned with: ImunifyAV, ClamAV, Linux Maldet, RKHunter"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ ${#real_threats[@]} -eq 0 ]; then
|
||||||
|
echo "RESULT: ✅ No malware found - your server is clean"
|
||||||
|
else
|
||||||
|
echo "RESULT: ⚠️ ${#real_threats[@]} infected file(s) detected"
|
||||||
|
echo ""
|
||||||
|
echo "INFECTED FILES:"
|
||||||
|
for file in "${real_threats[@]}"; do
|
||||||
|
echo " • $file"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
echo "NEXT STEPS:"
|
||||||
|
echo " 1. Remove infected files immediately"
|
||||||
|
echo " 2. Change all passwords"
|
||||||
|
echo " 3. Update WordPress/plugins to latest versions"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${#false_positives[@]} -gt 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "───────────────────────────────────────────────────────────"
|
||||||
|
echo "NOTE: Attack attempts were detected in your server logs."
|
||||||
|
echo "These were successfully blocked. No action needed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Scan ID: $session_name"
|
||||||
|
} > "$report_file"
|
||||||
|
|
||||||
|
# Display the report
|
||||||
|
echo ""
|
||||||
|
print_header "Client Security Report Generated"
|
||||||
|
echo ""
|
||||||
|
cat "$report_file"
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}Report saved to:${NC} $report_file"
|
||||||
|
echo ""
|
||||||
|
echo "You can now copy/paste this report into your support ticket."
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
# Main execution
|
# Main execution
|
||||||
main() {
|
main() {
|
||||||
if ! detect_scanners; then
|
if ! detect_scanners; then
|
||||||
|
|||||||
Reference in New Issue
Block a user