| Linux webm007.cluster106.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64 Path : /home/eglisebaa/www/.malware-scripts/ |
| Current File : /home/eglisebaa/www/.malware-scripts/surveillance-wp.sh |
#!/usr/bin/env bash
#
# Surveillance d'intégrité WordPress par baseline (empreintes MD5 + mtime).
# À exécuter sur le serveur depuis la racine WordPress (ou avec WP_ROOT défini).
#
# Usage:
# ./surveillance-wp.sh baseline [--full] # Créer la baseline (une fois après nettoyage)
# ./surveillance-wp.sh check # Comparer à la baseline, générer rapport
#
# Baseline stockée dans WP_ROOT/.malware-scripts/baseline/
# Rapports dans WP_ROOT/wp-surveillance/
#
set -e
WP_ROOT="${WP_ROOT:-/home/eglisebaa/www}"
BASELINE_DIR="${WP_ROOT}/.malware-scripts/baseline"
REPORT_DIR="${WP_ROOT}/wp-surveillance"
REPORT_FILE=""
CHANGES=0
cd "$WP_ROOT"
if [ ! -f "wp-includes/version.php" ]; then
echo "Erreur : racine WordPress introuvable (wp-includes/version.php). Définir WP_ROOT si besoin."
exit 1
fi
mkdir -p "$BASELINE_DIR"
mkdir -p "$REPORT_DIR"
# Séparateur dans les fichiers baseline : chemin|md5|mtime (relatif à WP_ROOT)
_line_hash() {
local f="$1"
local rel="${f#./}"
if [ ! -f "$f" ]; then
return 1
fi
if [ -r "$f" ]; then
local h
local m
h=$(md5sum "$f" 2>/dev/null | awk '{print $1}' || md5 -q "$f" 2>/dev/null)
m=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f" 2>/dev/null)
echo "${rel}|${h}|${m}"
fi
}
# ----- baseline -----
cmd_baseline() {
local full=0
[ "$1" = "--full" ] && full=1
echo "Création de la baseline (WP_ROOT=$WP_ROOT)"
echo " - Core + racine"
> "$BASELINE_DIR/baseline-core.txt"
local core_files="index.php wp-blog-header.php wp-load.php wp-settings.php .htaccess wp-login.php wp-config.php"
for f in $core_files; do
if [ -f "$f" ]; then
_line_hash "$f" >> "$BASELINE_DIR/baseline-core.txt"
fi
done
while IFS= read -r -d '' f; do
[ -f "$f" ] && _line_hash "$f" >> "$BASELINE_DIR/baseline-core.txt"
done < <(find . -maxdepth 1 -type f -name "*.php" -print0 2>/dev/null)
sort -u "$BASELINE_DIR/baseline-core.txt" -o "$BASELINE_DIR/baseline-core.txt"
echo " - wp-content/uploads"
> "$BASELINE_DIR/baseline-uploads.txt"
if [ -d "wp-content/uploads" ]; then
while IFS= read -r -d '' f; do
_line_hash "$f" >> "$BASELINE_DIR/baseline-uploads.txt"
done < <(find wp-content/uploads -type f -print0 2>/dev/null)
sort -u "$BASELINE_DIR/baseline-uploads.txt" -o "$BASELINE_DIR/baseline-uploads.txt"
fi
if [ "$full" -eq 1 ]; then
echo " - wp-content/plugins et themes (--full)"
> "$BASELINE_DIR/baseline-full.txt"
for dir in wp-content/plugins wp-content/themes; do
[ ! -d "$dir" ] && continue
while IFS= read -r -d '' f; do
_line_hash "$f" >> "$BASELINE_DIR/baseline-full.txt"
done < <(find "$dir" -type f -name "*.php" -print0 2>/dev/null)
done
sort -u "$BASELINE_DIR/baseline-full.txt" -o "$BASELINE_DIR/baseline-full.txt"
else
rm -f "$BASELINE_DIR/baseline-full.txt"
fi
echo "Baseline enregistrée dans $BASELINE_DIR"
}
# ----- check : compare et rapport -----
_report() {
echo "$1" >> "$REPORT_FILE"
}
_check_file() {
local path="$1"
local old_md5="$2"
local old_mtime="$3"
if [ ! -f "$WP_ROOT/$path" ]; then
_report " SUPPRIMÉ: $path"
CHANGES=1
return
fi
local new_hash new_mtime
new_hash=$(md5sum "$WP_ROOT/$path" 2>/dev/null | awk '{print $1}' || md5 -q "$WP_ROOT/$path" 2>/dev/null)
new_mtime=$(stat -c %Y "$WP_ROOT/$path" 2>/dev/null || stat -f %m "$WP_ROOT/$path" 2>/dev/null)
if [ "$new_hash" != "$old_md5" ] || [ "$new_mtime" != "$old_mtime" ]; then
_report " MODIFIÉ: $path (ancien md5=$old_md5, nouveau=$new_hash)"
CHANGES=1
fi
}
_check_baseline_file() {
local file="$1"
local name="$2"
[ ! -f "$file" ] && return
_report ""
_report "--- $name ---"
while IFS='|' read -r path old_md5 old_mtime; do
[ -z "$path" ] && continue
_check_file "$path" "$old_md5" "$old_mtime"
done < "$file"
}
_check_added_uploads() {
[ ! -f "$BASELINE_DIR/baseline-uploads.txt" ] && return
local in_baseline
in_baseline=$(mktemp)
cut -d'|' -f1 "$BASELINE_DIR/baseline-uploads.txt" | sort -u > "$in_baseline"
_report ""
_report "--- Fichiers ajoutés (uploads) ---"
find wp-content/uploads -type f 2>/dev/null | sort | while read -r f; do
if ! grep -qFx "$f" "$in_baseline"; then
_report " AJOUTÉ: $f"
CHANGES=1
fi
done
rm -f "$in_baseline"
}
_check_added_root_php() {
_report ""
_report "--- Fichiers PHP ajoutés (racine) ---"
local in_baseline
in_baseline=$(mktemp)
cut -d'|' -f1 "$BASELINE_DIR/baseline-core.txt" | sort -u > "$in_baseline"
find . -maxdepth 1 -type f -name "*.php" 2>/dev/null | sed 's|^\./||' | sort -u | while read -r f; do
if ! grep -qFx "$f" "$in_baseline"; then
_report " AJOUTÉ: $f"
CHANGES=1
fi
done
rm -f "$in_baseline"
}
cmd_check() {
if [ ! -f "$BASELINE_DIR/baseline-core.txt" ]; then
echo "Erreur : aucune baseline trouvée. Exécutez d'abord : $0 baseline"
exit 1
fi
REPORT_FILE="$REPORT_DIR/wp-surveillance-$(date +%Y%m%d-%H%M%S).txt"
CHANGES=0
{
echo "Rapport de surveillance WordPress"
echo "Date: $(date)"
echo "WP_ROOT: $WP_ROOT"
echo "Comparaison à la baseline dans $BASELINE_DIR"
} > "$REPORT_FILE"
_check_baseline_file "$BASELINE_DIR/baseline-core.txt" "Core et racine"
_check_added_root_php
_check_baseline_file "$BASELINE_DIR/baseline-uploads.txt" "wp-content/uploads"
_check_added_uploads
if [ -f "$BASELINE_DIR/baseline-full.txt" ]; then
_check_baseline_file "$BASELINE_DIR/baseline-full.txt" "Plugins et thèmes (--full)"
fi
# Recompter les changements (certains sont détectés dans des sous-shells)
if grep -qE 'MODIFIÉ|SUPPRIMÉ|AJOUTÉ' "$REPORT_FILE" 2>/dev/null; then
CHANGES=1
fi
if [ $CHANGES -eq 0 ]; then
_report ""
_report "Aucun changement détecté."
echo "Aucun changement. Rapport: $REPORT_FILE"
exit 0
fi
_report ""
_report "--- Fin du rapport ---"
echo "Changements détectés. Rapport: $REPORT_FILE"
cat "$REPORT_FILE"
exit 1
}
# ----- main -----
case "${1:-}" in
baseline)
cmd_baseline "${2:-}"
;;
check)
cmd_check
;;
*)
echo "Usage: $0 baseline [--full] | check"
echo " baseline Créer la baseline (après nettoyage / restauration backup)"
echo " baseline --full Inclure plugins et thèmes"
echo " check Comparer à la baseline et générer un rapport"
exit 1
;;
esac