Seguridad PrestaShop: La lista de verificación completa
Guía de seguridad para tiendas PrestaShop: protección del servidor, administración segura, auditoría de módulos, base de datos y respuesta a incidentes.
Cómo es realmente una tienda PrestaShop comprometida
La mayoría de las tiendas hackeadas por cuya limpieza nos llamaron desde 2013 se veían perfectas desde la portada. El propietario solo se enteró porque Google marcó el sitio, la pasarela de pago congeló los abonos, o un cliente llamó por una "redirección rara después del checkout". A esas alturas, el atacante normalmente ya llevaba semanas dentro.
Los patrones se repiten. Un módulo de terceros vulnerable filtra la base de datos. Una URL de administración rastreada sufre un ataque de fuerza bruta durante un fin de semana. Un shell PHP disfrazado de imagen aterriza en img/. Una puerta trasera inyecta un robador de tarjetas en order-confirmation.tpl. Ninguno de estos casos es exótico. La lista de verificación de más abajo puede ayudar a reducir estos riesgos.
Esta es la lista de verificación que entregamos a los clientes antes de aceptar gestionar su tienda PrestaShop. Las rutas y las versiones de PHP varían según la versión de PrestaShop, pero los principios de endurecimiento siguen siendo los mismos. Para la versión no técnica, envíe al propietario de la tienda a nuestra guía de seguridad en lenguaje sencillo.
1. Cómo se hackean realmente las tiendas PrestaShop
Inyección SQL en un módulo de terceros
Este es el vector número uno, con diferencia. El núcleo está razonablemente curtido en batalla; los módulos no. Un desarrollador junior publica un controlador frontal que concatena $_GET['id'] directamente en una consulta, un escáner automatizado lo encuentra, y el atacante vuelca ps_customer y ps_orders antes de comer. Lo hemos visto con módulos del marketplace oficial Addons, no solo con los de foros piratas.
Fuerza bruta en la administración
PrestaShop no tiene limitación de tasa nativa en el formulario de inicio de sesión de la administración. Una vez que un atacante conoce su directorio de administración (y lo conocerá, porque la mitad de las tiendas que auditamos siguen usando /admin/ o /admin123/) lanzará miles de intentos de contraseña por minuto. Cualquier cuenta con welcome2024 o el nombre de la tienda cae en cuestión de minutos.
Utiliza límites de intentos de inicio de sesión, bloqueos por IP y alertas ante ataques a cuentas de empleados. Estos controles complementan las contraseñas seguras y el 2FA, pero no los sustituyen.
Subida de archivos a shell PHP
Una subida de "foto de perfil" o "imagen de producto" que no valida el contenido real del archivo, solo la extensión. El atacante sube shell.php.jpg, el servidor está configurado para ejecutar cualquier cosa que coincida con .php en la ruta, y se acabó. La corrección del lado del servidor web (bloquear la ejecución de PHP en img/, upload/, download/) está más abajo, configúrelo una vez y neutralizará toda una clase de módulos defectuosos.
PHP en fin de vida útil y software sin parchear
PHP 7.4 está en fin de vida útil desde noviembre de 2022. Todavía lo vemos en producción. Cada exploit documentado públicamente contra PHP 7.x es una victoria gratis para un atacante, y lo mismo se aplica a MySQL 5.7, Apache 2.2 y PrestaShop 1.7.6 con tres años de CVE sin parchear.
Archivos de configuración expuestos
Un servidor web mal configurado sirve sin problema /.env, /.git/config o /app/config/parameters.php a quien lo pida. Contraseña de la base de datos, clave de cookie, nombre de la carpeta de administración, todo, en texto plano, en una sola petición GET. Ejecutamos esta comprobación en cada tienda que incorporamos.
Dosis de realidad: "Mi tienda es demasiado pequeña para ser un objetivo" es lo que nos dice cada propietario antes de la factura de limpieza. Los escáneres no leen su página "Acerca de", recorren cada dirección IPv4 de internet buscando firmas de PrestaShop. El tamaño es irrelevante.
2. Endurecimiento a nivel de servidor
Versión y configuración de PHP
Ejecute la versión de PHP más reciente que admita su versión de PrestaShop, PHP 8.1+ para PS 8.x, PHP 8.1–8.4 para PS 9.x. Si está atascado en algo anterior a PHP 8.1 por culpa de un módulo, la respuesta es reemplazar el módulo, no quedarse en un PHP en fin de vida útil.
El endurecimiento de php.ini que aplicamos por defecto:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
expose_php = Off
allow_url_include = Off
display_errors = Off
log_errors = On
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1
session.cookie_samesite = Lax
open_basedir = /var/www/html:/tmp:/usr/share/php
Un puñado de módulos (procesadores de imágenes antiguos, algunos generadores de PDF) necesitan de verdad exec(). No vuelva a abrir toda la lista para que funcione un solo módulo. Reactive únicamente la función concreta que pide, registre la decisión, y si puede reemplazar el módulo por uno que no recurra al shell, hágalo en la próxima ventana de mantenimiento.
Permisos de archivos
Los tres números que importan:
- 755 en directorios: el propietario puede escribir, todos pueden listar y recorrer
- 644 en archivos: el propietario puede escribir, todos pueden leer
- 400 en
app/config/parameters.php: solo el propietario puede leerlo. Este archivo contiene las credenciales de su base de datos. Trátelo como una clave privada.
chown -R www-data:www-data /var/www/html/prestashop
find /var/www/html/prestashop -type d -exec chmod 755 {} \\;
find /var/www/html/prestashop -type f -exec chmod 644 {} \\;
chmod 400 /var/www/html/prestashop/app/config/parameters.php
# Directorios con escritura que PrestaShop necesita
chmod -R 775 /var/www/html/prestashop/var/cache
chmod -R 775 /var/www/html/prestashop/var/logs
chmod -R 775 /var/www/html/prestashop/img
chmod -R 775 /var/www/html/prestashop/upload
chmod -R 775 /var/www/html/prestashop/download
Si un tutorial, un artículo de soporte o un servicio de asistencia de hosting le dice que haga chmod 777 a cualquier cosa, ignórelos y busque una fuente mejor. No hay ningún escenario en el que 777 sea la respuesta correcta en una tienda de producción.
SSL/TLS y cabeceras de seguridad
Active SSL en Parámetros de la tienda → General, fuerce la redirección a nivel de servidor web y añada HSTS para que el navegador se niegue a degradar la conexión.
# Apache .htaccess
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Nginx
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
Política de seguridad de contenido (CSP)
La CSP puede amortiguar el impacto de un robador de tarjetas inyectado o de un payload XSS, pero una política estricta en PrestaShop romperá el proceso de compra la primera vez que lo intente. Los widgets de pago, la analítica, el chat, las fuentes y numerosos scripts JavaScript de módulos cargan desde orígenes de terceros. Despliéguela en dos fases:
# Apache: monitorice primero, no aplique de inmediato
Header always set Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; font-src 'self' data: https:; connect-src 'self' https:; frame-src 'self' https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; report-uri /csp-report"
# Nginx: monitorice primero, no aplique de inmediato
add_header Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; font-src 'self' data: https:; connect-src 'self' https:; frame-src 'self' https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; report-uri /csp-report" always;
Déjela en Report-Only durante al menos una semana de tráfico real. Recopile las infracciones, reemplace el comodín https: por los dominios reales de sus proveedores (Stripe, PayPal, Adyen, Klarna, GA, GTM, Hotjar, etc.) y pase a aplicarla solo cuando una prueba completa de compra se complete sin problemas. Mantenga 'unsafe-inline' tanto tiempo como lo necesite su tema. Eliminarlo requiere compatibilidad con nonce o hash en cada plantilla.
Bloquear el listado de directorios y los archivos sensibles
Las reglas de .htaccess que colocamos en la raíz de cada tienda que alojamos:
Options -Indexes
# Bloquear tipos de archivo sensibles
<FilesMatch "\\.(env|yml|yaml|log|sql|bak|old|orig|save|swp|dist|config|ini|phps)$">
Require all denied
</FilesMatch>
# Bloquear archivos y directorios ocultos (.git, .env, etc.)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule (^\\.|/\\.) - [F]
</IfModule>
# Bloquear archivos de composer
<FilesMatch "^(composer\\.json|composer\\.lock)$">
Require all denied
</FilesMatch>
# Bloquear los directorios de configuración, vendor y registros
<IfModule mod_rewrite.c>
RewriteRule ^config/ - [F]
RewriteRule ^vendor/ - [F]
RewriteRule ^var/logs/ - [F]
RewriteRule ^app/config/ - [F]
</IfModule>
# Bloquear la ejecución de PHP en los directorios de subida
<Directory "/var/www/html/prestashop/upload">
<FilesMatch "\\.ph(p[3457]?|t|tml)$">
Require all denied
</FilesMatch>
</Directory>
<Directory "/var/www/html/prestashop/img">
<FilesMatch "\\.ph(p[3457]?|t|tml)$">
Require all denied
</FilesMatch>
</Directory>
Equivalente para Nginx:
location ~* \\.(env|yml|yaml|log|sql|bak|old|swp|dist|config|ini)$ { deny all; return 404; }
location ~ /\\. { deny all; return 404; }
location ~* ^/(upload|img|download)/.*\\.php$ { deny all; return 404; }
location ~* ^/(config|vendor|var/logs|app/config)/ { deny all; return 404; }
autoindex off;
Verifíquelo. Abrahttps://yourshop.com/.envyhttps://yourshop.com/app/config/parameters.phpen una ventana de incógnito tras desplegar. Un 403 o un 404 es lo correcto. Cualquier otra cosa significa que está repartiendo credenciales.
3. Endurecimiento del panel de administración
Ajustes de seguridad en el Back Office de PrestaShop 8.
La protección por token y la política de contraseñas son los dos ajustes de aquí. La protección por token debe permanecer activada; la puntuación de contraseña debe ser de al menos 3.
Renombrar el directorio de administración: correctamente
PrestaShop instala una carpeta de administración aleatoria por defecto. Si la suya sigue siendo /admin/ o cualquier palabra adivinable (/backoffice, /panel, el nombre de la tienda, las iniciales del desarrollador), renómbrela hoy mismo a diez o más caracteres aleatorios:
mv /var/www/html/prestashop/admin /var/www/html/prestashop/admin-x7k9m2p4
rm -rf /var/www/html/prestashop/var/cache/*
No es seguridad por sí misma. Es la diferencia entre estar en la lista de objetivos de todos los escáneres o no estarlo. Marque la nueva URL como favorita, guárdela en su gestor de contraseñas y siga adelante.
Contraseñas fuertes y 2FA: no opcionales
Cada cuenta de administración: 16 caracteres o más, generada por un gestor de contraseñas, nunca reutilizada. PrestaShop 1.7.6 y posteriores admiten TOTP (Google Authenticator, Authy, 1Password, Bitwarden) de forma nativa en Parámetros avanzados → Administración. Actívelo para cada empleado, sin excepciones. Esta única opción bloquea a la inmensa mayoría de los ataques de fuerza bruta y de relleno de credenciales que vemos.
Security Revolution impone el 2FA, audita el endurecimiento de las cuentas de empleados y saca a la luz las cuentas que se han desviado de la política. La regla básica, con o sin el módulo, es la misma: 2FA activado en cada cuenta que pueda llegar a /admin/.
Restrinja la administración por IP si puede
Si su equipo trabaja desde una IP fija de oficina o una VPN, bloquee la administración a esas direcciones:
# .htaccess dentro del directorio de administración
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^203\\.0\\.113\\.10$
RewriteCond %{REMOTE_ADDR} !^198\\.51\\.100\\.20$
RewriteRule .* - [F,L]
</IfModule>
Solo VPN es el punto óptimo: los empleados pueden trabajar desde cualquier cafetería de Europa, y la administración sigue rechazando a todos los demás a nivel de servidor web antes de que se ejecute siquiera el código de inicio de sesión de PrestaShop. Cuando el abuso proviene de IP de clientes o visitantes reincidentes y no de ataques fijos contra la administración, Customer Extra Info & IP Ban da al personal de soporte una vía de revisión y bloqueo más segura que editar a mano las reglas del servidor web.
Depure las cuentas de empleados
Abra Parámetros avanzados → Equipo → Empleados ahora mismo. Cada cuenta es una credencial que puede ser objeto de phishing. Elimine:
- A quien dejó la empresa hace más de 30 días
- Las cuentas de prueba que el desarrollador original creó y olvidó
- A los contratistas cuyo proyecto terminó
Y rebaje a quien no necesite SuperAdmin. El personal de almacén no necesita restablecer la clave de cookie. El servicio de atención al cliente no necesita instalar módulos.
Fail2ban en el endpoint de inicio de sesión
# /etc/fail2ban/filter.d/prestashop-admin.conf
[Definition]
failregex = ^<HOST> -.*"POST .*/admin.*/index\\.php\\?controller=AdminLogin.*" (200|302)
# /etc/fail2ban/jail.d/prestashop.conf
[prestashop-admin]
enabled = true
filter = prestashop-admin
logpath = /var/log/apache2/access.log
maxretry = 5
findtime = 600
bantime = 3600
Fail2ban vigila los registros del servidor. Para los formularios de cara al cliente donde los bots nunca tocan el endpoint de administración, reCAPTCHA & hCaptcha Protection añade la capa de verificación antes de que el spam se convierta en abuso de cuentas, de formularios de contacto o de registros.
4. Seguridad de los módulos
Los módulos son, con diferencia, la mayor superficie de ataque de cualquier instalación de PrestaShop. Trate cada uno como código no confiable que se ejecuta con acceso total a la base de datos hasta que demuestre lo contrario.
Dónde conseguir módulos, y dónde no
Fuentes aceptables: el marketplace oficial PrestaShop Addons, proveedores establecidos con una trayectoria pública y proyectos de código abierto bien mantenidos en GitHub donde usted mismo pueda leer el código. Todo lo demás es un riesgo.
Los módulos pirateados harán que le hackeen. Esto no es teórico. Quien crackeó el módulo añadió una puerta trasera antes de volver a subirlo. Ese es el objetivo de la operación. Hemos limpiado tiendas donde un solo módulo pirata de "descarga gratuita" exfiltró silenciosamente cada pedido a un tercero durante seis meses. Sin excepciones, sin "solo lo usaré en pruebas". Termina en producción.
Audite el código del módulo antes de instalarlo
Abra el ZIP. Busque con grep estos patrones:
# Peligroso: ejecución de código arbitrario
eval($variable)
eval(base64_decode($something))
assert($user_input)
# Peligroso: carga de código remoto
file_get_contents('http://external-domain.com/...')
include('http://...')
# Peligroso: SQL sin sanear
"SELECT * FROM ps_table WHERE id = " . $_GET['id']
Db::getInstance()->execute("... " . $_POST['value'] . " ...")
Así es como se ve el código limpio de un módulo:
// SEGURO: convierta a entero, use pSQL()
$id = (int)Tools::getValue('id');
$name = pSQL(Tools::getValue('name'));
Si no tiene el tiempo o la formación en PHP para auditar, compruebe al menos si el desarrollador tiene una página de avisos de seguridad, publica changelogs y responde a las incidencias. El silencio tras un CVE es una señal de alarma.
Manténgalos actualizados
- Comprobación semanal de actualizaciones de módulos como mínimo
- Suscríbase a la lista de correo de seguridad de su proveedor
- Siga a Friends of Presta para los CVE de módulos de PrestaShop. Es lo más parecido a un canal de divulgación coordinada que tiene el ecosistema
- Haga una copia de seguridad antes de cada actualización. Siempre.
Deshabilitar no es eliminar
Los archivos PHP de un módulo deshabilitado siguen en el disco y sus controladores frontales siguen siendo accesibles por URL directa. Si tiene una inyección SQL, deshabilitarlo no hace nada. El único estado seguro es que desaparezca:
# Desinstale desde el Back Office y luego borre los archivos
rm -rf /var/www/html/prestashop/modules/unused_module
Abra su lista de módulos y hágalo ahora. Cada módulo que probó en 2022 y nunca usó es un riesgo innecesario.
Permisos en el directorio de módulos
find /var/www/html/prestashop/modules -type d -exec chmod 755 {} \\;
find /var/www/html/prestashop/modules -type f -exec chmod 644 {} \\;
5. Seguridad de la base de datos
No ejecute PrestaShop como root
El usuario de la base de datos en parameters.php debe tener exactamente los permisos que PrestaShop necesita y nada más:
CREATE USER 'prestashop_user'@'localhost' IDENTIFIED BY 'long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER,
CREATE TEMPORARY TABLES, LOCK TABLES
ON prestashop_db.* TO 'prestashop_user'@'localhost';
FLUSH PRIVILEGES;
Cuando llegue la inyección SQL (y en una tienda de 50 módulos acabará llegando), un usuario con permisos acotados es la diferencia entre "volcaron una base de datos" y "volcaron todas las bases de datos del servidor, leyeron /etc/passwd mediante LOAD_FILE y escribieron un webshell mediante INTO OUTFILE".
Copias de seguridad que funcionan de verdad
# Entradas del crontab
# Copia de la base de datos: a diario a las 3 AM
0 3 * * * mysqldump -u backup_user -p'password' prestashop_db | gzip > /backups/db/ps_$(date +\\%Y\\%m\\%d).sql.gz
# Copia de archivos: a diario a las 3:30 AM
30 3 * * * tar -czf /backups/files/ps_files_$(date +\\%Y\\%m\\%d).tar.gz /var/www/html/prestashop/
# Limpiar copias de más de 30 días
0 4 * * * find /backups/ -name "*.gz" -mtime +30 -delete
Las reglas que hemos aprendido a las malas:
- Fuera del servidor. Las copias en la misma máquina las borra el mismo atacante que borró los originales. S3, un segundo VPS, cualquier sitio con credenciales separadas.
- Pruebe la restauración mensualmente. Las copias sin probar son cuentos, no un seguro. Restáurelas en un contenedor de pruebas y cargue la página de inicio.
- Cifre antes de que salgan del servidor. Los volcados SQL contienen datos personales de clientes y hashes de contraseñas.
gpgoage, y las claves viven en un sitio al que solo usted y otra persona puedan llegar. - 30 días de retención como mínimo. Algunos compromisos solo salen a la luz semanas después. Una rotación de 7 días no le salvará.
phpMyAdmin: elimínelo o conténgalo
Nuestra postura por defecto es no instalarlo en producción en absoluto. Un túnel SSH hace el mismo trabajo sin exponer una amplia superficie de ataque basada en web:
# Desde su máquina LOCAL
ssh -L 3307:localhost:3306 user@yourserver.com
# Luego conecte su cliente MySQL local a localhost:3307
Si tiene que conservar phpMyAdmin: ruta de URL aleatoria, restricción por IP, autenticación básica HTTP por delante y el inicio de sesión como root deshabilitado:
$cfg['Servers'][$i]['AllowRoot'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
6. Monitorización y detección
Monitorización de la integridad de archivos
Un atacante que esté dentro modificará archivos, webshell en img/, robador en una plantilla, administrador extra en ps_employee. Una comprobación diaria de hashes detecta la mitad de esto, la de los archivos:
#!/bin/bash
# /usr/local/bin/prestashop-integrity-check.sh
SHOP_DIR="/var/www/html/prestashop"
BASELINE="/var/backups/prestashop-file-hashes.txt"
CURRENT="/tmp/prestashop-file-hashes-current.txt"
ALERT_EMAIL="admin@yourdomain.com"
find "$SHOP_DIR" -type f \\
-not -path "*/var/cache/*" \\
-not -path "*/var/logs/*" \\
-not -path "*/img/p/*" \\
-not -path "*/img/c/*" \\
-exec md5sum {} \\; | sort > "$CURRENT"
if [ -f "$BASELINE" ]; then
DIFF=$(diff "$BASELINE" "$CURRENT")
if [ -n "$DIFF" ]; then
echo "$DIFF" | mail -s "ALERT: PrestaShop files modified" "$ALERT_EMAIL"
fi
fi
Genere la línea base justo después de un despliegue limpio, programe el script a diario y ajuste las exclusiones hasta que solo reciba alertas de cambios reales. Espere ruido la primera semana.
Security Revolution agrupa esto y algunas otras comprobaciones si prefiere no mantener usted mismo un script cron y un archivo de línea base.
Monitorización de registros
# Intentos de inyección SQL
grep -iE "(union\\s+select|or\\s+1=1|information_schema)" /var/log/apache2/access.log
# Intentos de inclusión de archivos
grep -iE "(etc/passwd|\\.\\.\\/\\.\\.\\/)" /var/log/apache2/access.log
# Acceso directo a archivos de módulos (posibles intentos de exploit)
grep -E "modules/.*/ajax|modules/.*/api" /var/log/apache2/access.log
Un cron nocturno que envíe por correo las coincidencias es la versión barata. Enviar los registros a Graylog, Loki o Papertrail y alertar sobre patrones es la versión correcta.
Monitorización de disponibilidad: comprobación de contenido, no solo HTTP 200
- UptimeRobot, HetrixTools o el autoalojado Uptime Kuma: todos sirven
- Monitorice la página de inicio y el proceso de compra, una brecha parcial a menudo solo mata el flujo de compra
- Compruebe un texto de página específico ("Añadir al carrito", el nombre de su tienda), no solo una respuesta 200. Una tienda desfigurada sigue devolviendo 200.
- Intervalos de 1 a 5 minutos, alertas por SMS o Slack, el correo por sí solo se acaba enterrando
Alertas de inicio de sesión en la administración
Sesiones de empleados en PrestaShop 8.
Esta página muestra cada sesión de administración activa con el nombre del empleado, el correo electrónico y la marca de tiempo de la última actividad. Si sospecha de un inicio de sesión no autorizado, este es el primer sitio que debe comprobar.
Un pequeño módulo personalizado enganchado al evento posterior al inicio de sesión envía un correo a seguridad cada vez que alguien accede. Barato de implementar, le dice al instante si se ha filtrado una credencial:
public function hookActionAdminLoginControllerLoginAfter($params)
{
$employee = $params['employee'];
$ip = Tools::getRemoteAddr();
Mail::Send(
(int)Configuration::get('PS_LANG_DEFAULT'),
'alert_admin_login',
"Admin Login: {$employee->email} from {$ip}",
['{body}' => "Employee: {$employee->email}
IP: {$ip}
Time: " . date('Y-m-d H:i:s')],
'security@yourdomain.com',
'Security Alert'
);
}
7. Le han hackeado. ¿Y ahora qué?
Los primeros 30 minutos
- No borre nada todavía. El estado comprometido es evidencia forense. La necesitará para encontrar el punto de entrada.
- Ponga la tienda fuera de línea con una página de mantenimiento o una barrera de contraseña temporal, detenga la hemorragia de inmediato.
- Rote todas las credenciales. SSH, FTP, base de datos, cada cuenta de administración, panel de hosting, claves de API de la pasarela de pago, cualquier cosa guardada en el
parameters.phpcomprometido. - Haga una instantánea del estado comprometido (
tarcompleto +mysqldump) y etiquétela. La querrá para el análisis cuando se asiente el polvo. - Llame por teléfono a su procesador de pagos si maneja datos de tarjetas directamente. Prefieren enterarse por usted primero.
# Modo de mantenimiento rápido
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^YOUR\\.IP\\.ADDRESS$
RewriteCond %{REQUEST_URI} !^/maintenance\\.html$
RewriteRule .* /maintenance.html [R=503,L]
Encuentre la puerta trasera: siempre dejan una
Limpiar el daño visible sin encontrar el mecanismo de persistencia hace que le vuelvan a comprometer en una semana. Los sitios donde mirar:
# Buscar patrones de puerta trasera
grep -rn "eval(" /var/www/html/prestashop/ --include="*.php" | grep -v "vendor\\|cache"
grep -rn "base64_decode" /var/www/html/prestashop/ --include="*.php" | grep -v "vendor\\|cache"
grep -rn "shell_exec\\|passthru\\|system(" /var/www/html/prestashop/ --include="*.php" | grep -v "vendor\\|cache"
# Buscar archivos PHP modificados recientemente
find /var/www/html/prestashop/ -name "*.php" -mtime -7 -not -path "*/cache/*"
# Buscar archivos PHP en directorios donde no deberían existir
find /var/www/html/prestashop/img/ -name "*.php"
find /var/www/html/prestashop/upload/ -name "*.php"
# Comprobar código ofuscado (líneas únicas muy largas)
find /var/www/html/prestashop/ -name "*.php" -exec awk 'NR==1 && length>5000' {} +
No se detenga en el sistema de archivos, los atacantes también persisten a través de la base de datos:
SELECT id_cms, meta_title FROM ps_cms_lang WHERE content LIKE '%<?php%' OR content LIKE '%eval(%';
SELECT * FROM ps_employee ORDER BY date_add DESC LIMIT 10;
Esa segunda consulta detecta un movimiento clásico: el atacante crea su propia cuenta de administración para conservar el acceso después de que usted cambie todas las contraseñas.
Recuperación
- Encuentre el punto de entrada en los registros de acceso. Busque POST inusuales a
modules/*/ajax.phpomodules/*/api.phpalrededor del momento en que la comprobación de integridad marcó un cambio por primera vez. - Restaure desde una copia de seguridad limpia conocida si existe alguna y es anterior al compromiso.
- Si no hay copia limpia: reemplace todos los archivos del núcleo con una descarga nueva de su versión exacta de PS, reinstale cada módulo desde su fuente original y conserve únicamente su tema y el directorio
img/tras escanearlos a fondo. - Escanee la base de datos en busca de contenido inyectado en
ps_configuration,ps_cms_langyps_meta_lang. A los skimmers de tarjetas les encantan estas tablas. - Parchee todo: núcleo, módulos, PHP, MySQL, sistema operativo. No vuelva a poner la tienda en marcha sobre el mismo software que les dejó entrar.
Después de la limpieza
- Corrija la vulnerabilidad concreta que se explotó. Deshabilitar el módulo defectuoso no es corregirlo, elimínelo o parchéelo.
- Monitorice con más intensidad los primeros 30 días. Intentarán volver.
- Un WAF por delante de la tienda (el plan gratuito de Cloudflare es un punto de partida razonable) atrapa muchos de los mismos escáneres en su siguiente pasada.
- Si los datos de clientes o de pago pudieron quedar expuestos, hable con un abogado sobre la notificación de brechas del RGPD. Hay un reloj de 72 horas en marcha.
Verdad incómoda: Si no puede determinar cómo entraron, asuma que volverán a entrar. Una auditoría profesional puntual cuesta muchísimo menos que una segunda brecha más las consecuencias regulatorias.
8. La lista de verificación
Imprímala y trabájela punto por punto. Cada casilla sin marcar es una vía de entrada.
Servidor y PHP
- Versión de PHP actual y compatible
- Funciones PHP peligrosas deshabilitadas
-
expose_php = Off -
display_errors = Offen producción -
allow_url_include = Off - Cookies de sesión: HttpOnly, Secure, SameSite
-
open_basedirconfigurado - Sistema operativo, MySQL y servidor web actualizados
- Autenticación por clave SSH activada, autenticación por contraseña desactivada
- Cortafuegos, solo los puertos que necesita
Sistema de archivos
- Directorios 755, archivos 644
-
parameters.phpen 400 - Nada con 777
- Ejecución de PHP bloqueada en
upload/,img/,download/ - Listado de directorios desactivado
-
.env,.git, YAML y archivos de configuración bloqueados desde la web -
vendor/yvar/logs/bloqueados desde la web
SSL y HTTPS
- Certificado válido con renovación automática
- Redirección HTTP→HTTPS en el servidor web
- Cabecera HSTS configurada
- SSL activado para todas las páginas en PrestaShop
- Sin avisos de contenido mixto
Panel de administración
- El directorio de administración es una cadena aleatoria
- Todas las contraseñas de 16 caracteres o más desde un gestor de contraseñas
- 2FA activado en cada cuenta, sin excepciones
- Administración restringida por IP donde sea factible
- Cuentas sin uso eliminadas, exempleados retirados
- Cada empleado en un perfil de mínimo privilegio
- fail2ban o equivalente en el endpoint de inicio de sesión
Módulos
- Cada módulo de una fuente confiable
- Cero módulos pirateados
- Todos los módulos al día
- Módulos sin uso eliminados, no solo deshabilitados
- Código de módulos revisado en busca de
eval()y SQL sin sanear - Suscrito a los avisos de seguridad de sus proveedores
Base de datos
- Usuario de base de datos dedicado, no root
- Solo los permisos mínimos necesarios
- Contraseña de base de datos de 20 caracteres o más
- MySQL vinculado a localhost
- phpMyAdmin eliminado o restringido por IP
- Prefijo de tablas cambiado del
ps_por defecto
Copias de seguridad
- Volcado diario de la base de datos automatizado
- Copia diaria de archivos automatizada
- Copias almacenadas fuera del servidor
- Copias cifradas antes de la transferencia
- Retención de 30 días o más
- Restauración probada en los últimos 30 días
Monitorización
- Comprobaciones de integridad de archivos en marcha
- Registros de acceso analizados en busca de patrones de ataque
- Monitorización de disponibilidad con comprobación de cadena de contenido
- Alertas de inicio de sesión en la administración activas
- Cabeceras de seguridad enviadas en cada respuesta
Preparación ante incidentes
- Plan de respuesta a incidentes por escrito
- Contactos del hosting y del procesador de pagos a mano
- Proceso de notificación del RGPD documentado
- Página de mantenimiento lista para desplegar
- Cada credencial crítica en un gestor de contraseñas
La seguridad es una tarea de mantenimiento, no un proyecto. Ponga un recordatorio trimestral en su calendario para recorrer esta lista de nuevo. La primera vez que lo haga le llevará un día. Después es una hora. Empiece por arriba: actualice todo, active el 2FA en cada cuenta, elimine los módulos que no usa y ponga en marcha las copias de seguridad fuera del servidor. El resto viene solo.
Lecturas relacionadas
- Copias de seguridad y recuperación ante desastres en PrestaShop: construya la vía de restauración antes de necesitarla
- Cumplimiento del RGPD para tiendas PrestaShop: alinee el trabajo de seguridad con las obligaciones de protección de datos
- Guía de hosting para PrestaShop: requisitos del servidor, límites de PHP y endurecimiento a nivel de hosting
- Resolución de problemas en PrestaShop: diagnóstico de errores 500, pantallas en blanco y recuperación tras un incidente
- Guía de hooks de PrestaShop: contexto para auditar personalizaciones de módulos arriesgadas
- Security Revolution: imposición de 2FA, comprobaciones de integridad de archivos y endurecimiento de la administración en un solo módulo
- Total Defender: protección contra fuerza bruta en la administración y monitorización de inicios de sesión