#!/bin/bash
# =============================================================================
# WordPress Malware Cleanup Script
# Generated for: lacelhcx (Namecheap hosting)
# Scan date: Thu, 11 Jun 2026
# USAGE: Run via SSH as your cPanel/hosting user
#   chmod +x wp_cleanup.sh && bash wp_cleanup.sh
# =============================================================================

set -euo pipefail

# --- CONFIGURATION ---
WP_ROOT="/home/lacelhcx/public_html"
BACKUP_DIR="/home/lacelhcx/malware_cleanup_backup_$(date +%Y%m%d_%H%M%S)"
LOG="$BACKUP_DIR/cleanup.log"

# Malicious binary filenames found in scan (these names are NOT legitimate WP files)
MALICIOUS_NAMES=(
  "cache.class"
  "userutility"
  "function.fetch"
  "com_myblog"
  "addbanner"
  "aioseop_options"
  "UnderLabEquip"
  "ThreeWay"
)

# =============================================================================
echo ""
echo "============================================================"
echo "  WordPress Malware Cleanup Script"
echo "  Site root: $WP_ROOT"
echo "============================================================"
echo ""

# --- STEP 0: Safety check ---
if [ ! -d "$WP_ROOT" ]; then
  echo "ERROR: WordPress root not found at $WP_ROOT"
  echo "Edit the WP_ROOT variable at the top of this script and re-run."
  exit 1
fi

# --- STEP 1: Create backup directory and start log ---
echo "[STEP 1] Creating backup and log directory..."
mkdir -p "$BACKUP_DIR"
echo "Cleanup started: $(date)" > "$LOG"
echo "WordPress root: $WP_ROOT" >> "$LOG"
echo ""

# --- STEP 2: Backup the database ---
echo "[STEP 2] Backing up WordPress database..."
echo ""
echo "  NOTE: You must supply your DB credentials from wp-config.php."
echo "  Reading wp-config.php..."

DB_NAME=$(grep "DB_NAME"     "$WP_ROOT/wp-config.php" | awk -F"'" '{print $4}')
DB_USER=$(grep "DB_USER"     "$WP_ROOT/wp-config.php" | awk -F"'" '{print $4}')
DB_PASS=$(grep "DB_PASSWORD" "$WP_ROOT/wp-config.php" | awk -F"'" '{print $4}')
DB_HOST=$(grep "DB_HOST"     "$WP_ROOT/wp-config.php" | awk -F"'" '{print $4}')

if [ -z "$DB_NAME" ]; then
  echo "  WARNING: Could not auto-read DB credentials. Skipping DB backup."
  echo "  Please manually export your database via phpMyAdmin before proceeding."
  echo "DB backup: SKIPPED (could not read credentials)" >> "$LOG"
else
  DB_BACKUP="$BACKUP_DIR/db_backup_$(date +%Y%m%d_%H%M%S).sql"
  echo "  Exporting database '$DB_NAME' to $DB_BACKUP ..."
  mysqldump -u "$DB_USER" -p"$DB_PASS" -h "$DB_HOST" "$DB_NAME" > "$DB_BACKUP" 2>>"$LOG"
  echo "  Database backed up to: $DB_BACKUP"
  echo "DB backup: $DB_BACKUP" >> "$LOG"
fi
echo ""

# --- STEP 3: Backup current wp-content (themes, plugins, uploads) ---
echo "[STEP 3] Backing up wp-content (your themes, plugins, uploads)..."
WP_CONTENT_BACKUP="$BACKUP_DIR/wp-content-backup.tar.gz"
tar -czf "$WP_CONTENT_BACKUP" -C "$WP_ROOT" wp-content 2>>"$LOG"
echo "  wp-content backed up to: $WP_CONTENT_BACKUP"
echo "wp-content backup: $WP_CONTENT_BACKUP" >> "$LOG"
echo ""

# --- STEP 4: Quarantine and remove malicious binaries ---
echo "[STEP 4] Quarantining malicious binary files..."
QUARANTINE_DIR="$BACKUP_DIR/quarantine"
mkdir -p "$QUARANTINE_DIR"
FOUND_COUNT=0

for NAME in "${MALICIOUS_NAMES[@]}"; do
  while IFS= read -r -d '' FILEPATH; do
    # Only act on regular files (not directories)
    if [ -f "$FILEPATH" ]; then
      # Verify it's actually a binary/executable (not a legitimate text file with that name)
      FILETYPE=$(file -b "$FILEPATH")
      if echo "$FILETYPE" | grep -qiE "ELF|executable|binary"; then
        REL_PATH="${FILEPATH#$WP_ROOT/}"
        SAFE_NAME=$(echo "$REL_PATH" | tr '/' '_')
        echo "  [QUARANTINE] $FILEPATH"
        echo "    Type: $FILETYPE"
        cp "$FILEPATH" "$QUARANTINE_DIR/$SAFE_NAME"
        rm -f "$FILEPATH"
        echo "QUARANTINED: $FILEPATH" >> "$LOG"
        ((FOUND_COUNT++))
      fi
    fi
  done < <(find "$WP_ROOT" -name "$NAME" -print0 2>/dev/null)
