CASO DI STUDIO · EDITORIA

L’inside job: l’account del redattore che simulava i defacement

  • CLIENTEQuotidiano online locale (dati anonimizzati)
  • PIATTAFORMAWordPress

Banner offensivi e titoli riscritti di notte, nessun malware: le revisioni portavano all’account di un ex collaboratore ancora Editor. Chiuso entro 24 ore.

Una pagina di giornale online con un banner rosso di traverso, accanto a un badge da redattore con una chiave ancora appesa e una lente che collega i due con una linea tratteggiata

Il contesto

Un quotidiano online locale, con una redazione di una decina di giornalisti e una rete di collaboratori esterni che scrivono da casa. Il sito è un WordPress ben tenuto, su un server virtuale seguito da un fornitore informatico: core e plugin aggiornati, backup giornalieri, un firewall applicativo. Gli account erano una quarantina e, «per non perdere tempo con i permessi», quasi tutti avevano il ruolo di Editor, compresi i collaboratori occasionali. Per riservatezza, nome della testata, territorio e ogni dettaglio che permetterebbe di identificare le persone coinvolte sono stati omessi o modificati.

I sintomi

Da metà giugno la testata aveva subito sette episodi che tutti chiamavano «defacement». Sempre di notte, tra l’una e le quattro: in alcuni articoli vecchi comparivano banner con frasi offensive verso l’amministrazione comunale e verso la stessa redazione, e in due occasioni i titoli degli articoli in evidenza in homepage erano stati riscritti in tono provocatorio. La mattina qualcuno se ne accorgeva, correggeva a mano e il giorno dopo tutto sembrava tornato normale, fino all’episodio successivo.

Il fornitore aveva fatto tutto ciò che si fa di solito: cambiato la password dell’amministratore, reinstallato i plugin, eseguito due scanner diversi, ripristinato un backup. Gli scanner non trovavano nulla, e gli episodi continuavano. La convinzione di tutti era che dietro ci fosse un gruppo di attaccanti esterni, abbastanza bravi da non lasciare tracce. A fine luglio la testata ci ha contattato con il servizio entro 24 ore, chiedendo di trovare la backdoor.

Cosa abbiamo trovato a livello applicativo

Prima di tutto, cosa non abbiamo trovato. Il core e i plugin corrispondevano esattamente ai pacchetti ufficiali, nessun file PHP fuori posto negli upload, nessun file nella cartella mu-plugins, nessuna opzione del database con codice nascosto, nessun amministratore sconosciuto, come quelli descritti nell’articolo sugli amministratori fantasma. Nei log non c’era traccia di tentativi di sfruttare vulnerabilità nelle notti degli episodi.

# Integrità di core e plugin rispetto ai pacchetti ufficiali
wp core verify-checksums
wp plugin verify-checksums --all

# Chi può pubblicare e scrivere HTML senza filtri
wp user list --role=editor --fields=ID,user_login,user_registered
wp user list --role=administrator --fields=ID,user_login,user_registered

La risposta era in un posto che gli scanner non guardano: le revisioni. WordPress salva una revisione a ogni modifica di un articolo, e la revisione registra anche l’utente che l’ha fatta. Tutte le modifiche delle sette notti erano state fatte da un unico account, con ruolo Editor: quello di un collaboratore esterno il cui contratto non era stato rinnovato a fine maggio. L’account non era mai stato disattivato, e il ruolo di Editor, su un’installazione singola, include la capacità unfiltered_html, che secondo la documentazione di WordPress sui ruoli permette di inserire HTML e perfino JavaScript nei contenuti. I banner non erano un’iniezione: erano blocchi HTML inseriti dall’editor, esattamente come farebbe un redattore.

Questo spiega anche perché settimane di ricerche non avevano portato a nulla. Uno scanner cerca codice malevolo nei file e nel database, e qui il «codice» era un normale blocco HTML salvato da un utente autorizzato a farlo. Cambiare la password dell’amministratore non toccava l’account usato, e ripristinare un backup rimetteva a posto gli articoli ma lasciava l’account attivo, pronto per l’episodio successivo. Anche la scelta dell’orario aveva contribuito all’equivoco: modifiche notturne, dai toni aggressivi, hanno l’aspetto tipico di un attacco esterno, e nessuno aveva pensato di guardare chi risultasse autore delle modifiche.

# Revisioni create da un utente, in ordine di data
wp post list --post_type=revision --author=27 --fields=ID,post_parent,post_date --orderby=date --order=ASC

