| Server IP : 146.190.157.162 / Your IP : 216.73.217.6 Web Server : Apache System : Linux ubuntu-s-2vcpu-4gb-amd-sfo3-01-KIT-DIGITAL 6.5.0-44-generic #44-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 7 15:10:09 UTC 2024 x86_64 User : businessweek ( 639) PHP Version : 8.2.10-2ubuntu2.2 Disable Function : exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_signal,pcntl_signal_dispatch,pcntl_getpriority,pcntl_setpriority,dl,putenv,parse_ini_file,show_source MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/html/ansiosos/ |
Upload File : |
#!/bin/bash
# =============================================================================
# clean_wp_malware.sh
# Limpia inyecciones maliciosas de redirección en archivos PHP de WordPress.
#
# Detecta y elimina DOS variantes del patrón:
#
# Variante A (con ob_start):
# ob_start();
# <script>window.location.href = "//ushort.info/...";</script>
# (repetido N veces)
#
# Variante B (solo script tags):
# <script>window.location.href = "//ushort.info/...";</script>
# (repetido N veces, sin ob_start)
#
# USO:
# ./clean_wp_malware.sh [OPCIONES] /ruta/al/sitio/wp
#
# OPCIONES:
# -d, --dry-run Solo muestra los archivos afectados, sin modificar nada
# -b, --backup Crea un .bak de cada archivo antes de limpiarlo
# -l, --log FILE Guarda el log en FILE (default: ./malware_clean.log)
# -h, --help Muestra esta ayuda
#
# EJEMPLOS:
# ./clean_wp_malware.sh --dry-run /var/www/html/misite
# ./clean_wp_malware.sh --backup /var/www/html/misite
# ./clean_wp_malware.sh -b -l /tmp/limpieza.log /var/www/html/misite
# =============================================================================
set -euo pipefail
# --- Defaults ---
DRY_RUN=false
BACKUP=false
LOG_FILE="./malware_clean.log"
TARGET_DIR=""
# --- Colores ---
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# --- Ayuda ---
usage() {
sed -n '/^# USO:/,/^# =====/p' "$0" | grep -v "^# ====" | sed 's/^# //'
exit 0
}
# --- Parse argumentos ---
while [[ $# -gt 0 ]]; do
case "$1" in
-d|--dry-run) DRY_RUN=true; shift ;;
-b|--backup) BACKUP=true; shift ;;
-l|--log) LOG_FILE="$2"; shift 2 ;;
-h|--help) usage ;;
-*) echo "Opción desconocida: $1"; usage ;;
*) TARGET_DIR="$1"; shift ;;
esac
done
if [[ -z "$TARGET_DIR" ]]; then
echo -e "${RED}Error: falta el directorio objetivo.${NC}"
usage
fi
if [[ ! -d "$TARGET_DIR" ]]; then
echo -e "${RED}Error: '$TARGET_DIR' no es un directorio válido.${NC}"
exit 1
fi
# --- Init log ---
echo "=== clean_wp_malware.sh ===" | tee "$LOG_FILE"
echo "Fecha : $(date '+%Y-%m-%d %H:%M:%S')" | tee -a "$LOG_FILE"
echo "Dir : $TARGET_DIR" | tee -a "$LOG_FILE"
echo "Dry-run : $DRY_RUN" | tee -a "$LOG_FILE"
echo "Backup : $BACKUP" | tee -a "$LOG_FILE"
echo "Log : $LOG_FILE" | tee -a "$LOG_FILE"
echo "-------------------------------------------" | tee -a "$LOG_FILE"
FOUND=0
CLEANED=0
ERRORS=0
# =============================================================================
# Función principal: procesa un archivo
# =============================================================================
process_file() {
local file="$1"
# Detectar cualquiera de las dos variantes:
# Variante A: ob_start(); + script tags maliciosos
# Variante B: script tags maliciosos solos (sin ob_start)
# Basta con que aparezca la URL maliciosa en un script tag.
if ! grep -qP '<script>\s*window\.location\.href\s*=\s*"//ushort\.info/' "$file" 2>/dev/null; then
return
fi
((FOUND++)) || true
echo -e "${YELLOW}[INFECTADO]${NC} $file" | tee -a "$LOG_FILE"
if $DRY_RUN; then
return
fi
# Backup opcional
if $BACKUP; then
cp "$file" "${file}.bak" && \
echo " → Backup: ${file}.bak" | tee -a "$LOG_FILE"
fi
# -------------------------------------------------------------------------
# Limpieza con Python (más confiable que sed para bloques multi-línea).
#
# Variante A: ob_start(); seguido de N script tags → se elimina todo
# Variante B: N script tags solos (sin ob_start) → se eliminan los tags
#
# Ambos patrones pueden coexistir en el mismo archivo.
# -------------------------------------------------------------------------
python3 - "$file" <<'PYEOF'
import sys
import re
filepath = sys.argv[1]
with open(filepath, 'rb') as f:
raw = f.read()
# Decodificar con latin-1 para no perder bytes en archivos con codificación mixta
text = raw.decode('latin-1')
# El archivo tiene line endings MIXTOS: CRLF (\r\n) en el código PHP
# y LF (\n) en las líneas maliciosas inyectadas.
# Normalizamos TODO a LF para que los patrones multi-línea funcionen,
# y recordamos si había CRLF para restaurarlo al escribir.
had_crlf = '\r\n' in text
text = text.replace('\r\n', '\n')
# ------------------------------------------------------------------
# Patrón base: 1..N script tags maliciosos consecutivos (con LF)
# Acepta cualquier URL bajo ushort.info (no solo la conocida)
# ------------------------------------------------------------------
SCRIPT_TAG = r'<script>\s*window\.location\.href\s*=\s*"//ushort\.info/[^"]*"\s*;\s*</script>'
SCRIPT_BLOCK = r'(?:' + SCRIPT_TAG + r'\n?)*' + SCRIPT_TAG # último tag sin \n obligatorio
# Variante A: ob_start(); inmediatamente antes de los script tags
pattern_a = re.compile(
r'[ \t]*ob_start\(\);[ \t]*\n?' + SCRIPT_BLOCK,
re.MULTILINE
)
# Variante B: script tags solos (con o sin newline al final)
pattern_b = re.compile(
r'\n?[ \t]*' + SCRIPT_BLOCK,
re.MULTILINE
)
total = 0
cleaned, n = re.subn(pattern_a, '', text); total += n
cleaned, n = re.subn(pattern_b, '', cleaned); total += n
if total == 0:
print(f" → AVISO: patrón no removido con regex en {filepath}", file=sys.stderr)
sys.exit(1)
# Dejar el archivo con exactamente un newline al final
cleaned = cleaned.rstrip('\n') + '\n'
# Restaurar CRLF si el archivo original lo usaba
if had_crlf:
cleaned = cleaned.replace('\n', '\r\n')
with open(filepath, 'wb') as f:
f.write(cleaned.encode('latin-1'))
print(f" → Bloques eliminados: {total}")
PYEOF
local exit_code=$?
if [[ $exit_code -eq 0 ]]; then
((CLEANED++)) || true
echo -e " ${GREEN}✓ Limpio${NC}" | tee -a "$LOG_FILE"
else
((ERRORS++)) || true
echo -e " ${RED}✗ Error al limpiar${NC}" | tee -a "$LOG_FILE"
fi
}
# =============================================================================
# Recorrer todos los .php recursivamente
# =============================================================================
while IFS= read -r -d '' phpfile; do
process_file "$phpfile"
done < <(find "$TARGET_DIR" -type f -name "*.php" -print0)
# --- Resumen ---
echo "-------------------------------------------" | tee -a "$LOG_FILE"
echo -e "${CYAN}Resumen:${NC}" | tee -a "$LOG_FILE"
echo " Archivos infectados encontrados : $FOUND" | tee -a "$LOG_FILE"
if $DRY_RUN; then
echo -e " ${YELLOW}(Modo dry-run: no se modificó nada)${NC}" | tee -a "$LOG_FILE"
else
echo " Archivos limpiados : $CLEANED" | tee -a "$LOG_FILE"
echo " Errores : $ERRORS" | tee -a "$LOG_FILE"
fi
echo "Log guardado en: $LOG_FILE"
if [[ $FOUND -eq 0 ]]; then
echo -e "${GREEN}✓ No se encontraron archivos infectados.${NC}"
elif $DRY_RUN; then
echo -e "${YELLOW}Correlo sin --dry-run para limpiar.${NC}"
elif [[ $ERRORS -eq 0 ]]; then
echo -e "${GREEN}✓ Limpieza completada sin errores.${NC}"
else
echo -e "${RED}✗ Algunos archivos tuvieron errores. Revisá el log.${NC}"
exit 1
fi