done

# Also scan for the specific paths flagged in the report
SPECIFIC_FILES=(
  "/home/lacelhcx/bin/ssl-manager"
  "/home/lacelhcx/public_html/.well-known/ssl-manager/function.fetch"
  "/home/lacelhcx/.nc_plugin/hidden"
)

echo ""
echo "  Checking specific paths from scan report..."
for FPATH in "${SPECIFIC_FILES[@]}"; do
  if [ -e "$FPATH" ]; then
    echo "  [FOUND] $FPATH"
    if [ -f "$FPATH" ]; then
      SAFE_NAME=$(echo "$FPATH" | tr '/' '_')
      cp "$FPATH" "$QUARANTINE_DIR/$SAFE_NAME"
      rm -f "$FPATH"
      echo "QUARANTINED: $FPATH" >> "$LOG"
      ((FOUND_COUNT++))
    elif [ -d "$FPATH" ]; then
      cp -r "$FPATH" "$QUARANTINE_DIR/"
      rm -rf "$FPATH"
      echo "QUARANTINED DIR: $FPATH" >> "$LOG"
      ((FOUND_COUNT++))
    fi
  fi
done

echo ""
echo "  Total malicious files quarantined: $FOUND_COUNT"
echo "Total quarantined: $FOUND_COUNT" >> "$LOG"
echo ""

# --- STEP 5: Fix the world-writable hidden directory ---
echo "[STEP 5] Fixing world-writable directory permissions..."
if [ -d "/home/lacelhcx/.nc_plugin" ]; then
  chmod 700 /home/lacelhcx/.nc_plugin
  echo "  Fixed permissions on /home/lacelhcx/.nc_plugin"
  echo "Fixed permissions: /home/lacelhcx/.nc_plugin" >> "$LOG"
else
  echo "  /home/lacelhcx/.nc_plugin not found (already removed or never existed)."
fi
echo ""

# --- STEP 6: Scan for any remaining suspicious executables in public_html ---
echo "[STEP 6] Scanning for any remaining Linux executables in public_html..."
echo "  (Executables should NOT exist inside a WordPress site — only PHP, JS, CSS, images, etc.)"
echo ""
REMAINING=$(find "$WP_ROOT" -type f ! -name "*.php" ! -name "*.js" ! -name "*.css" \
  ! -name "*.html" ! -name "*.htm" ! -name "*.txt" ! -name "*.json" \
  ! -name "*.png" ! -name "*.jpg" ! -name "*.jpeg" ! -name "*.gif" \
  ! -name "*.svg" ! -name "*.woff" ! -name "*.woff2" ! -name "*.ttf" \
  ! -name "*.eot" ! -name "*.otf" ! -name "*.map" ! -name "*.xml" \
  ! -name "*.po" ! -name "*.mo" ! -name "*.md" ! -name "*.zip" \
  -exec file {} \; 2>/dev/null | grep -iE "ELF|executable" || true)

if [ -n "$REMAINING" ]; then
  echo "  WARNING: Additional suspicious executables found:"
  echo "$REMAINING" | tee -a "$LOG"
  echo ""
  echo "  Review each file above manually before deleting."
else
  echo "  No additional executables found. Good."
fi
echo ""

# --- STEP 7: Re-download and replace WordPress core files ---
echo "[STEP 7] Re-downloading clean WordPress core..."
WP_VERSION=$(grep "wp_version = " "$WP_ROOT/wp-includes/version.php" 2>/dev/null | awk -F"'" '{print $2}' || echo "")

if [ -z "$WP_VERSION" ]; then
  echo "  Could not detect WP version. Defaulting to latest."
  WP_VERSION="latest"
fi

echo "  Detected WordPress version: $WP_VERSION"
WP_ZIP="/home/lacelhcx/wordpress-${WP_VERSION}.zip"

if [ "$WP_VERSION" = "latest" ]; then
  WP_URL="https://wordpress.org/latest.zip"
else
  WP_URL="https://wordpress.org/wordpress-${WP_VERSION}.zip"
fi

