Sicurezza PrestaShop: La checklist completa
Guida completa alla sicurezza PrestaShop: hardening server, protezione admin, audit moduli, sicurezza database e risposta agli incidenti.
Che aspetto ha davvero un PrestaShop compromesso
La maggior parte dei negozi violati per cui siamo stati chiamati a intervenire dal 2013 in poi sembrava perfettamente normale dalla home page. Il proprietario se ne accorgeva solo perché Google segnalava il sito, il gestore dei pagamenti sospendeva gli accrediti, oppure un cliente telefonava lamentando uno "strano reindirizzamento dopo il checkout". A quel punto l'aggressore era di solito già dentro da settimane.
Gli schemi si ripetono. Un modulo di terze parti vulnerabile fa trapelare il database. Un URL di amministrazione individuato viene sottoposto a brute force nel fine settimana. Una shell PHP camuffata da immagine finisce in img/. Una backdoor inietta uno skimmer di carte in order-confirmation.tpl. Nessuno di questi attacchi è esotico. La checklist qui sotto può aiutare a ridurre questi rischi.
Questa è la checklist che consegniamo ai clienti prima di accettare di gestire il loro negozio PrestaShop. I percorsi e le versioni di PHP variano in base alla versione di PrestaShop, ma i principi di hardening restano gli stessi. Per la versione non tecnica, indirizza il proprietario del negozio alla nostra guida alla sicurezza in linguaggio semplice.
1. Come vengono violati realmente i negozi PrestaShop
SQL injection in un modulo di terze parti
Questo è il vettore numero uno, con ampio margine. Il core è ragionevolmente collaudato; i moduli non lo sono. Uno sviluppatore alle prime armi pubblica un front controller che concatena $_GET['id'] direttamente in una query, uno scanner automatico la individua, l'aggressore esporta ps_customer e ps_orders prima di pranzo. Lo abbiamo visto con moduli del marketplace ufficiale Addons, non solo dei forum di software craccato.
Brute force sull'amministrazione
PrestaShop non ha alcun limite di frequenza nativo sul modulo di login dell'amministrazione. Una volta che un aggressore conosce la directory di amministrazione (e la conoscerà, perché metà dei negozi che controlliamo usa ancora /admin/ o /admin123/) lancerà migliaia di tentativi di password al minuto. Qualsiasi account con welcome2024 o il nome del negozio è perso in pochi minuti.
Usa limiti ai tentativi di accesso, blocchi basati su IP e avvisi in caso di attacchi agli account dei dipendenti. Questi controlli affiancano password robuste e 2FA, ma non le sostituiscono.
Caricamento di un file che diventa una shell PHP
Un caricamento di "foto del profilo" o di "immagine del prodotto" che non convalida il contenuto reale del file, ma solo l'estensione. L'aggressore carica shell.php.jpg, il server è configurato per eseguire qualsiasi cosa corrisponda a .php nel percorso, partita finita. La correzione sul lato del server web (bloccare l'esecuzione di PHP in img/, upload/, download/) è più sotto, impostala una volta e neutralizza un'intera classe di moduli difettosi.
PHP a fine vita e software non aggiornato
PHP 7.4 è a fine vita dal novembre 2022. Lo vediamo ancora in produzione. Ogni exploit documentato pubblicamente contro PHP 7.x è una vittoria gratuita per un aggressore, e lo stesso vale per MySQL 5.7, Apache 2.2 e PrestaShop 1.7.6 con tre anni di CVE non corrette.
File di configurazione esposti
Un server web mal configurato serve allegramente /.env, /.git/config o /app/config/parameters.php a chiunque ne faccia richiesta. Password del database, chiave dei cookie, nome della cartella di amministrazione, tutto, in chiaro, in una singola richiesta GET. Eseguiamo questo controllo su ogni negozio che acquisiamo.
La realtà è questa: "Il mio negozio è troppo piccolo per essere un bersaglio" è ciò che ogni proprietario ci dice prima della fattura di ripulitura. Gli scanner non leggono la tua pagina Chi siamo, passano al setaccio ogni indirizzo IPv4 di Internet alla ricerca di firme PrestaShop. Le dimensioni sono irrilevanti.
2. Hardening a livello di server
Versione e configurazione di PHP
Esegui la versione di PHP più recente supportata dalla tua versione di PrestaShop, PHP 8.1+ per PS 8.x, PHP 8.1–8.4 per PS 9.x. Se sei bloccato su qualcosa di più vecchio di PHP 8.1 a causa di un modulo, la risposta è sostituire il modulo, non restare su PHP a fine vita.
L'hardening di php.ini che applichiamo per impostazione predefinita:
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
Una manciata di moduli (vecchi elaboratori di immagini, alcuni generatori di PDF) ha realmente bisogno di exec(). Non riaprire l'intero elenco per far funzionare un solo modulo. Riabilita la singola funzione che richiede, registra la decisione e, se puoi sostituire il modulo con uno che non ricorre alla shell, fallo alla prossima finestra di manutenzione.
Permessi dei file
I tre numeri che contano:
- 755 sulle directory: il proprietario può scrivere, tutti possono elencare e attraversare
- 644 sui file: il proprietario può scrivere, tutti possono leggere
- 400 su
app/config/parameters.php: solo il proprietario può leggerlo. Questo file contiene le credenziali del tuo database. Trattalo come una chiave privata.
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
# Directory scrivibili di cui PrestaShop ha bisogno
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
Se un tutorial, un articolo di supporto o l'assistenza dell'hosting ti dice di fare chmod 777 su qualcosa, ignorali e trova una fonte migliore. Non esiste alcuno scenario in cui 777 sia la risposta giusta su un negozio in produzione.
SSL/TLS e header di sicurezza
Attiva SSL in Parametri del negozio → Generale, forza il reindirizzamento a livello di server web e aggiungi HSTS in modo che il browser rifiuti il downgrade.
# 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;
}
Content Security Policy
La CSP può smorzare l'impatto di uno skimmer di carte iniettato o di un payload XSS, ma una policy rigida su PrestaShop romperà il checkout la prima volta che la provi. Widget di pagamento, analytics, chat, font e una lunga coda di JavaScript dei moduli attingono a origini di terze parti. Distribuiscila in due fasi:
# Apache: prima monitorare, non applicare subito
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: prima monitorare, non applicare subito
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;
Lasciala in Report-Only per almeno una settimana di traffico reale. Raccogli le violazioni, sostituisci il carattere jolly https: con i domini effettivi dei tuoi provider (Stripe, PayPal, Adyen, Klarna, GA, GTM, Hotjar, ecc.) e passa all'applicazione solo dopo che un test completo del checkout va a buon fine senza errori. Mantieni 'unsafe-inline' finché il tuo tema ne ha bisogno, rimuoverlo richiede il supporto di nonce o hash in ogni template.
Bloccare l'elenco delle directory e i file sensibili
Le regole Apache che usiamo per ogni negozio che ospitiamo: inseriscile nel file .htaccess nella radice del negozio, tranne i blocchi <Directory>, che vanno nella configurazione del server o del virtual host:
Options -Indexes
# Bloccare i tipi di file sensibili
<FilesMatch "\\.(env|yml|yaml|log|sql|bak|old|orig|save|swp|dist|config|ini|phps)$">
Require all denied
</FilesMatch>
# Bloccare file e directory nascosti (.git, .env, ecc.)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule (^\\.|/\\.) - [F]
</IfModule>
# Bloccare i file di composer
<FilesMatch "^(composer\\.json|composer\\.lock)$">
Require all denied
</FilesMatch>
# Bloccare le directory di config, vendor e log
<IfModule mod_rewrite.c>
RewriteRule ^config/ - [F]
RewriteRule ^vendor/ - [F]
RewriteRule ^var/logs/ - [F]
RewriteRule ^app/config/ - [F]
</IfModule>
# Bloccare l'esecuzione di PHP nelle directory di caricamento
<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 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;
Verificalo. Aprihttps://yourshop.com/.envehttps://yourshop.com/app/config/parameters.phpin una finestra in incognito dopo la distribuzione. 403 o 404 è corretto. Qualsiasi altra cosa e stai distribuendo credenziali.
3. Hardening del pannello di amministrazione
Impostazioni di sicurezza nel Back Office di PrestaShop 8.
La protezione tramite token e la policy delle password sono le due impostazioni presenti qui. La protezione tramite token dovrebbe restare attiva; il punteggio della password dovrebbe essere almeno 3.
Rinominare la directory di amministrazione: fatto come si deve
PrestaShop installa una cartella di amministrazione casuale per impostazione predefinita. Se la tua è ancora /admin/ o una qualsiasi parola indovinabile (/backoffice, /panel, il nome del negozio, le iniziali dello sviluppatore) rinominala oggi stesso con dieci o più caratteri casuali:
mv /var/www/html/prestashop/admin /var/www/html/prestashop/admin-x7k9m2p4
rm -rf /var/www/html/prestashop/var/cache/*
Non è sicurezza di per sé. È la differenza tra essere nella lista dei bersagli di ogni scanner e non esserlo. Aggiungi ai segnalibri il nuovo URL, conservalo nel tuo gestore di password e vai avanti.
Password forti e autenticazione a due fattori: non facoltative
Ogni account di amministrazione: 16+ caratteri, generati da un gestore di password, mai riutilizzati. PrestaShop 1.7.6 e versioni successive supportano TOTP (Google Authenticator, Authy, 1Password, Bitwarden) nativamente in Parametri avanzati → Amministrazione. Attivala per ogni dipendente, senza eccezioni. Questa singola impostazione sconfigge la stragrande maggioranza degli attacchi di brute force e di credential stuffing che vediamo.
Security Revolution impone l'autenticazione a due fattori, verifica l'hardening degli account dei dipendenti e fa emergere gli account che si sono allontanati dalla policy. La regola di base, con o senza il modulo, è la stessa: autenticazione a due fattori attivata su ogni account che può raggiungere /admin/.
Restringere l'amministrazione per IP, se possibile
Se il tuo team lavora da un IP fisso dell'ufficio o da una VPN, blocca l'amministrazione su quegli indirizzi:
# .htaccess all'interno della directory di amministrazione
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^203\\.0\\.113\\.10$
RewriteCond %{REMOTE_ADDR} !^198\\.51\\.100\\.20$
RewriteRule .* - [F,L]
</IfModule>
Il solo accesso via VPN è il punto di equilibrio ideale: i dipendenti possono lavorare da qualsiasi caffè in Europa, l'amministrazione respinge comunque tutti gli altri a livello di server web prima ancora che il codice di login di PrestaShop venga eseguito. Quando l'abuso proviene da IP ricorrenti di clienti o visitatori piuttosto che da attacchi fissi all'amministrazione, Customer Extra Info & IP Ban offre al personale di supporto un percorso di revisione e blocco più sicuro rispetto alla modifica manuale delle regole del server web.
Ridurre gli account dei dipendenti
Apri Parametri avanzati → Team → Dipendenti proprio adesso. Ogni account è una credenziale che può essere oggetto di phishing. Elimina:
- Chiunque abbia lasciato l'azienda da più di 30 giorni
- Gli account di prova creati e dimenticati dallo sviluppatore originale
- I collaboratori esterni il cui progetto è terminato
E declassa chiunque non abbia bisogno di SuperAdmin. Il personale di magazzino non ha bisogno di reimpostare la chiave dei cookie. Il servizio clienti non ha bisogno di installare moduli.
Fail2ban sull'endpoint di login
# /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 controlla i log del server. Per i moduli rivolti ai clienti dove i bot non toccano mai l'endpoint di amministrazione, reCAPTCHA & hCaptcha Protection aggiunge il livello di sfida prima che lo spam diventi abuso di account, di moduli di contatto o di registrazione.
4. Sicurezza dei moduli
I moduli sono la più ampia superficie di attacco di qualsiasi installazione PrestaShop. Tratta ognuno come codice non attendibile in esecuzione con pieno accesso al database, finché non dimostra il contrario.
Dove procurarsi i moduli, e dove no
Fonti accettabili: il marketplace ufficiale PrestaShop Addons, fornitori affermati con una reputazione pubblica e progetti open source ben mantenuti su GitHub dove puoi leggere il codice da te. Tutto il resto è un rischio.
I moduli craccati ti faranno violare. Non è un'ipotesi teorica. Chi ha craccato il modulo ha aggiunto una backdoor prima di ricaricarlo. È proprio questo lo scopo dell'operazione. Abbiamo ripulito negozi dove un singolo modulo "scaricato gratis" e craccato ha esfiltrato silenziosamente ogni ordine a terzi per sei mesi. Nessuna eccezione, nessun "lo userò solo in staging". Finisce sempre in produzione.
Verificare il codice del modulo prima di installarlo
Apri lo ZIP. Cerca con grep questi pattern:
# Pericoloso: esecuzione di codice arbitrario
eval($variable)
eval(base64_decode($something))
assert($user_input)
# Pericoloso: caricamento di codice remoto
file_get_contents('http://external-domain.com/...')
include('http://...')
# Pericoloso: SQL non sanificato
"SELECT * FROM ps_table WHERE id = " . $_GET['id']
Db::getInstance()->execute("... " . $_POST['value'] . " ...")
Che aspetto ha il codice pulito di un modulo:
// SICURO: cast a intero, uso di pSQL()
$id = (int)Tools::getValue('id');
$name = pSQL(Tools::getValue('name'));
Se non hai il tempo o le basi di PHP per fare la verifica, controlla almeno se lo sviluppatore ha una pagina di avvisi di sicurezza, pubblica i changelog e risponde alle segnalazioni. Il silenzio dopo una CVE è un campanello d'allarme.
Mantenerli aggiornati
- Controllo settimanale degli aggiornamenti dei moduli come minimo
- Iscriviti alla mailing list di sicurezza del tuo fornitore
- Segui Friends of Presta per le CVE dei moduli PrestaShop. È la cosa più vicina a un feed di divulgazione coordinata che l'ecosistema possieda
- Fai un backup prima di ogni aggiornamento. Sempre.
Disabilitare non è rimuovere
I file PHP di un modulo disabilitato sono ancora su disco e i suoi front controller restano raggiungibili tramite URL diretto. Se ha una SQL injection, disabilitarlo non serve a nulla. L'unico stato sicuro è eliminato:
# Disinstallare dal Back Office, poi eliminare i file
rm -rf /var/www/html/prestashop/modules/unused_module
Apri il tuo elenco dei moduli e fallo adesso. Ogni modulo che hai provato nel 2022 e non hai mai usato è un rischio non necessario.
Permessi sulla directory dei moduli
find /var/www/html/prestashop/modules -type d -exec chmod 755 {} \\;
find /var/www/html/prestashop/modules -type f -exec chmod 644 {} \\;
5. Sicurezza del database
Non eseguire PrestaShop come root
L'utente del database in parameters.php dovrebbe avere esattamente i permessi di cui PrestaShop ha bisogno e nulla di più:
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;
Quando arriva una SQL injection (e su un negozio da 50 moduli prima o poi arriva) un utente con privilegi ridotti è la differenza tra "ha esportato un database" e "ha esportato ogni database sul server, ha letto /etc/passwd tramite LOAD_FILE e ha scritto una webshell tramite INTO OUTFILE".
Backup che funzionano davvero
# Voci del crontab
# Backup del database: ogni giorno alle 3:00
0 3 * * * mysqldump -u backup_user -p'password' prestashop_db | gzip > /backups/db/ps_$(date +\\%Y\\%m\\%d).sql.gz
# Backup dei file: ogni giorno alle 3:30
30 3 * * * tar -czf /backups/files/ps_files_$(date +\\%Y\\%m\\%d).tar.gz /var/www/html/prestashop/
# Eliminazione dei backup più vecchi di 30 giorni
0 4 * * * find /backups/ -name "*.gz" -mtime +30 -delete
Le regole che ci siamo guadagnati nel modo più duro:
- Fuori dal server. I backup sulla stessa macchina vengono cancellati dallo stesso aggressore che ha cancellato gli originali. S3, un secondo VPS, qualunque luogo con credenziali separate.
- Testa il ripristino ogni mese. I backup non testati sono racconti, non un'assicurazione. Ripristina su un container di staging e carica la home page.
- Cifra prima che lascino il server. I dump SQL contengono dati personali dei clienti e hash delle password.
gpgoage, con le chiavi conservate in un posto raggiungibile solo da te e da un'altra persona. - Ritenzione minima di 30 giorni. Alcune compromissioni emergono solo settimane dopo. Una rotazione di 7 giorni non ti salverà.
phpMyAdmin: lo rimuova, o lo contenga
La nostra posizione predefinita è non installarlo affatto in produzione. Un tunnel SSH fa lo stesso lavoro senza esporre un'ampia superficie di attacco basata sul web:
# Dalla tua macchina LOCALE
ssh -L 3307:localhost:3306 user@yourserver.com
# Poi collega il tuo client MySQL locale a localhost:3307
Se devi tenere phpMyAdmin: percorso URL casuale, restrizione per IP, HTTP Basic Auth davanti ad esso e login root disabilitato:
$cfg['Servers'][$i]['AllowRoot'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
6. Monitoraggio e rilevamento
Monitoraggio dell'integrità dei file
Un aggressore che è dentro modificherà dei file, una webshell in img/, uno skimmer in un template, un amministratore in più in ps_employee. Un controllo giornaliero degli hash intercetta la metà di tutto questo legata ai file:
#!/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
Genera la baseline subito dopo una distribuzione pulita, pianifica l'esecuzione giornaliera dello script e regola le esclusioni finché non ricevi avvisi solo su cambiamenti reali. Aspettati del rumore la prima settimana.
Security Revolution include questo e qualche altro controllo, se preferisci non mantenere da te uno script cron e un file di baseline.
Monitoraggio dei log
# Tentativi di SQL injection
grep -iE "(union\\s+select|or\\s+1=1|information_schema)" /var/log/apache2/access.log
# Tentativi di inclusione di file
grep -iE "(etc/passwd|\\.\\.\\/\\.\\.\\/)" /var/log/apache2/access.log
# Accesso diretto ai file dei moduli (potenziali tentativi di exploit)
grep -E "modules/.*/ajax|modules/.*/api" /var/log/apache2/access.log
Un cron notturno che invia via e-mail le corrispondenze è la versione economica. Inviare i log a Graylog, Loki o Papertrail e generare avvisi sui pattern è la versione fatta come si deve.
Monitoraggio dell'uptime: controllo del contenuto, non solo HTTP 200
- UptimeRobot, HetrixTools o Uptime Kuma auto-ospitato, vanno tutti bene
- Monitora la home page e il checkout, una violazione parziale spesso uccide solo il flusso di checkout
- Controlla la presenza di testo specifico nella pagina ("Aggiungi al carrello", il nome del tuo negozio), non solo una risposta 200. Un negozio deturpato restituisce comunque 200.
- Intervalli di 1–5 minuti, avvisi via SMS o Slack, la sola e-mail finisce sepolta
Avvisi di login all'amministrazione
Sessioni dei dipendenti in PrestaShop 8.
Questa pagina mostra ogni sessione di amministrazione attiva con nome del dipendente, e-mail e data e ora dell'ultima attività. Se sospetti un login non autorizzato, è il primo posto da controllare.
Un piccolo modulo personalizzato agganciato all'evento successivo al login invia un'e-mail alla sicurezza ogni volta che qualcuno accede. Economico da realizzare, ti dice all'istante se una credenziale è trapelata:
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. È stato violato. E adesso.
Primi 30 minuti
- Non eliminare ancora nulla. Lo stato compromesso è una prova forense. Ti servirà per trovare il punto di ingresso.
- Metti il negozio offline con una pagina di manutenzione o un blocco temporaneo tramite password: ferma subito l'emorragia.
- Ruota ogni credenziale. SSH, FTP, database, ogni account di amministrazione, pannello di hosting, chiavi API del gateway di pagamento, qualsiasi cosa memorizzata nel
parameters.phpcompromesso. - Crea un'istantanea dello stato compromesso (
tarcompleto +mysqldump) ed etichettala. La vorrai per l'analisi dopo che la polvere si sarà posata. - Telefona al tuo operatore di pagamento se gestisci direttamente i dati delle carte. Preferiscono sentirlo prima da te.
# Modalità di manutenzione rapida
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^YOUR\\.IP\\.ADDRESS$
RewriteCond %{REQUEST_URI} !^/maintenance\\.html$
RewriteRule .* /maintenance.html [R=503,L]
Trovare la backdoor: ne lasciano sempre una
Ripulire i danni visibili senza trovare il meccanismo di persistenza ti fa compromettere di nuovo entro una settimana. I posti dove cercare:
# Cercare i pattern delle backdoor
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"
# Trovare i file PHP modificati di recente
find /var/www/html/prestashop/ -name "*.php" -mtime -7 -not -path "*/cache/*"
# Trovare file PHP in directory dove non dovrebbero esistere
find /var/www/html/prestashop/img/ -name "*.php"
find /var/www/html/prestashop/upload/ -name "*.php"
# Controllare il codice offuscato (righe singole molto lunghe)
find /var/www/html/prestashop/ -name "*.php" -exec awk 'NR==1 && length>5000' {} +
Non ti fermare al filesystem, gli aggressori persistono anche tramite il database:
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;
Quella seconda query intercetta una mossa classica: l'aggressore crea il proprio account di amministrazione così da mantenere l'accesso dopo che tu hai cambiato ogni password.
Ripristino
- Trova il punto di ingresso nei log di accesso. Cerca POST insoliti verso
modules/*/ajax.phpomodules/*/api.phpintorno al momento in cui il controllo di integrità ha segnalato per la prima volta un cambiamento. - Ripristina da un backup notoriamente pulito se ne esiste uno antecedente alla compromissione.
- Se non c'è un backup pulito: sostituisci tutti i file del core con un download nuovo della tua esatta versione di PS, reinstalla ogni modulo dalla sua fonte originale, conserva solo il tuo tema e la directory
img/dopo averli analizzati a fondo. - Analizza il database alla ricerca di contenuto iniettato in
ps_configuration,ps_cms_langeps_meta_lang. Gli skimmer adorano queste tabelle. - Correggi tutto: core, moduli, PHP, MySQL, sistema operativo. Non rimettere online il negozio sullo stesso software che li ha fatti entrare.
Dopo la ripulitura
- Correggi la vulnerabilità specifica che è stata sfruttata. Disabilitare il modulo difettoso non significa correggerlo, rimuovilo o applica una patch.
- Monitora più intensamente per i primi 30 giorni. Cercheranno di tornare.
- Un WAF davanti al negozio (il piano gratuito di Cloudflare è un punto di partenza ragionevole) intercetta molti degli stessi scanner al passaggio successivo.
- Se dati dei clienti o di pagamento sono stati potenzialmente esposti, parla con un avvocato della notifica di violazione prevista dal GDPR, c'è un conto alla rovescia di 72 ore in corso.
Verità scomoda: Se non riesci a determinare come sono entrati, dai per scontato che entreranno di nuovo. Una verifica professionale una tantum costa molto meno di una seconda violazione più le conseguenze sul piano normativo.
8. La checklist
Stampala e affrontala voce per voce. Ogni casella non spuntata è una via di accesso.
Server e PHP
- Versione di PHP aggiornata e supportata
- Funzioni PHP pericolose disabilitate
-
expose_php = Off -
display_errors = Offin produzione -
allow_url_include = Off - Cookie di sessione: HttpOnly, Secure, SameSite
-
open_basedirimpostato - Sistema operativo, MySQL, server web aggiornati
- Autenticazione SSH a chiave attiva, autenticazione a password disattivata
- Firewall. Solo le porte che servono
Sistema di file
- Directory a 755, file a 644
-
parameters.phpa 400 - Niente impostato a 777
- Esecuzione di PHP bloccata in
upload/,img/,download/ - Elenco delle directory disattivato
-
.env,.git, YAML, file di configurazione tutti bloccati dal web -
vendor/evar/logs/bloccati dal web
SSL e HTTPS
- Certificato valido con rinnovo automatico
- Reindirizzamento HTTP→HTTPS a livello di server web
- Header HSTS impostato
- SSL attivo su tutte le pagine in PrestaShop
- Nessun avviso di contenuto misto
Pannello di amministrazione
- La directory di amministrazione è una stringa casuale
- Tutte le password con 16+ caratteri da un gestore di password
- Autenticazione a due fattori attiva su ogni account, senza eccezioni
- Amministrazione ristretta per IP dove possibile
- Account inutilizzati eliminati, ex dipendenti rimossi
- Ogni dipendente su profilo a privilegio minimo
- fail2ban o equivalente sull'endpoint di login
Moduli
- Ogni modulo da una fonte attendibile
- Zero moduli craccati
- Tutti i moduli aggiornati
- Moduli inutilizzati eliminati, non solo disabilitati
- Codice dei moduli controllato a campione per
eval()e SQL non sanificato - Iscritto agli avvisi di sicurezza dei tuoi fornitori
Database
- Utente del database dedicato, non root
- Solo i permessi minimi necessari
- Password del database con 20+ caratteri
- MySQL vincolato a localhost
- phpMyAdmin rimosso o ristretto per IP
- Prefisso delle tabelle cambiato dal predefinito
ps_
Backup
- Dump giornaliero del database automatizzato
- Backup giornaliero dei file automatizzato
- Backup conservati fuori dal server
- Backup cifrati prima del trasferimento
- Ritenzione di 30+ giorni
- Ripristino testato negli ultimi 30 giorni
Monitoraggio
- Controlli di integrità dei file in esecuzione
- Log di accesso analizzati per pattern di attacco
- Monitoraggio dell'uptime con controllo della stringa di contenuto
- Avvisi di login all'amministrazione attivi
- Header di sicurezza inviati su ogni risposta
Preparazione agli incidenti
- Piano di risposta agli incidenti messo per iscritto
- Contatti dell'hosting e dell'operatore di pagamento a portata di mano
- Processo di notifica GDPR documentato
- Pagina di manutenzione pronta alla distribuzione
- Ogni credenziale critica in un gestore di password
La sicurezza è un'attività di manutenzione, non un progetto. Metti un promemoria trimestrale sul calendario per ripercorrere questo elenco. La prima volta che lo farai ti porterà via una giornata. Dopodiché è un'ora. Inizia dall'alto: aggiorna tutto, attiva l'autenticazione a due fattori su ogni account, elimina i moduli che non usi, fai partire i backup fuori dal server. Il resto viene da sé.
Letture correlate
- Backup e ripristino di emergenza di PrestaShop: costruisci il percorso di ripristino prima di averne bisogno
- Conformità al GDPR per i negozi PrestaShop: allinea il lavoro sulla sicurezza con gli obblighi di protezione dei dati
- Guida all'hosting di PrestaShop: requisiti del server, limiti di PHP e hardening a livello di hosting
- Risoluzione dei problemi di PrestaShop: diagnosi di errori 500, schermate bianche e ripristino dopo un incidente
- Guida agli hook di PrestaShop: contesto per verificare le personalizzazioni rischiose dei moduli
- Security Revolution: imposizione dell'autenticazione a due fattori, controlli di integrità dei file e hardening dell'amministrazione in un unico modulo
- Total Defender: protezione dal brute force sull'amministrazione e monitoraggio dei login