PrestaShop Security Hardening: The Complete Checklist
Comprehensive security guide for PrestaShop stores — server hardening, admin protection, module audits, database security, and incident response.
PrestaShop Security Hardening: The Complete Checklist
Every week, thousands of PrestaShop stores get compromised. Owners find out when Google flags their site, when customers report stolen cards, or when the homepage redirects to spam. The damage is real: lost revenue, destroyed trust, GDPR liability, and weeks of cleanup.
This guide comes from years of cleaning up hacked stores. Every recommendation addresses a real vulnerability we have seen exploited in production. Follow it from top to bottom.
1. Why PrestaShop Stores Get Hacked
SQL Injection in Third-Party Modules
This is the number one attack vector and it is not close. Modules from inexperienced developers often pass user input directly into SQL queries. An attacker sends a crafted request to a module's front controller and extracts your entire database. The vulnerability is almost never in PrestaShop core — it is in the modules.
Admin Panel Brute Force
PrestaShop has no built-in rate limiting. An attacker who knows your admin directory name can run thousands of password combinations per minute. Any account using admin123 or the company name will be cracked in minutes.
File Upload Vulnerabilities
Some modules allow file uploads without proper validation. An attacker uploads a PHP shell disguised as an image, accesses it via the browser, and gains full server control.
Outdated PHP and Software
End-of-life PHP versions have publicly documented vulnerabilities with working exploits. The same applies to outdated PrestaShop, Apache, and MySQL versions.
Exposed Configuration Files
Misconfigured servers serve .env files, .git directories, and YAML configs to anyone who requests them — revealing database credentials and encryption secrets.
Reality check: Most owners think "my store is too small to target." Automated scanners do not care about size. They scan every IP on the internet. If you run PrestaShop, you are a target.
2. Server-Level Security
PHP Version and Configuration
Run the newest PHP version your PrestaShop supports — PHP 8.1+ for PS 8.x, PHP 8.1-8.4 for PS 9.x. Never run an end-of-life version.
Key php.ini hardening:
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
Note: Some modules need exec() for image processing or PDF generation. If a module breaks, re-enable only the specific function it requires.
File Permissions
- Directories: 755 — owner read/write/execute, others read/execute
- Files: 644 — owner read/write, others read only
- Configuration files: 400 —
app/config/parameters.phpshould be owner-read only
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
Never set anything to 777. If a tutorial tells you to chmod 777, find a better tutorial.
SSL/TLS Configuration
Enable SSL in PrestaShop (Shop Parameters > General), then add HSTS headers:
# 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;
}
Disable Directory Listing and Harden .htaccess
Add these rules to your root .htaccess:
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>
Nginx equivalent:
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;
Test it: After adding these rules, try accessinghttps://yourshop.com/.envandhttps://yourshop.com/app/config/parameters.phpin your browser. You should get 403 or 404 — never the actual content.
3. PrestaShop Admin Security
Rename the Admin Directory
PrestaShop generates a random admin directory name during installation. Never rename it to admin, backoffice, or panel. If it is predictable, change it:
mv /var/www/html/prestashop/admin /var/www/html/prestashop/admin-x7k9m2p4
rm -rf /var/www/html/prestashop/var/cache/*
Use at least 10 random characters. Bookmark the URL — it does not need to be memorable.
Strong Passwords and 2FA
Every admin account must use a unique 16+ character password from a password manager. No exceptions.
Enable two-factor authentication for all accounts (Advanced Parameters > Administration). PrestaShop 1.7.6+ supports Google Authenticator natively. This single measure stops the vast majority of brute force attacks.
Limit Admin Access by IP
If your team works from fixed IPs, restrict admin access accordingly:
# .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>
If you use a VPN, restrict to the VPN IP — employees work from anywhere while remaining IP-restricted.
Disable Unnecessary Employee Accounts
Audit employee accounts regularly (Advanced Parameters > Team > Employees):
- Delete accounts for former employees and contractors
- Remove test accounts from initial setup
- Ensure each employee has the minimum necessary profile — warehouse staff do not need SuperAdmin
Admin Login Monitoring
Set up fail2ban for brute force protection:
# /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. Module Security
Modules are the biggest attack surface in any PrestaShop installation. Treat every module as a potential risk until proven otherwise.
Only Install from Trusted Sources
Safe sources: PrestaShop Addons Marketplace, established developers with a track record, and well-maintained open-source modules on GitHub.
Never install modules from "nulled" or "free download" sites, unknown developers, or random forum posts.
Warning: Nulled (pirated) modules are the fastest way to get hacked. Attackers inject backdoors into legitimate modules and distribute them for free. The backdoor gives them control over every store that installs it. We have seen this hundreds of times. There are no exceptions.
Audit Module Code
Before installing any module, search for these red flags:
# 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'] . " ...")
Safe code uses parameterized queries and PrestaShop's validation methods:
// SAFE: Cast to integer, use pSQL()
$id = (int)Tools::getValue('id');
$name = pSQL(Tools::getValue('name'));
Keep Modules Updated
- Check for updates at least weekly
- Subscribe to developer security bulletins
- Follow the Friends of Presta security advisories for PrestaShop module CVEs
- Always back up before updating
Remove Unused Modules Completely
Disabling a module is not enough. A disabled module's files still exist on your server and its front controllers remain accessible via direct URL. If it has a vulnerability, disabling provides zero protection.
# Uninstall via Back Office, then delete the files
rm -rf /var/www/html/prestashop/modules/unused_module
Go through your module list now. If you installed something to test six months ago — delete it. Every unused module is unnecessary attack surface.
Audit Module Permissions
find /var/www/html/prestashop/modules -type d -exec chmod 755 {} \;
find /var/www/html/prestashop/modules -type f -exec chmod 644 {} \;
5. Database Security
Never Use Root for the Application
Create a dedicated user with minimal permissions:
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;
If an attacker exploits SQL injection, a limited user restricts the damage. Root can access other databases, read server files, and execute system commands.
Regular Backups
# 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
Critical rules:
- Store backups off-server — if the server is compromised, local backups are too
- Test your backups monthly — restore to a test environment and verify the site works
- Encrypt before transferring off-site — dumps contain customer PII
- Keep 30+ days of dailies — some compromises are not discovered immediately
Secure phpMyAdmin (or Remove It)
The safest option: do not install phpMyAdmin on production. Use SSH tunnels instead:
# From your LOCAL machine
ssh -L 3307:localhost:3306 user@yourserver.com
# Then connect your local MySQL client to localhost:3307
If you must run phpMyAdmin: restrict by IP, use a random URL path, enable HTTP Basic Auth, and disable root login:
$cfg['Servers'][$i]['AllowRoot'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
6. Monitoring and Detection
File Integrity Monitoring
Attackers modify files — injecting backdoors, adding shells to upload directories, or altering .htaccess. Detect changes with a daily cron job:
#!/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
Generate the baseline after a clean deployment, then this script emails you whenever files change unexpectedly.
Log Monitoring
Scan access logs for attack patterns:
# 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
Set up daily log summaries via cron, or feed logs into a centralized system like Graylog or Papertrail for real-time alerts.
Uptime Monitoring
- Use UptimeRobot, Hetrix Tools, or self-hosted Uptime Kuma
- Monitor both homepage and checkout page
- Check for specific page content, not just HTTP 200 — a defaced page still returns 200
- Check every 1-5 minutes with alerts via email, SMS, or Slack
Admin Login Alerts
Get notified of every admin login with a simple hook:
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. What to Do If You Have Been Hacked
Immediate Response (First 30 Minutes)
- Do not delete anything yet — you need the files for forensic analysis
- Take the store offline with a maintenance page to stop ongoing damage
- Change ALL passwords: SSH, FTP, database, admin accounts, hosting panel, payment gateway keys
- Back up the compromised state — label it "compromised" for later analysis
- Notify your payment processor if you handle payments directly
# Quick maintenance mode
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^YOUR\.IP\.ADDRESS$
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteRule .* /maintenance.html [R=503,L]
Finding the Backdoor
Attackers always leave backdoors for re-entry. Cleaning the visible hack without finding the backdoor means re-compromise within days.
# 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' {} +
Check the database too:
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;
Recovery Process
- Determine the entry point from access logs — look for unusual POST requests to module controllers around the time of compromise
- Restore from clean backup if available. Verify the backup predates the compromise.
- If no clean backup exists: replace all core files with a fresh download of your exact PS version, reinstall all modules from original sources, keep only your theme and
img/directory (scan them thoroughly) - Scan the database for injected content in
ps_configuration,ps_cms_lang, andps_meta_lang - Update everything — core, modules, PHP, MySQL, OS
Prevention After Cleanup
- Remove or patch the specific vulnerability that was exploited
- Monitor intensively for the first month — attackers often try to return
- Consider a WAF (Cloudflare free tier, Sucuri, or ModSecurity)
- If payment data was potentially compromised, consult a lawyer about GDPR notification obligations (72-hour deadline)
Hard truth: If you cannot determine how the attacker got in, assume they will get in again. A professional security audit costs a fraction of a second breach.
8. Security Checklist
Print this list and work through it. Every unchecked item is a potential entry point.
Server and PHP
- PHP version is current and supported
- Dangerous PHP functions disabled
-
expose_php = Off -
display_errors = Offin production -
allow_url_include = Off - Session cookies: HttpOnly, Secure, SameSite
-
open_basedirset - OS, MySQL, and web server up to date
- SSH key auth enabled, password auth disabled
- Firewall configured (only necessary ports open)
File System
- Directories: 755, Files: 644
-
parameters.php: 400 - No files set to 777
- PHP execution blocked in
upload/,img/,download/ - Directory listing disabled
-
.env,.git, YAML, config files blocked from web -
vendor/andvar/logs/blocked from web
SSL and HTTPS
- Valid SSL certificate with auto-renewal
- HTTP-to-HTTPS redirect in place
- HSTS header configured
- SSL enabled in PrestaShop (all pages)
- No mixed content warnings
Admin Panel
- Admin directory has a random name
- All passwords 16+ characters from a password manager
- 2FA enabled for all accounts
- Admin access restricted by IP (if feasible)
- Unnecessary accounts deleted
- Each employee has minimum necessary permissions
- Brute force protection (fail2ban or equivalent)
Modules
- All modules from trusted sources
- No nulled/pirated modules
- All modules up to date
- Unused modules deleted (not just disabled)
- Module code audited for
eval()and unsanitized SQL - Subscribed to security advisories
Database
- Dedicated database user (not root)
- Minimal permissions granted
- Strong database password (20+ characters)
- MySQL bound to localhost only
- phpMyAdmin removed or IP-restricted
- Table prefix changed from default
ps_
Backups
- Automated daily database backups
- Automated daily file backups
- Backups stored off-server
- Backups encrypted before transfer
- 30+ days retention
- Restoration tested in the last 30 days
Monitoring
- File integrity monitoring active
- Access logs monitored for attack patterns
- Uptime monitoring with content checks
- Admin login alerts enabled
- Security headers in place
Incident Readiness
- Incident response plan documented
- Hosting and payment processor contacts accessible
- GDPR notification process documented
- Maintenance page ready to deploy
- All critical passwords in a password manager
Security is ongoing, not a one-time setup. Schedule a quarterly review. The time you invest now is insignificant compared to the cost of recovering from a breach. Start with the highest-impact items: update everything, enable 2FA, remove unused modules, and configure backups. Then work through the rest.
Your customers trust you with their personal data. Honor that trust.
More guides available
Browse our knowledge base for more practical PrestaShop tutorials, or reach out if you need help.