# Sessioni ancora valide dell'utente: data di accesso, scadenza, IP, browser
wp user session list 27 --fields=login_time,expiration_time,ip,ua

# Password per le applicazioni, che resterebbero valide anche cambiando la password
wp user application-password list 27

Cosa abbiamo trovato a livello di sistema

Anche a livello di sistema il server era pulito: nessuna voce estranea nei crontab, nessun processo anomalo, nessuna chiave SSH sconosciuta, nessuna connessione sospetta in uscita. È un risultato importante quanto gli altri, perché spiegava perché la ricerca di una backdoor non portava a nulla: non ce n’era bisogno.

Il sistema, però, conservava le prove. Abbiamo incrociato quattro fonti, ciascuna con il proprio orario, dopo averle riportate tutte allo stesso fuso orario:

  • i log di accesso del server web, in cui ogni notte comparivano un POST a wp-login.php con risposta di reindirizzamento, cioè un accesso riuscito, e poco dopo una serie di richieste POST /wp-json/wp/v2/posts/…, il modo in cui l’editor a blocchi salva gli articoli;
  • le sessioni di WordPress, salvate tra i metadati dell’utente, con data di accesso, indirizzo IP e browser di ogni sessione ancora valida;
  • le revisioni, con autore e orario di ogni modifica;
  • i log del firewall applicativo, che registravano gli accessi riusciti all’area riservata con utente e indirizzo.

Il metodo è lo stesso descritto nell’articolo sui log di accesso, applicato a un attacco che non usa nessuna vulnerabilità. In sei episodi su sette le richieste arrivavano da indirizzi di un servizio VPN commerciale, sempre con lo stesso browser. Nel primo episodio, a metà giugno, l’accesso era partito invece da un indirizzo di una connessione domestica di un operatore italiano; da quello successivo in poi, solo VPN. Il nome utente, il browser e la sequenza delle azioni erano gli stessi in tutti i casi.

Schema della correlazione tra quattro fonti, una per riga: log di accesso del server web, sessioni di WordPress, revisioni degli articoli, log del firewall applicativo. Su una linea del tempo notturna dall’una alle quattro, i punti delle quattro fonti si allineano nello stesso minuto: accesso riuscito, sessione aperta con lo stesso IP e lo stesso browser, revisioni firmate dallo stesso utente con ruolo Editor. Sotto, sette episodi tra metà giugno e fine luglio: il primo da un IP di una connessione domestica, gli altri sei da indirizzi di un servizio VPN. Un riquadro ricorda che un indirizzo IP identifica una connessione, non una persona.
Nessuna fonte da sola bastava: è l’allineamento delle quattro, nello stesso minuto, a rendere solida la ricostruzione.

Come abbiamo gestito la scoperta

A questo punto il lavoro tecnico diventava delicato. Quello che i dati dimostrano è che le modifiche sono state fatte con le credenziali di un certo account, da certi indirizzi, in certi orari. Non dimostrano chi fosse seduto alla tastiera: le credenziali potevano essere state condivise, annotate da qualche parte o rubate, e un indirizzo IP identifica una connessione, non una persona. Attribuire un’azione a qualcuno non è compito nostro, e non abbiamo mai nominato né sospettato nessuno nelle comunicazioni.

Abbiamo quindi fatto tre cose, in quest’ordine:

  1. conservato le prove prima di toccare qualsiasi cosa: copie dei log, un dump del database, l’esportazione delle revisioni e dei metadati dell’account, ciascuna con la propria impronta crittografica e l’annotazione di chi l’ha raccolta, quando e da dove. Gli originali non sono stati modificati;
  2. consegnato una relazione fattuale alla direzione della testata e al suo legale: una cronologia degli eventi con le fonti di ogni riga, senza conclusioni sulle persone. Le valutazioni legali, compresa l’opportunità di una denuncia, sono rimaste interamente a loro;
  3. chiuso l’accesso, d’accordo con il legale, subito dopo la raccolta delle prove: bloccare l’account prima avrebbe rischiato di perdere le sessioni ancora attive, che erano esse stesse un’evidenza.

La chiusura vera e propria è stata rapida. L’account è stato declassato a nessun ruolo e le sue sessioni distrutte; poiché nella redazione le password circolavano a voce, le abbiamo fatte cambiare a tutti gli utenti con permessi di pubblicazione. Gli articoli modificati sono stati riportati alla revisione precedente all’intervento, verificando uno per uno il risultato.