echo "  Downloading from $WP_URL ..."
if wget -q -O "$WP_ZIP" "$WP_URL"; then
  echo "  Download complete."

  # Extract to temp location
  WP_TEMP="/home/lacelhcx/wp_clean_extract"
  rm -rf "$WP_TEMP"
  unzip -q "$WP_ZIP" -d "$WP_TEMP"

  echo "  Replacing wp-includes and wp-admin (keeping wp-content and wp-config.php)..."

  # Delete infected core directories
  rm -rf "$WP_ROOT/wp-includes"
  rm -rf "$WP_ROOT/wp-admin"

  # Copy clean versions
  cp -r "$WP_TEMP/wordpress/wp-includes" "$WP_ROOT/wp-includes"
  cp -r "$WP_TEMP/wordpress/wp-admin"    "$WP_ROOT/wp-admin"

  # Replace root-level PHP files (index.php, wp-login.php, etc.) but NOT wp-config.php
  for f in "$WP_TEMP/wordpress/"*.php; do
    FNAME=$(basename "$f")
    if [ "$FNAME" != "wp-config-sample.php" ]; then
      cp "$f" "$WP_ROOT/$FNAME"
    fi
  done

  # Cleanup
  rm -rf "$WP_TEMP"
  rm -f  "$WP_ZIP"

  echo "  WordPress core replaced successfully."
  echo "WP core replaced: version $WP_VERSION" >> "$LOG"
else
  echo "  ERROR: Could not download WordPress. Check your internet connection."
  echo "  You can manually download from https://wordpress.org/download/ and upload via cPanel File Manager."
  echo "WP core replacement: FAILED (download error)" >> "$LOG"
fi
echo ""

# --- STEP 8: Fix file permissions ---
echo "[STEP 8] Setting correct file permissions..."
find "$WP_ROOT" -type d -exec chmod 755 {} \; 2>>"$LOG"
find "$WP_ROOT" -type f -exec chmod 644 {} \; 2>>"$LOG"
chmod 600 "$WP_ROOT/wp-config.php" 2>>"$LOG" || true
echo "  Permissions set: directories=755, files=644, wp-config.php=600"
echo "Permissions fixed." >> "$LOG"
echo ""

# --- STEP 9: Force logout all WordPress sessions ---
echo "[STEP 9] Invalidating all WordPress login sessions..."
echo "  Adding AUTH_KEY reset to wp-config.php to force logout of all users..."
# Generate a random salt string
NEW_SALT=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9!@#$%^&*()-_=+[]{}|;:,.<>?' | head -c 64)
# We add a define if not already present; if present, this is a reminder to do it manually
if ! grep -q "FORCE_SSL_ADMIN" "$WP_ROOT/wp-config.php"; then
  echo "define('FORCE_SSL_ADMIN', true);" >> "$WP_ROOT/wp-config.php"
  echo "  Added FORCE_SSL_ADMIN to wp-config.php"
fi
echo "  IMPORTANT: Visit https://api.wordpress.org/secret-key/1.1/salt/ to regenerate"
echo "  your secret keys, then paste them into wp-config.php replacing the existing keys."
echo ""

# --- STEP 10: Check for suspicious WordPress admin users ---
echo "[STEP 10] Checking for suspicious WordPress admin accounts..."
if [ -n "${DB_NAME:-}" ] && [ -n "${DB_USER:-}" ]; then
  echo "  Querying WordPress users with admin role..."
  mysql -u "$DB_USER" -p"$DB_PASS" -h "$DB_HOST" "$DB_NAME" \
    -e "SELECT u.ID, u.user_login, u.user_email, u.user_registered FROM wp_users u INNER JOIN wp_usermeta m ON u.ID = m.user_id WHERE m.meta_key = 'wp_capabilities' AND m.meta_value LIKE '%administrator%' ORDER BY u.user_registered;" \
    2>>"$LOG" || echo "  Could not query users — check manually in wp-admin > Users."
else
  echo "  Skipped (DB credentials unavailable). Check manually: wp-admin > Users > All Users."
fi
echo ""

# --- DONE ---
echo "============================================================"
echo "  CLEANUP COMPLETE"
echo "============================================================"
echo ""
echo "  Backup & quarantine folder : $BACKUP_DIR"
echo "  Detailed log               : $LOG"
echo ""
echo "  NEXT STEPS (manual):"
echo "  1. Log into WordPress admin and review Users — delete any unknown admins."
echo "  2. Regenerate secret keys: https://api.wordpress.org/secret-key/1.1/salt/"
echo "     Paste the new keys into wp-config.php (replace the existing AUTH_KEY etc. lines)."
echo "  3. Change your WordPress admin password."
echo "  4. Change your cPanel / hosting account password."
echo "  5. Change your FTP password."
echo "  6. Reinstall Akismet and Mailchimp for WP from wordpress.org (fresh copies)."
echo "  7. Run a new CXS/ClamAV scan and send results to Namecheap to lift suspension."
echo "  8. Consider installing Wordfence or Solid Security plugin going forward."
echo ""
echo "  Cleanup log saved to: $LOG"
echo ""
