Attacchi a PrestaShop: skimmer, pagamenti dirottati e backdoor che abbiamo visto
Moduli di carta falsi al pagamento, incassi che finiscono sul conto di qualcun altro, backdoor nascoste in moduli che nessuno usa. Senza dire di chi, raccontiamo cosa abbiamo trovato ripulendo negozi PrestaShop, come gestiamo un incidente e perché è il negozio non aggiornato quello che finisce in questa lista.
Un negozio online non viene violato come nei film. Niente schermate rosse né teschi in homepage. Di solito succede l'esatto contrario: il negozio funziona perfettamente, gli ordini arrivano, i clienti pagano e il titolare non si accorge di nulla. Nel frattempo qualcuno sta copiando le carte nel passaggio di pagamento, incassando su un conto che non è il tuo o tenendosi una backdoor per tornare quando vuole.
In Rekire ripuliamo negozi PrestaShop compromessi più spesso di quanto vorremmo. Questo articolo raccoglie ciò che abbiamo visto in quegli interventi. I casi sono reali, ma li raccontiamo in modo che sia impossibile capire di quale negozio si tratti: niente settore, niente città, niente date, niente cifre e nessun dettaglio che permetta di risalirvi. Quello che conta non è chi, ma come, perché il come si ripete.
È un articolo lungo, ed è voluto. Se il tuo negozio gira su una versione vecchia di PrestaShop, ti chiediamo di leggerlo fino in fondo.
Che cos'è uno skimmer e perché è l'attacco preferito contro un negozio
Uno skimmer (detto anche clonatore di carte o attacco di tipo Magecart) è un pezzo di JavaScript che si infila nel tuo negozio e ruba i dati della carta nel momento stesso in cui il cliente li digita. Numero, scadenza, CVV e nome del titolare finiscono su un server dell'attaccante, e l'ordine prosegue normalmente.
È l'attacco più redditizio che esista contro un negozio online, per tre motivi:
- Non rompe nulla. Il cliente compra, tu incassi, nessuno si lamenta. I dati rubati vengono usati settimane dopo, altrove, e quando la banca del cliente rileva la frode nessuno collega la carta al tuo negozio.
- Non serve che il tuo gateway di pagamento sia vulnerabile. Che tu usi il POS virtuale della tua banca, Stripe o PayPal non fa differenza. Lo skimmer non attacca il gateway: attacca la pagina su cui si trova il cliente.
- Scala. Un negozio con un traffico normale consegna decine di carte a settimana senza che l'attaccante debba fare altro.
Caso 1: il modulo di carta che non esisteva
Il primo segnale è stato un avviso automatico del nostro modulo di sicurezza: un template del passaggio di pagamento del tema era cambiato senza che nessuno avesse toccato il tema.
Tirando il filo è emersa l'intera sequenza, ricostruita con i log del server:
- Qualcuno è entrato nel pannello dell'hosting con nome utente e password corretti. Non era una falla di PrestaShop: la password era trapelata.
- Dal file manager del pannello ha scritto circa 60 KB di JavaScript in un file del tema stesso, fino ad allora vuoto. Un file dal nome noioso, di quelli che nessuno apre.
- Ha aggiunto una sola riga in fondo al template del passaggio di pagamento: uno
<script src>che caricava quel file. Dallo stesso dominio del negozio, quindi nessun filtro sui «domini esterni» l'avrebbe segnalato. - Ha caricato un piccolo file PHP per svuotare la cache dei template, l'ha eseguito e se n'è andato. Il tutto in meno di venti minuti.
Il JavaScript non faceva nulla mentre il cliente navigava. Si attivava solo quando il cliente selezionava il pagamento con carta. A quel punto mostrava un modulo di carta identico a quello del negozio e, una volta compilato, inviava i dati codificati con navigator.sendBeacon a un altro negozio online, anch'esso violato, che faceva da casella di raccolta. Usare il sito di un'altra vittima come destinazione è frequente: un normale dominio commerciale non desta sospetti.
È rimasto attivo per circa una settimana. Il lavoro successivo è stato importante quanto la pulizia: estrarre l'elenco di ordini e pagamenti di quei giorni per avvisare l'istituto di pagamento e valutare con il responsabile del negozio la notifica all'AEPD (l'autorità spagnola per la protezione dei dati), che il GDPR (articolo 33) richiede entro 72 ore da quando si viene a conoscenza della violazione.
Cosa è emerso sotto
Controllando i dipendenti del back office abbiamo trovato di peggio: più di una ventina di falsi superamministratori, tutti con la stessa email e il nome «Prestashop Addons», creati a raffiche di un secondo mesi prima. Questo modo di crearli — molti insieme, con la stessa email — è la firma di una SQL injection, non di qualcuno che entra dal modulo di accesso. L'origine più probabile era un controller del page builder di un tema commerciale che rispondeva a chiunque, senza verificare la sessione, e inseriva un parametro non filtrato dentro una query.
Nessun audit precedente li aveva visti. Il negozio aveva la porta aperta da mesi, e lo skimmer è stato solo ciò che alla fine si è notato.
Caso 2: i pagamenti che finivano su un altro conto
È il caso che spiega meglio perché diciamo che un attacco non si vede. Il negozio vendeva normalmente. Gli ordini con carta comparivano nel back office come pagati, con il numero di transazione, lo stato corretto e la fattura. Tutto tornava… tranne il fatto che quei soldi non sono mai arrivati sul conto del negozio.
L'attaccante aveva sostituito il file principale del modulo di pagamento della banca con una copia modificata. La modifica faceva questo:
- Sostituiva il pagamento con carta con un modulo di un gateway internazionale collegato a un conto dell'attaccante. Lasciava intatto Bizum e nascondeva un altro metodo, così che il cliente andasse dritto alla carta.
- Scriveva un record falso nelle tabelle del modulo della banca, in modo che l'ordine sembrasse un pagamento normale nel back office.
- Non si attivava per i dipendenti del negozio, né per indirizzi email che sembravano di test o dell'agenzia che si occupava della manutenzione. Chi provava il negozio vedeva il pagamento di sempre.
- Avvisava l'attaccante di ogni incasso tramite Telegram.
- Teneva le sue chiavi fuori dalla cartella web, nella directory personale dell'account di hosting.
- E poteva autodistruggersi, ripristinando i file originali che aveva conservato lì accanto.
L'accesso è avvenuto via FTP, con l'account principale dell'hosting, che aveva la stessa password del pannello. I log FTP mostravano decine di sessioni dallo stesso indirizzo per settimane, a caricare e ritoccare file come se fosse uno sviluppatore in più.
E come è stato scoperto? Per un errore dello stesso attaccante, ed è questa la parte che ci interessa. Il negozio era appena migrato a PrestaShop 9. Il codice malevolo era scritto per la versione precedente e, nel reiniettarlo, l'attaccante ha caricato i file del modulo di pagamento del vecchio negozio. In PrestaShop 9 quei file non funzionavano più: il negozio è rimasto con la pagina bianca. Senza quel guasto, il dirottamento sarebbe continuato. Incrociando gli ordini con la traccia lasciata dal codice falso sono emersi decine di incassi dirottati nell'arco di diversi mesi.
Caso 3: backdoor dove nessuno guarda
Uno skimmer o un dirottamento richiedono che l'attaccante possa scrivere nel tuo negozio. Per tornare quando vuole, lascia una web shell: un file PHP che, richiamato tramite il suo URL, gli permette di eseguire comandi o scrivere file sul tuo server. Queste sono alcune di quelle che abbiamo trovato, e fai caso a dove si trovavano:
- Una riga di 30 byte (un
evaldi ciò che arriva nella richiesta) dentro la cartella di un modulo che non era installato. La cartella era sul disco da anni, nessuno la controllava e PrestaShop 1.7 esegue qualsiasi.phpdimodules/se qualcuno lo richiede via URL. - Un file di meno di 200 byte, con un nome che iniziava con un punto, nella root del negozio. Faceva una sola cosa: scrivere sul server qualsiasi file ricevesse. Nessuno scanner automatico l'ha visto; è emerso confrontando il negozio, file per file, con una copia precedente.
- Una shell completa di oltre 80 KB (file manager, esecuzione di comandi, caricamento di file) dentro la cartella di un modulo nativo di PrestaShop, con l'intestazione di licenza di PrestaShop, autore «PrestaShop» e funzioni dai nomi innocui. Una copia identica stava in un altro modulo abbandonato, nel caso cancellassero la prima.
- Un file manager travestito da lettore di codici QR, scritto in PHP pulito e leggibile, dentro un plugin di un WordPress che condivideva l'hosting con il negozio. Da lì è stato riscritto il JavaScript del tema di PrestaShop senza mai toccare PrestaShop.
- Una riga nella cartella
vendor/di un modulo che includeva un file con estensione.jpeg… che in realtà era PHP. Il negozio aveva superato due pulizie con quella porta aperta, perché lo strumento usato escludevavendor/per impostazione predefinita. - Un loader di 6 KB dentro un modulo di spedizione per il resto legittimo, che apriva un WebSocket ed eseguiva ciò che gli veniva inviato. Sul disco non c'era altro: il codice malevolo arrivava a ogni visita e serviva a portare via l'URL del back office, con il suo token, verso un dominio esterno.
I sabotaggi di un solo carattere
Il caso che ci ha insegnato di più è stato un negozio in cui, oltre alle backdoor, l'attaccante aveva modificato due file del core di PrestaShop. In uno, un'espressione regolare che ripulisce i tag HTML era stata allentata in modo da non ripulire più nulla. Nell'altro aveva tolto la chiusura dell'indice delle classi che PrestaShop genera, così che qualsiasi cosa aggiunta in fondo venisse eseguita come codice: reinfezione automatica senza bisogno di alcun file proprio.
Nessuna regola di ricerca per pattern l'avrebbe visto. L'ha trovato il confronto byte per byte con lo ZIP ufficiale di PrestaShop della stessa versione.
Da dove entrano (quasi sempre)
Con tutti i casi sul tavolo, le vie d'ingresso si ripetono:
| Via d'ingresso | Cosa abbiamo visto | Cosa la chiude |
|---|---|---|
| Password del pannello o dell'FTP trapelata | Accesso valido al pannello dell'hosting o all'FTP principale, senza alcuna falla tecnica | Password uniche, 2FA sul pannello, SFTP, account FTP ridotti al minimo e rotazione dopo qualsiasi incidente |
| Modulo con SQL injection | Superamministratori creati a raffica; controller pubblici che non verificano nulla | Moduli aggiornati, rimozione di quelli non usati, revisione periodica dell'elenco dei dipendenti |
File PHP accessibili in modules/ | Web shell in moduli disinstallati o abbandonati | PrestaShop 9 (lo blocca di serie) o un .htaccess con eccezioni ponderate |
| Un altro sito sullo stesso hosting | Un WordPress non aggiornato usato per scrivere nel negozio | Separare gli account di hosting o tenere entrambi i siti ugualmente aggiornati |
| Il computer di chi amministra | Programmi che rubano le password salvate nel browser e nel client FTP | Non salvare le password FTP nel client, password manager, 2FA |
Nota che solo una delle cinque è un errore di programmazione «puro». Le altre riguardano la manutenzione: cosa è installato, cosa è di troppo e chi ha le chiavi.
Perché quasi tutti i negozi violati erano vecchi
Non è un caso. In quasi tutti gli incidenti che abbiamo gestito, il negozio era su PrestaShop 1.6 o 1.7, con PHP 7.x e moduli non aggiornati da anni. Questo somma rischi che si moltiplicano tra loro:
- PHP 7.4 ha smesso di ricevere patch di sicurezza alla fine del 2022, e le versioni precedenti ancora prima. Una nuova falla in PHP non verrà mai corretta per il tuo server.
- I vecchi rami di PrestaShop non ricevono più correzioni, e molti moduli di terze parti hanno smesso di pubblicare versioni per essi. Quando viene resa pubblica una vulnerabilità di un modulo diffuso, la correzione esce per la versione attuale. Se non puoi installarla perché il tuo negozio è troppo vecchio, la vulnerabilità è pubblica e il tuo negozio resta aperto.
- I negozi vecchi accumulano moduli orfani: cartelle di moduli provati e disinstallati anni fa che restano sul disco e che, in 1.7, si possono eseguire via URL. In PrestaShop 9 il
.htaccessdimodules/blocca già l'esecuzione diretta di PHP. - Più il negozio è vecchio, più fa paura toccarlo. E ciò che non si tocca non si controlla.
Aggiornare non è una garanzia assoluta: il negozio del caso 2 era già su PrestaShop 9, ma l'attaccante era entrato prima, con la password dell'hosting. Quello che un negozio aggiornato fa è chiudere le vie d'ingresso note e rendere visibile qualsiasi cambiamento anomalo. Un negozio vecchio è un negozio in cui le vie note restano aperte e in cui nessuno confronta niente con niente.
Cosa facciamo in Rekire quando un negozio è stato violato
Quando ci arriva un negozio compromesso seguiamo sempre lo stesso ordine. L'ordine conta: cancellare per primo il file malevolo è il modo più rapido perché l'attaccante torni dalla stessa strada una settimana dopo.
- Copia forense prima di toccare qualsiasi cosa. File e database, salvati fuori dal sito. Se cancelli senza copiare, perdi la prova di cosa è successo, da quando e quali dati sono stati esposti.
- Lavorare su una copia isolata. Portiamo il negozio nel nostro ambiente, senza accesso a Internet, con le email intercettate e i gateway disattivati, per analizzarlo senza il rischio che scriva ai clienti o effettui incassi.
- Confrontare con qualcosa di noto. Il core, con lo ZIP ufficiale della stessa versione di PrestaShop. I moduli, con il loro pacchetto originale. L'intero negozio, con una copia precedente se esiste. Ciò che cambia senza motivo è il primo sospettato.
- Controllare ciò che non è nei file. Dipendenti e profili, account del webservice e relativi permessi, attività pianificate del server, chiavi di configurazione dei gateway, JavaScript dentro pagine CMS, nella configurazione o nelle descrizioni dei prodotti.
- Trovare la via d'ingresso. Log di accesso web, dell'FTP e del pannello. Senza sapere da dove sono entrati, la pulizia è provvisoria.
- Chiudere l'ingresso e poi ripulire. Correggere o rimuovere il modulo vulnerabile, blindare le cartelle, eliminare gli account FTP superflui. Poi quarantena di ciò che è malevolo, che viene conservato come prova anziché essere cancellato.
- Ruotare tutte le credenziali. Pannello, FTP, database, dipendenti, chiavi API di gateway e servizi. E chiudere tutte le sessioni aperte del back office.
- Misurare il danno. Quali ordini e pagamenti sono passati dal negozio mentre il codice era attivo, per avvisare l'istituto di pagamento e decidere con il titolare del trattamento la notifica all'AEPD.
- Lasciare un sistema di sorveglianza. Una baseline pulita e avvisi che scattano nel momento stesso in cui qualcosa cambia di nuovo.
- Proporre la soluzione di fondo. Se il negozio è su una versione senza supporto, il piano di migrazione. Ripulire un negozio vecchio senza migrarlo significa guadagnare tempo, non risolvere.
RKR Security Alert: il modulo nato da tutto questo
Ciascuno degli incidenti raccontati qui ci ha costretto a fare a mano controlli che si potevano automatizzare. Da qui è nato RKR Security Alert, il modulo di sicurezza che abbiamo sviluppato in Rekire e che usiamo nei nostri audit. Funziona da PrestaShop 1.7.6 a 9.2, proprio perché i negozi che ne hanno più bisogno sono quelli che non hanno ancora migrato.
Cosa sorveglia
- I dati di pagamento e la configurazione. Salva un'istantanea della configurazione, dei moduli, dei dipendenti, degli URL del negozio e degli account del webservice, e la confronta con lo stato attuale. Non dipende dagli eventi di PrestaShop: se qualcuno modifica qualcosa direttamente via SQL, scavalcando il back office, il cambiamento compare comunque. Le modifiche ai gateway di pagamento vengono segnalate come critiche.
- I dipendenti. Creazioni, modifiche ed eliminazioni, con in evidenza gli account di superamministratore. I falsi amministratori del caso 1 avrebbero fatto scattare l'avviso il giorno stesso in cui sono stati creati.
- Gli accessi. Accesso al back office da un nuovo IP, con paese, città e avviso se si tratta di un proxy, una VPN o un data center.
- I template del pagamento. Impronta di tutti i template del checkout di tutti i temi installati, non solo di quello attivo. Il fatto che uno di essi cambi è già l'avviso: è esattamente ciò che ha tradito il caso 1.
- I moduli per versione. Se i file di un modulo cambiano senza che sia cambiata la sua versione, o ne compare uno nuovo, scatta l'avviso. È ciò che avrebbe tradito la sostituzione del modulo di pagamento del caso 2.
- Le attività pianificate e la blindatura delle cartelle.
Cosa cerca nei file
- Clonatori di pagamento, backdoor e web shell, esecuzione di comandi, offuscamento, JavaScript iniettato e codice nascosto nelle immagini.
- Web shell riconosciute per quello che sanno fare e non solo per firme: elencare, scrivere e cancellare file con un percorso ricevuto come parametro. Così si scovano quelle scritte in PHP pulito, come il falso lettore QR del caso 3.
- Confronto del core con lo ZIP ufficiale di PrestaShop, l'unica cosa che rileva la modifica di un solo carattere in un file legittimo.
- Un rilevamento critico non si può nascondere con un pattern di percorso: l'abbiamo imparato dal negozio che aveva superato due pulizie con un loader in
vendor/.
La scansione procede per parti e riprende da dove si era fermata, quindi non si interrompe per il limite di tempo del server, e ogni rilevamento porta con sé la prova: cosa ha trovato, in quale riga e da dove è raggiungibile.
La sentinella del browser
Ci sono attacchi che non lasciano nulla sul disco, come il loader via WebSocket del caso 3, o che compaiono solo quando il cliente fa qualcosa, come il modulo falso del caso 1. Per questi, il modulo include una sentinella che osserva la pagina già renderizzata nel browser: avvisa se compare un campo carta fuori da un iframe dopo il caricamento della pagina, se il checkout invia dati a un dominio nuovo con sendBeacon, fetch o XHR, se si apre un WebSocket esterno o se una pagina scrive negli appunti un comando di sistema senza che l'utente abbia cliccato nulla (la tecnica del falso captcha nota come ClickFix). La sentinella non salva mai il contenuto di quelle richieste: in un checkout conterrebbero dati di carte reali.
Pensato per negozi già compromessi
Si installa in modalità primo audit: non considera nulla «normale» finché non hai esaminato il report. Se il negozio era già infetto al momento dell'installazione, l'infezione non entra nella baseline. Gli avvisi arrivano via Telegram, classificati per gravità (puoi usare un gruppo per ciò che è importante e un altro per ciò che è informativo), e restano anche nella casella del pannello anche se non usi Telegram.
E una scelta di progettazione che ci sembra importante: niente esce dal tuo negozio. L'analisi viene fatta sul tuo server con regole incluse nel modulo. Nessun file, frammento o dato del tuo database viene inviato a nessuno.
Lista di controllo per questa settimana
Se sei arrivato fin qui, ecco cosa puoi fare senza l'aiuto di nessuno:
- Vai in Parametri Avanzati → Team e controlla ogni dipendente. Se ce n'è uno che non riconosci, soprattutto con profilo di superamministratore, considera il negozio compromesso.
- Riconcilia gli incassi dell'ultima settimana nel pannello del tuo gateway con gli ordini pagati del negozio.
- Fai un acquisto di prova con un'email che non sia del negozio, da un browser senza sessione di amministratore, e controlla se il modulo di pagamento è quello di sempre.
- Cambia la password del pannello dell'hosting e dell'FTP, in modo che non sia ripetuta da nessun'altra parte, e attiva la verifica in due passaggi del pannello se il tuo provider la offre.
- Chiedi al tuo hosting l'elenco degli account FTP ed elimina quelli che non usi.
- Guarda in Moduli cosa hai installato e via FTP quali cartelle ci sono in
modules/. Ciò che è sul disco ma non nell'elenco è di troppo. - Verifica quale versione di PrestaShop e di PHP hai. Se è PrestaShop 1.6 o 1.7, o PHP 7.x, fissa una data per la migrazione.
Migrare non è un lusso: è la misura di sicurezza più importante
Sappiamo che migrare un negozio scoraggia e mette un po' di timore. Bisogna rivedere moduli, tema, URL, pagamenti, fatture. Ma dopo aver visto dall'interno tutti questi casi, la nostra conclusione è chiara: il negozio più costoso da mantenere è quello che non si aggiorna. Un incidente costa la pulizia, la notifica, i chargeback, il tempo del team e, soprattutto, la fiducia dei clienti le cui carte sono state usate altrove.
Una migrazione a PrestaShop 9 con un PHP attuale chiude in un colpo solo le vie d'ingresso note delle vecchie versioni, ti obbliga a fare l'inventario di ciò che hai installato e ti lascia su una versione che continua a ricevere correzioni. Se in più sorvegli ciò che cambia, il prossimo tentativo si nota il giorno stesso.
Come risolverlo in PrestaShop
RKR Security Alert sorveglia configurazione, pagamenti, dipendenti, accessi, template del checkout e file, confronta il core con lo ZIP ufficiale e avvisa via Telegram appena qualcosa cambia, da PrestaShop 1.7.6 a 9.2. RKR Sentinel ti avvisa degli errori del sito prima che te li segnalino i clienti, e un negozio che all'improvviso resta con la pagina bianca, come quello del caso 2, è un errore che conviene vedere entro un minuto. RKR Order Guard evita ordini, stati di pagamento e fatture duplicati, così che ciò che dice il back office sia affidabile quando lo riconcili con la banca.
E se sospetti che il tuo negozio sia compromesso o vuoi migrarlo prima che lo sia, con i pacchetti di ore di supporto di Rekire facciamo l'audit, la pulizia con il metodo di questo articolo e la migrazione a PrestaShop 9.