#!/usr/bin/env bash
# wp-entry-forensics.sh, methodical access-log forensics for finding the entry vector
# of a WordPress compromise. Reports only; does NOT modify anything.
# Source: https://techearl.com/wordpress-entry-point-log-forensics
# Site:   https://techearl.com/
#
# Usage:
#   ./wp-entry-forensics.sh /path/to/wordpress /path/to/access.log [YYYY-MM-DD-of-symptoms]

set -e
WP_ROOT="${1:?Usage: $0 <wp-root> <access-log> [symptom-date]}"
LOG="${2:?Usage: $0 <wp-root> <access-log> [symptom-date]}"
SYMPTOM_DATE="${3:-}"

echo "========================================="
echo "  WordPress Entry-Point Forensics"
echo "  WP root: $WP_ROOT"
echo "  Log:     $LOG"
echo "  Symptom date: ${SYMPTOM_DATE:-<not specified>}"
echo "========================================="

# 1. File modification cluster
echo
echo "--- 1. 20 most-recently-modified PHP files in WordPress directory ---"
if [ "$(uname)" = "Darwin" ]; then
  find "$WP_ROOT" -type f -name '*.php' \
    -exec stat -f '%Sm %N' -t '%Y-%m-%d %H:%M:%S' {} \; 2>/dev/null \
    | sort -r | head -20
else
  find "$WP_ROOT" -type f -name '*.php' -printf '%T+ %p\n' 2>/dev/null \
    | sort -r | head -20
fi

# 2. XML-RPC brute force
echo
echo "--- 2. Top XML-RPC POST sources (credential stuffing target) ---"
grep -E 'POST .*/xmlrpc\.php' "$LOG" 2>/dev/null \
  | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

# 3. wp-login.php brute force
echo
echo "--- 3. Top wp-login.php POST sources ---"
grep -E 'POST .*/wp-login\.php' "$LOG" 2>/dev/null \
  | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

# 4. PHP files served from wp-content/uploads (red flag)
echo
echo "--- 4. PHP files in wp-content/uploads/ ---"
grep -E 'GET|POST .*/wp-content/uploads/.*\.php' "$LOG" 2>/dev/null \
  | awk '{print $1, $4, $6, $7, $9}' | head -20

# 5. Suspicious admin-ajax.php actions (often plugin AJAX exploits)
echo
echo "--- 5. admin-ajax.php request volume by action ---"
grep -aE 'admin-ajax\.php\?action=' "$LOG" 2>/dev/null \
  | sed -E 's/.*action=([^& "]+).*/\1/' | sort | uniq -c | sort -rn | head -20

# 6. Known-CVE plugin endpoint probes
echo
echo "--- 6. Known plugin-CVE entry patterns ---"
echo "  LayerSlider CVE-2024-2879 (ls_get_popup_markup):"
grep -c 'ls_get_popup_markup' "$LOG" 2>/dev/null || echo "  0"
echo "  Bricks Builder CVE-2024-25600 (/bricks/v1/render_element):"
grep -c '/bricks/v1' "$LOG" 2>/dev/null || echo "  0"
echo "  LiteSpeed-related requests:"
grep -cE '/litespeed-cache/|action=litespeed' "$LOG" 2>/dev/null || echo "  0"

# 7. REST API exploitation attempts
echo
echo "--- 7. REST API namespaces accessed (unfamiliar ones are suspicious) ---"
grep -aoE '/wp-json/[^ "/]+' "$LOG" 2>/dev/null \
  | sort | uniq -c | sort -rn | head -20

# 8. Server access logs (SSH/FTP) if accessible
echo
echo "--- 8. SSH/FTP authentication ---"
sudo grep -aE 'sshd.*Accepted' /var/log/auth.log /var/log/secure 2>/dev/null \
  | tail -10 || echo "  (auth log not readable; skip on shared hosting)"

echo
echo "========================================="
echo "  Cross-reference section 1 (file mod"
echo "  times) against sections 2-7 (log)."
echo "  The IP / endpoint that appears just"
echo "  before the modification cluster is"
echo "  your entry vector."
echo "========================================="