# Toglie ogni ruolo all'account e chiude tutte le sue sessioni
wp user remove-role 27 editor
wp user session destroy 27 --all

# Ripristina un articolo alla revisione indicata (ID della revisione)
wp eval 'wp_restore_post_revision( 18342 );'

L’hardening

Il problema di fondo non era tecnico, era organizzativo, e l’hardening è stato soprattutto questo:

  • ruoli rivisti con il principio del minimo privilegio: i collaboratori esterni sono diventati Autori, che possono modificare solo i propri articoli, o Collaboratori, i cui testi passano da un redattore prima della pubblicazione. Il ruolo di Editor è rimasto a tre caporedattori;
  • HTML senza filtri disattivato per tutti con la costante DISALLOW_UNFILTERED_HTML in wp-config.php; i pochi blocchi che richiedono codice, come i widget dei sondaggi, passano da un blocco dedicato gestito dall’amministratore;
  • una procedura di uscita collegata all’amministrazione: il giorno in cui un contratto termina l’account viene disattivato, i contenuti riassegnati e le sessioni chiuse, con una revisione trimestrale di tutti gli account;
  • autenticazione a due fattori obbligatoria per chiunque possa pubblicare, e password personali, mai condivise;
  • un registro delle attività che annota accessi, modifiche e cambi di ruolo e li invia fuori dal server, con un avviso quando un articolo in homepage viene modificato di notte.
Confronto dei ruoli prima e dopo l’intervento. Prima: circa quaranta account, quasi tutti Editor con HTML senza filtri, account di ex collaboratori ancora attivi, password condivise, nessun registro delle attività. Dopo: tre Editor, gli altri redattori Autori, i collaboratori esterni Collaboratori con revisione prima della pubblicazione, HTML senza filtri disattivato per tutti, due fattori obbligatori, account disattivato il giorno della fine del contratto, registro delle attività inviato fuori dal server e revisione trimestrale degli account.
Meno Editor, nessun HTML senza filtri, un account che si chiude insieme al contratto: tre regole che avrebbero evitato tutti e sette gli episodi.

Il risultato

L’analisi, la messa in sicurezza dell’account e il ripristino degli articoli si sono chiusi entro le 24 ore previste dal servizio. Da allora non si è verificato nessun altro episodio, e il registro delle attività non ha segnalato modifiche notturne non previste. La testata ha ricevuto due documenti distinti: la relazione fattuale con le prove per il legale e un rapporto tecnico con gli interventi e le nuove regole sui ruoli, da condividere con la redazione.

Il fornitore informatico, che per settimane aveva cercato un malware che non c’era, ha adottato la procedura di uscita anche per gli altri clienti che segue.

Cosa insegna questo caso

Non tutte le compromissioni passano da una vulnerabilità. Un account legittimo, con più permessi del necessario e dimenticato attivo dopo la fine di un rapporto, fa gli stessi danni di una webshell, e in più non lo trova nessuno scanner, perché dal punto di vista del software non c’è nulla di anomalo. Per questo, quando un sito viene «attaccato» senza che si trovino file malevoli, le prime domande da farsi riguardano gli account: chi ha accesso, con quale ruolo, da quando e fino a quando.

La seconda lezione riguarda il metodo: davanti a un possibile caso interno, la tentazione è bloccare subito tutto e dire un nome. Conservare prima le prove, descrivere solo i fatti e lasciare le valutazioni a chi ne ha la competenza protegge l’azienda, le persone coinvolte e il valore stesso delle prove.

Rimozionemalware.com è il servizio di bonifica dei siti WordPress di Managed Server S.r.l., attiva dal 2005 nella gestione di server e hosting. Analizziamo l’applicazione e il sistema, anche quando il problema non è un malware, con tempi garantiti di 6, 12 o 24 ore per installazione, calcolati dalla ricezione degli accessi. Per un caso simile puoi contattarci.

IL PROSSIMO PASSO

Il tuo sito
è infetto?

Ogni ora conta: il malware continua a colpire visitatori e clienti, e Google, l’hosting e le blacklist non aspettano. Scegli il piano, paga online e condividi gli accessi: la bonifica parte subito, a prezzo fisso e con tempi garantiti.

Richiedi la bonifica

Ti porta ai piani: bonifica entro 6, 12 o 24 ore dalla ricezione degli accessi.

MANAGED SERVER S.R.L.info@rimozionemalware.com +39 02 5656 9681

Lunedì – venerdì · 09:30 – 19:30

Preferisci un modulo online?
Contattaci su managedserver.it ↗