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, seguridad de base de datos y respuesta ante incidentes.
Blindaje de Seguridad para PrestaShop: La Lista de Verificación Completa
Cada semana, miles de tiendas PrestaShop son comprometidas. Los propietarios se enteran cuando Google marca su sitio, cuando los clientes reportan tarjetas robadas, o cuando la página de inicio redirige a spam. El daño es real: pérdida de ingresos, confianza destruida, responsabilidad bajo el RGPD y semanas de reparación.
Esta guía proviene de años de limpiar tiendas hackeadas. Cada recomendación aborda una vulnerabilidad real que hemos visto explotada en producción. Sígala de arriba a abajo.
1. Por qué las tiendas PrestaShop son hackeadas
Inyección SQL en módulos de terceros
Este es el vector de ataque número uno, y por amplio margen. Los módulos de desarrolladores sin experiencia a menudo pasan la entrada del usuario directamente a las consultas SQL. Un atacante envía una solicitud manipulada al controlador frontal de un módulo y extrae toda su base de datos. La vulnerabilidad casi nunca está en el núcleo de PrestaShop — está en los módulos.
Fuerza bruta en el panel de administración
PrestaShop no tiene limitación de intentos integrada. Un atacante que conozca el nombre de su directorio de administración puede ejecutar miles de combinaciones de contraseñas por minuto. Cualquier cuenta que use admin123 o el nombre de la empresa será descifrada en minutos.
Vulnerabilidades de carga de archivos
Algunos módulos permiten la carga de archivos sin validación adecuada. Un atacante sube un shell PHP disfrazado de imagen, accede a él a través del navegador y obtiene control total del servidor.
PHP y software desactualizados
Las versiones de PHP fuera de soporte tienen vulnerabilidades documentadas públicamente con exploits funcionales. Lo mismo aplica a versiones desactualizadas de PrestaShop, Apache y MySQL.
Archivos de configuración expuestos
Los servidores mal configurados sirven archivos .env, directorios .git y configuraciónes YAML a cualquiera que los solicite — revelando credenciales de base de datos y secretos de cifrado.
Revisión de realidad: La mayoría de los propietarios piensan “mi tienda es demasiado pequeña para ser un objetivo”. A los escáneres automatizados no les importa el tamaño. Escanean cada IP en internet. Si usted ejecuta PrestaShop, es un objetivo.
2. Seguridad a nivel de servidor
Versión y configuración de PHP
Ejecute la versión más reciente de PHP que su PrestaShop soporte — PHP 8.1+ para PS 8.x, PHP 8.1-8.4 para PS 9.x. Nunca ejecute una versión fuera de soporte.
Blindaje clave de php.ini:
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
Nota: Algunos módulos necesitan exec() para el procesamiento de imágenes o la generación de PDF. Si un módulo deja de funcionar, reactive únicamente la función específica que requiere.
Permisos de archivos
- Directorios: 755 — propietario lectura/escritura/ejecución, otros lectura/ejecución
- Archivos: 644 — propietario lectura/escritura, otros solo lectura
- Archivos de configuración: 400 —
app/config/parameters.phpdebe ser solo lectura para el propietario
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
# Writable directories PrestaShop needs
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
Nunca establezca nada en 777. Si un tutorial le dice que ejecute chmod 777, busque un tutorial mejor.
Configuración de SSL/TLS
Active SSL en PrestaShop (Parámetros de la tienda > General), luego añada las cabeceras HSTS:
# 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;
}
Desactivar el listado de directorios y blindar .htaccess
Añada estas reglas a su .htaccess raíz:
Options -Indexes
# Block sensitive file types
<FilesMatch "\.(env|yml|yaml|log|sql|bak|old|orig|save|swp|dist|config|ini|phps)$">
Require all denied
</FilesMatch>
# Block hidden files and directories (.git, .env, etc.)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule (^\.|/\.) - [F]
</IfModule>
# Block composer files
<FilesMatch "^(composer\.json|composer\.lock)$">
Require all denied
</FilesMatch>
# Block config, vendor, and log directories
<IfModule mod_rewrite.c>
RewriteRule ^config/ - [F]
RewriteRule ^vendor/ - [F]
RewriteRule ^var/logs/ - [F]
RewriteRule ^app/config/ - [F]
</IfModule>
# Block PHP execution in upload directories
<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 en 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;
Pruébelo: Después de añadir estas reglas, intente acceder ahttps://yourshop.com/.envyhttps://yourshop.com/app/config/parameters.phpen su navegador. Debería obtener 403 o 404 — nunca el contenido real.
3. Seguridad del panel de administración de PrestaShop
Renombrar el directorio de administración
PrestaShop genera un nombre aleatorio para el directorio de administración durante la instalación. Nunca lo renombre a admin, backoffice o panel. Si es predecible, cámbielo:
mv /var/www/html/prestashop/admin /var/www/html/prestashop/admin-x7k9m2p4
rm -rf /var/www/html/prestashop/var/cache/*
Use al menos 10 caracteres aleatorios. Guarde la URL en marcadores — no necesita ser fácil de recordar.
Contraseñas robustas y 2FA
Cada cuenta de administración debe usar una contraseña única de 16 o más caracteres generada por un gestor de contraseñas. Sin excepciones.
Active la autenticación de dos factores para todas las cuentas (Parámetros avanzados > Administración). PrestaShop 1.7.6+ soporta Google Authenticator de forma nativa. Esta única medida detiene la gran mayoría de los ataques de fuerza bruta.
Limitar el acceso de administración por IP
Si su equipo trabaja desde IPs fijas, restrinja el acceso de administración en consecuencia:
# .htaccess inside admin directory
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^203\.0\.113\.10$
RewriteCond %{REMOTE_ADDR} !^198\.51\.100\.20$
RewriteRule .* - [F,L]
</IfModule>
Si utiliza una VPN, restrinja a la IP de la VPN — los empleados trabajan desde cualquier lugar manteniéndose restringidos por IP.
Desactivar cuentas de empleados innecesarias
Audite las cuentas de empleados regularmente (Parámetros avanzados > Equipo > Empleados):
- Elimine las cuentas de exempleados y contratistas
- Elimine las cuentas de prueba de la configuración inicial
- Asegúrese de que cada empleado tenga el perfil mínimo necesario — el personal de almacén no necesita SuperAdmin
Monitoreo de inicio de sesión de administración
Configure fail2ban para protección contra fuerza bruta:
# /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
4. Seguridad de módulos
Los módulos son la mayor superficie de ataque en cualquier instalación de PrestaShop. Trate cada módulo como un riesgo potencial hasta que se demuestre lo contrario.
Instale solo desde fuentes confiables
Fuentes seguras: PrestaShop Addons Marketplace, desarrolladores establecidos con trayectoria comprobada y módulos de código abierto bien mantenidos en GitHub.
Nunca instale módulos de sitios “nulled” o de “descarga gratuita”, de desarrolladores desconocidos o de publicaciones aleatorias en foros.
Advertencia: Los módulos nulled (pirateados) son la forma más rápida de ser hackeado. Los atacantes inyectan puertas traseras en módulos legítimos y los distribuyen gratuitamente. La puerta trasera les da control sobre cada tienda que lo instale. Lo hemos visto cientos de veces. No hay excepciones.
Audite el código de los módulos
Antes de instalar cualquier módulo, busque estas señales de alerta:
# Dangerous — arbitrary code execution
eval($variable)
eval(base64_decode($something))
assert($user_input)
# Dangerous — remote code loading
file_get_contents('http://external-domain.com/...')
include('http://...')
# Dangerous — unsanitized SQL
"SELECT * FROM ps_table WHERE id = " . $_GET['id']
Db::getInstance()->execute("... " . $_POST['value'] . " ...")
El código seguro utiliza consultas parametrizadas y los métodos de validación de PrestaShop:
// SAFE: Cast to integer, use pSQL()
$id = (int)Tools::getValue('id');
$name = pSQL(Tools::getValue('name'));
Mantenga los módulos actualizados
- Compruebe las actualizaciones al menos semanalmente
- Suscríbase a los boletines de seguridad de los desarrolladores
- Siga los avisos de seguridad de Friends of Presta para CVEs de módulos de PrestaShop
- Siempre haga una copia de seguridad antes de actualizar
Elimine los módulos no utilizados completamente
Desactivar un módulo no es suficiente. Los archivos de un módulo desactivado siguen existiendo en su servidor y sus controladores frontales permanecen accesibles mediante URL directa. Si tiene una vulnerabilidad, desactivarlo no proporciona ninguna protección.
# Uninstall via Back Office, then delete the files
rm -rf /var/www/html/prestashop/modules/unused_module
Revise su lista de módulos ahora. Si instaló algo para probar hace seis meses — elimínelo. Cada módulo no utilizado es superficie de ataque innecesaria.
Audite los permisos de los 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
Nunca use root para la aplicación
Cree un usuario dedicado con permisos mínimos:
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;
Si un atacante explota una inyección SQL, un usuario limitado restringe el daño. Root puede acceder a otras bases de datos, leer archivos del servidor y ejecutar comandos del sistema.
Copias de seguridad regulares
# Crontab entries
# Database backup — daily at 3 AM
0 3 * * * mysqldump -u backup_user -p'password' prestashop_db | gzip > /backups/db/ps_$(date +\%Y\%m\%d).sql.gz
# File backup — daily at 3:30 AM
30 3 * * * tar -czf /backups/files/ps_files_$(date +\%Y\%m\%d).tar.gz /var/www/html/prestashop/
# Cleanup backups older than 30 days
0 4 * * * find /backups/ -name "*.gz" -mtime +30 -delete
Reglas críticas:
- Almacene las copias de seguridad fuera del servidor — si el servidor es comprometido, las copias locales también lo están
- Pruebe sus copias de seguridad mensualmente — restaure en un entorno de prueba y verifique que el sitio funcione
- Cifre antes de transferir externamente — los volcados contienen datos personales de clientes
- Conserve más de 30 días de copias diarias — algunos compromisos no se descubren de inmediato
Asegurar phpMyAdmin (o eliminarlo)
La opción más segura: no instale phpMyAdmin en producción. Use túneles SSH en su lugar:
# From your LOCAL machine
ssh -L 3307:localhost:3306 user@yourserver.com
# Then connect your local MySQL client to localhost:3307
Si debe ejecutar phpMyAdmin: restrinja por IP, use una ruta URL aleatoria, active la autenticación HTTP Basic y desactive el inicio de sesión como root:
$cfg['Servers'][$i]['AllowRoot'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
6. Monitoreo y detección
Monitoreo de integridad de archivos
Los atacantes modifican archivos — inyectando puertas traseras, añadiendo shells en directorios de carga o alterando .htaccess. Detecte cambios con una tarea cron diaria:
#!/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 después de un despliegue limpio, y este script le enviará un correo cada vez que los archivos cambien inesperadamente.
Monitoreo de registros
Escanee los registros de acceso en busca de patrones de ataque:
# SQL injection attempts
grep -iE "(union\s+select|or\s+1=1|information_schema)" /var/log/apache2/access.log
# File inclusion attempts
grep -iE "(etc/passwd|\.\.\/\.\.\/)" /var/log/apache2/access.log
# Direct module file access (potential exploit attempts)
grep -E "modules/.*/ajax|modules/.*/api" /var/log/apache2/access.log
Configure resúmenes diarios de registros mediante cron, o alimente los registros en un sistema centralizado como Graylog o Papertrail para alertas en tiempo real.
Monitoreo de disponibilidad
- Use UptimeRobot, Hetrix Tools o Uptime Kuma autoalojado
- Monitoree tanto la página de inicio como la página de pago
- Verifique el contenido específico de la página, no solo HTTP 200 — una página desfigurada también devuelve 200
- Compruebe cada 1-5 minutos con alertas por correo electrónico, SMS o Slack
Alertas de inicio de sesión de administración
Reciba una notificación de cada inicio de sesión de administración con un hook sencillo:
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}\nIP: {$ip}\nTime: " . date('Y-m-d H:i:s')],
'security@yourdomain.com',
'Security Alert'
);
}
7. Qué hacer si ha sido hackeado
Respuesta inmediata (primeros 30 minutos)
- No elimine nada todavía — necesita los archivos para el análisis forense
- Ponga la tienda fuera de línea con una página de mantenimiento para detener el daño continuo
- Cambie TODAS las contraseñas: SSH, FTP, base de datos, cuentas de administración, panel de hosting, claves de la pasarela de pago
- Haga una copia de seguridad del estado comprometido — etíquétela como “comprometida” para análisis posterior
- Notifique a su procesador de pagos si gestióna los pagos directamente
# Quick maintenance mode
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^YOUR\.IP\.ADDRESS$
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteRule .* /maintenance.html [R=503,L]
Encontrar la puerta trasera
Los atacantes siempre dejan puertas traseras para volver a entrar. Limpiar el hackeo visible sin encontrar la puerta trasera significa ser comprometido de nuevo en cuestión de días.
# Search for backdoor patterns
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"
# Find recently modified PHP files
find /var/www/html/prestashop/ -name "*.php" -mtime -7 -not -path "*/cache/*"
# Find PHP files in directories where they should not exist
find /var/www/html/prestashop/img/ -name "*.php"
find /var/www/html/prestashop/upload/ -name "*.php"
# Check for obfuscated code (very long single lines)
find /var/www/html/prestashop/ -name "*.php" -exec awk 'NR==1 && length>5000' {} +
Compruebe también 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;
Proceso de recuperación
- Determine el punto de entrada a partir de los registros de acceso — busque solicitudes POST inusuales a controladores de módulos alrededor del momento del compromiso
- Restaure desde una copia de seguridad limpia si está disponible. Verifique que la copia de seguridad sea anterior al compromiso.
- Si no existe una copia de seguridad limpia: reemplace todos los archivos del núcleo con una descarga nueva de su versión exacta de PS, reinstale todos los módulos desde las fuentes originales, conserve solo su tema y el directorio
img/(escanéelos exhaustivamente) - Escanee la base de datos en busca de contenido inyectado en
ps_configuration,ps_cms_langyps_meta_lang - Actualice todo — núcleo, módulos, PHP, MySQL, sistema operativo
Prevención después de la limpieza
- Elimine o parchee la vulnerabilidad específica que fue explotada
- Monitoree intensivamente durante el primer mes — los atacantes a menudo intentan volver
- Considere un WAF (nivel gratuito de Cloudflare, Sucuri o ModSecurity)
- Si los datos de pago fueron potencialmente comprometidos, consulte a un abogado sobre las obligaciones de notificación del RGPD (plazo de 72 horas)
Verdad dura: Si no puede determinar cómo entró el atacante, asuma que volverá a entrar. Una auditoría de seguridad profesional cuesta una fracción de lo que cuesta una segunda brecha.
8. Lista de verificación de seguridad
Imprima esta lista y trabaje en ella punto por punto. Cada elemento sin marcar es un punto de entrada potencial.
Servidor y PHP
- La versión de PHP es actual y tiene soporte
- Funciones PHP peligrosas desactivadas
-
expose_php = Off -
display_errors = Offen producción -
allow_url_include = Off - Cookies de sesión: HttpOnly, Secure, SameSite
-
open_basedirconfigurado - SO, MySQL y servidor web actualizados
- Autenticación SSH por clave activada, autenticación por contraseña desactivada
- Firewall configurado (solo puertos necesarios abiertos)
Sistema de archivos
- Directorios: 755, Archivos: 644
-
parameters.php: 400 - Ningún archivo con permisos 777
- Ejecución de PHP bloqueada en
upload/,img/,download/ - Listado de directorios desactivado
- Archivos
.env,.git, YAML y de configuración bloqueados desde la web -
vendor/yvar/logs/bloqueados desde la web
SSL y HTTPS
- Certificado SSL válido con renovación automática
- Redirección de HTTP a HTTPS configurada
- Cabecera HSTS configurada
- SSL activado en PrestaShop (todas las páginas)
- Sin advertencias de contenido mixto
Panel de administración
- El directorio de administración tiene un nombre aleatorio
- Todas las contraseñas de 16 o más caracteres generadas por un gestor de contraseñas
- 2FA activado para todas las cuentas
- Acceso de administración restringido por IP (si es viable)
- Cuentas innecesarias eliminadas
- Cada empleado tiene los permisos mínimos necesarios
- Protección contra fuerza bruta (fail2ban o equivalente)
Módulos
- Todos los módulos de fuentes confiables
- Sin módulos nulled/pirateados
- Todos los módulos actualizados
- Módulos no utilizados eliminados (no solo desactivados)
- Código de módulos auditado en busca de
eval()y SQL sin sanitizar - Suscrito a avisos de seguridad
Base de datos
- Usuario de base de datos dedicado (no root)
- Permisos mínimos otorgados
- Contraseña de base de datos robusta (20 o más caracteres)
- MySQL vinculado solo a localhost
- phpMyAdmin eliminado o restringido por IP
- Prefijo de tablas cambiado del predeterminado
ps_
Copias de seguridad
- Copias de seguridad de base de datos automatizadas diariamente
- Copias de seguridad de archivos automatizadas diariamente
- Copias de seguridad almacenadas fuera del servidor
- Copias de seguridad cifradas antes de la transferencia
- Retención de más de 30 días
- Restauración probada en los últimos 30 días
Monitoreo
- Monitoreo de integridad de archivos activo
- Registros de acceso monitoreados en busca de patrones de ataque
- Monitoreo de disponibilidad con verificación de contenido
- Alertas de inicio de sesión de administración activadas
- Cabeceras de seguridad configuradas
Preparación ante incidentes
- Plan de respuesta a incidentes documentado
- Contactos de hosting y procesador de pagos accesibles
- Proceso de notificación del RGPD documentado
- Página de mantenimiento lista para desplegar
- Todas las contraseñas críticas en un gestor de contraseñas
La seguridad es un proceso continuo, no una configuración única. Programe una revisión trimestral. El tiempo que invierta ahora es insignificante comparado con el costo de recuperarse de una brecha. Comience con los elementos de mayor impacto: actualice todo, active 2FA, elimine los módulos no utilizados y configure las copias de seguridad. Luego trabaje en el resto.
Sus clientes confían en usted con sus datos personales. Honre esa confianza.
More guides available
Browse our knowledge base for more practical PrestaShop tutorials, or reach out if you need help.