Il consiglio che vi hanno dato per dieci anni ha smesso di funzionare
“Tieni aggiornati core, plugin e temi.” È stato il pilastro della sicurezza WordPress per un decennio. Nel 2026 è diventato, in alcuni scenari, il vettore di compromissione.
A giugno 2026 tre incidenti distinti hanno colpito l’ecosistema nella stessa settimana, e in tutti e tre il codice malevolo è arrivato attraverso il canale ufficiale di aggiornamento o distribuzione, esattamente il percorso che ai gestori di siti viene detto di considerare affidabile: ad Awesome Motive è stata sottratta una chiave CDN poi usata per avvelenare plugin su oltre un milione di siti, ShapedPlugin ha subito la compromissione della propria build pipeline distribuendo una backdoor tramite gli aggiornamenti Pro licenziati, e un ricercatore ha ricostruito la storia di un singolo operatore che ha mantenuto backdoor nel repository WordPress.org per tredici anni.
Le vittime non erano amministratori negligenti. Erano amministratori diligenti.
Questo articolo è scritto per chi gestisce siti aziendali, e-commerce, portali di filiera — non per il blog personale. L’assunto di partenza è quello che uso in ogni consulenza: il vostro sito WordPress è un’applicazione PHP internet-facing con privilegi di scrittura sul proprio codice. Trattatelo come tale.
Indice
- Il quadro delle minacce 2026, con i numeri
- Il nuovo dominante: la supply chain
- L’acceleratore: exploit a velocità macchina
- Kill chain WordPress, fase per fase, con contromisure
- L’architettura di riferimento: deploy immutabile e egress filtering
- Detection engineering: cosa loggare e cosa cercare
- Runbook di Incident Response (0-1h / 1-24h / 72h)
- Governance, NIS2, GDPR e rischio di terza parte
- Matrice di controllo e checklist di audit
- KPI: come si misura se state migliorando
1. Il quadro delle minacce 2026, con i numeri
I dati aggregati da Patchstack, Wordfence e Sucuri delineano un problema strutturale, non episodico. Le vulnerabilità nei plugin WordPress hanno raggiunto oltre 250 divulgazioni settimanali nel 2026 — circa 36 al giorno — con il 43% sfruttabile senza autenticazione e il 23% ancora privo di patch a trenta giorni dalla divulgazione; WordPress ha rappresentato il 96% di tutte le vulnerabilità CMS divulgate nell’anno, e il grosso delle compromissioni è imputabile all’ecosistema dei plugin, non al core.
Sul lato tempistiche, il dato che dovrebbe ridisegnare ogni vostra procedura: secondo il report State of WordPress Security 2026 di Patchstack il tempo mediano che intercorre prima dello sfruttamento di massa di una vulnerabilità ad alto impatto è di cinque ore, e il 46% delle vulnerabilità nei plugin non dispone di una patch nel momento in cui viene resa pubblica.
Cinque ore. E quasi una vulnerabilità su due non ha una correzione disponibile quando diventa di dominio pubblico. Il modello “leggo il bollettino la mattina e aggiorno nel pomeriggio” è aritmeticamente perdente.
Nemmeno il core è più un porto sicuro. WordPress 7.0.2, rilasciato il 17 luglio 2026, ha corretto CVE-2026-60137 e CVE-2026-63030, concatenabili in un percorso di site takeover non autenticato: CVE-2026-60137 è entrata nel catalogo Known Exploited Vulnerabilities della CISA, Wordfence ha osservato milioni di tentativi di sfruttamento e Patchstack ha rilevato attacchi circa novanta minuti dopo il rilascio; meno di tre settimane dopo la 7.0.3 ha portato altre dodici correzioni, tra cui CVE-2026-64638, un XSS riflesso pre-autenticazione.
Novanta minuti tra patch e sfruttamento. Il rilascio della patch è il segnale di partenza per gli attaccanti: la diff del commit è la documentazione dell’exploit.
I casi che dovete conoscere
| Componente | CVE | CVSS | Natura |
|---|---|---|---|
| Elementor Pro | CVE-2026-32475 | 9.8 | Arbitrary file upload nella gestione dei form, sfruttata attivamente |
| Forminator Forms | CVE-2026-15748 | 9.8 | Upload di file eseguibili da parte di attaccanti non autenticati |
| The Events Calendar | CVE-2026-78006 | 9.8 | Oltre 600.000 installazioni; reset della password admin e RCE senza login |
| GiveWP | CVE-2026-82222 | 10.0 | Esecuzione di comandi arbitrari via helper di unserialize difettoso e gadget chain |
| WPMU DEV Dashboard | CVE-2026-76581 | 9.8 | Bypass di autenticazione |
Nota il pattern per chi fa threat modeling: quattro su cinque sono classi che un WAF generico intercetta male. L’upload arbitrario di file e la PHP Object Injection non hanno firme stabili — il payload è un file legittimo o un blob serializzato. Se la vostra strategia è “ho Cloudflare davanti”, state coprendo SQLi e XSS e lasciando scoperte le due classi che nel 2026 producono più takeover.
2. Il nuovo dominante: la supply chain
Il caso ShapedPlugin (giugno 2026)
La build pipeline automatizzata di ShapedPlugin è stata violata intorno al 21 maggio 2026; gli attaccanti hanno iniettato codice malevolo nelle versioni Pro di almeno tre plugin popolari, distribuiti poi attraverso il sistema di licenze del vendor ai clienti che aggiornavano normalmente, e l’attacco è rimasto non rilevato per circa tre settimane. L’incidente è tracciato come CVE-2026-10735 con CVSS 9.8; le versioni gratuite nel repository ufficiale non risultavano interessate, perché l’attacco ha colpito esclusivamente il canale di distribuzione premium.
Il payload merita attenzione tecnica. Si trattava di un loader chiamato LicenseLoader.php che sottraeva credenziali WordPress, segreti di secondo fattore, credenziali di database e SMTP e tre mesi di dati ordini WooCommerce, creando inoltre un account amministratore nascosto denominato wp_support_sys.
Leggete di nuovo: segreti TOTP esfiltrati. Il vostro 2FA, dopo un incidente di questo tipo, non è più un controllo: è un elenco di seed in mano all’avversario. Per questo il playbook di risposta impone di ruotare tutte le password admin, le credenziali di database e le chiavi API e, in modo critico, di revocare e rigenerare i segreti 2FA di ogni utente, poiché i seed TOTP esistenti vanno considerati compromessi.
Il caso repository (aprile 2026)
In una finestra di 72 ore ad aprile 2026 un attacco coordinato ha compromesso oltre 25 plugin sul repository WordPress.org, esponendo circa 800.000 siti: gli attaccanti hanno ottenuto accesso in push per tre vie distinte — acquistando plugin legittimi dagli sviluppatori, facendo credential stuffing sugli account developer e sfruttando infrastruttura CI condivisa tra team diversi — e hanno pubblicato aggiornamenti di versione minore contenenti PHP offuscato che creava account amministratore nascosti, trasmetteva le credenziali del sito a server di comando e controllo e installava backdoor persistenti. Molti siti hanno applicato gli aggiornamenti automaticamente durante la notte, senza alcuna revisione.
E nel caso Awesome Motive, Patchstack ha registrato 271 tentativi di creazione di amministratori fraudolenti su 13 siti nella finestra 14-15 giugno, in larga parte contro l’endpoint REST wp/v2/users, e il dominio di comando e controllo era stato registrato il 28 aprile 2026 — sei settimane di preparazione.
Cosa cambia operativamente
La risposta dell’ecosistema è arrivata: il 5 giugno 2026 è stata annunciata l’iniziativa “Protect The Shire”, che introduce un periodo di raffreddamento di 24 ore prima che un rilascio di plugin o tema — sulle oltre 78.000 estensioni della directory — raggiunga i siti tramite aggiornamento automatico.
Ma il controllo più efficace è vostro, non loro. In ogni incidente del 2026, i siti che aggiornavano con qualche giorno di ritardo non hanno mai installato la versione malevola: la finestra di attesa di 48-72 ore è la singola difesa a più alto impatto contro gli attacchi alla supply chain dei plugin.
Qui nasce il paradosso operativo del 2026, ed è il punto in cui quasi tutti gli articoli che leggete sbagliano:
| Tipo di aggiornamento | Politica corretta | Perché |
|---|---|---|
| Patch di sicurezza per CVE nota e sfruttata | Immediato (ore) | Lo sfruttamento di massa parte in ~5 ore |
| Release ordinaria (feature, minor, bugfix) | Attesa 48-72h + verifica | È la finestra in cui viaggiano i backdoor supply chain |
| Core WordPress, minor security | Automatico, immediato | Firmato e distribuito dal canale core, storicamente affidabile |
| Plugin premium da vendor singolo | Attesa + diff del pacchetto | Canale con controlli più deboli del repository ufficiale |
Non è “aggiorna sempre subito”. È aggiorna subito ciò che è sfruttato, attendi e verifica tutto il resto. La distinzione richiede threat intelligence — non si può fare guardando la pagina “Aggiornamenti” del pannello.
3. L’acceleratore: exploit a velocità macchina
Il contesto più ampio spiega perché la finestra si è compressa. Nel secondo trimestre 2026 il Google Threat Intelligence Group ha osservato attori compromettere una risorsa cloud e poi pianificare, costruire ed eseguire una campagna di raccolta massiva di credenziali abilitata da agenti in meno di sei ore, con una riduzione drastica della latenza introdotta dall’intervento umano.
Unit 42 ha documentato una dinamica analoga: un attaccante umano ha usato AI di frontiera per violare una rete enterprise in modo largamente autonomo nell’ambito di un attacco a scopo di riscatto, con chiamate LLM a più agenti in parallelo, file Markdown strutturati per passare informazioni tra agenti e sessioni, e script custom generati dall’AI per gestire le operazioni dinamiche — su una linea temporale operativa di dieci ore.
Il quadro macro è impietoso per chi difende: la telemetria Mandiant colloca il tempo medio di weaponizzazione intorno ai cinque giorni, mentre il Verizon DBIR 2026 rileva un tempo mediano di 43 giorni per applicare una patch, e lo sfruttamento di vulnerabilità è ormai il primo vettore di accesso iniziale, all’origine del 31% delle violazioni.
Cinque giorni contro quarantatré. Su WordPress, con lo sfruttamento di massa a cinque ore, il divario è ancora peggiore.
Implicazione architetturale: se non potete vincere sulla velocità di patch — e non potete — dovete vincere sulla riduzione dell’impatto post-exploit. Assumete che l’exploit riuscirà. Progettate perché non serva a nulla. È esattamente il principio “assume breach”, applicato a un CMS.
4. Kill chain WordPress, fase per fase
Fase 1 — Ricognizione
Cosa fa l’attaccante. Fingerprinting con whatweb, wappalyzer, httpx. Enumerazione plugin e versioni via WPScan, confrontando hash di file JS/CSS statici con database CVE. Enumerazione utenti via /wp-json/wp/v2/users, /?author=1, sitemap autore, feed RSS, e — spesso trascurato — la response timing differenziale di wp-login.php, che rivela se uno username esiste. OSINT su breach pregressi per il dominio. Nel 2026 tutto questo è un singolo job parallelizzato su decine di migliaia di target.
Contromisure.
// mu-plugin: 00-hardening.php (in wp-content/mu-plugins/)
// Chiude l'endpoint REST utenti agli anonimi
add_filter('rest_endpoints', function ($endpoints) {
if (is_user_logged_in()) return $endpoints;
unset($endpoints['/wp/v2/users']);
unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
return $endpoints;
});
// Blocca l'enumerazione ?author=N
add_action('parse_request', function ($q) {
if (!is_admin() && !empty($q->query_vars['author'])) {
wp_safe_redirect(home_url(), 301);
exit;
}
});
// Rimuove il generator e la versione dagli asset
remove_action('wp_head', 'wp_generator');
add_filter('style_loader_src', fn($s) => remove_query_arg('ver', $s));
add_filter('script_loader_src', fn($s) => remove_query_arg('ver', $s));
// Uniforma i messaggi di errore del login (anti user-enumeration)
add_filter('login_errors', fn() => __('Credenziali non valide.'));
Perché mu-plugins e non functions.php: i must-use plugin non sono disattivabili dal pannello, sopravvivono al cambio tema e non vengono sovrascritti dagli aggiornamenti. È la posizione giusta per i controlli di sicurezza.
Nota da red team. L’offuscamento dello slug di login (
/wp-login.php→/accesso-sicuro) — presente in molte guide, inclusa la bozza che ho ricevuto — è security by obscurity con beneficio marginale. Riduce il rumore dei bot generici, non ferma un attaccante mirato: lo slug trapela dawp_login_url()in email transazionali, redirect e header. Fatelo se volete log più puliti, non consideratelo un controllo.
Fase 2 — Accesso iniziale
Cosa fa l’attaccante. Credential stuffing (non brute force cieco: liste da breach correlate al dominio). Abuso di XML-RPC system.multicall per centinaia di tentativi in una singola richiesta HTTP, bypassando il rate limiting per-richiesta. Phishing mirato ai redattori con finti avvisi di sicurezza di plugin. Session hijacking su cookie senza flag adeguati. E — crescente — compromissione dell’account dell’agenzia che gestisce il sito: un solo set di credenziali per trenta siti clienti.
Contromisure.
# Nginx: XML-RPC off (se non usate Jetpack o app legacy)
location = /xmlrpc.php { deny all; access_log off; log_not_found off; }
# Rate limiting sul login
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=20r/m;
location = /wp-login.php {
limit_req zone=wplogin burst=5 nodelay;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
}
Sul secondo fattore, la raccomandazione del 2026 non è più “attivate il 2FA” ma attivate WebAuthn/FIDO2, non TOTP. Tre ragioni: il caso ShapedPlugin ha dimostrato che i seed TOTP sono esfiltrabili da una backdoor lato server; le passkey sono legate all’origine e quindi resistenti al phishing in reverse proxy (Evilginx e simili); non c’è un segreto condiviso da rubare. TOTP resta accettabile come fallback, non come controllo primario per ruoli Administrator ed Editor.
Aggiungete: sessioni admin limitate nel tempo, FORCE_SSL_ADMIN, cookie con Secure/HttpOnly/SameSite=Lax, e allowlist IP su /wp-admin e /wp-login.php dove l’operatività lo consente (sede, VPN aziendale). Quest’ultima, sui siti corporate, elimina da sola l’intera fase 2 per gli attori non mirati.
Fase 3 — Sfruttamento
Cosa fa l’attaccante. Le classi che contano oggi:
- Arbitrary File Upload → RCE. Validazione debole di estensione o MIME nei form builder. Il classico
shell.php.jpg, o l’upload di.htaccessche rimappaAddType application/x-httpd-php .jpg. - PHP Object Injection. Il caso GiveWP:
unserialize()su input controllato dall’attaccante, con gadget chain presenti nel codice spedito dal plugin stesso. Nessun WAF di firma la intercetta in modo affidabile. - Privilege Escalation via AJAX/REST. Endpoint
wp_ajax_nopriv_*che non verificanocurrent_user_can()o il nonce. Da Subscriber ad Administrator in una richiesta. - SQL Injection in plugin che costruiscono query senza
$wpdb->prepare(). - Stored XSS in campi recensione/commento, con furto del cookie amministratore.
Contromisure — quelle che contano davvero.
# wp-content/uploads/.htaccess — nessun PHP eseguibile negli upload
<FilesMatch "\.(?i:php|phtml|phar|php[0-9]|inc|hphp)$">
Require all denied
</FilesMatch>
# Neutralizza gli .htaccess caricati dall'attaccante
AllowOverride None
; php.ini — riduzione della superficie post-exploit
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,dl
open_basedir = /var/www/sito/:/tmp/:/usr/share/php/
expose_php = Off
allow_url_fopen = Off
allow_url_include = Off
session.cookie_httponly = 1
session.cookie_secure = 1
session.cookie_samesite = Lax
allow_url_fopen = Off merita una riga sua: spezza la maggior parte dei loader a due stadi, quelli che scaricano il payload reale da un server esterno. È la differenza tra una backdoor funzionante e un file inerte.
Content Security Policy — introducetela in Report-Only per due settimane, poi enforcing:
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-$request_id'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'; upgrade-insecure-requests" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), interest-cohort=()" always;
object-src 'none' e base-uri 'self' bloccano due tecniche di bypass XSS che quasi nessuno configura. Attenzione: WordPress e molti plugin emettono script inline — servirà una strategia a nonce o un periodo di tuning. Fatelo, non rinunciate: la CSP è ciò che trasforma uno stored XSS da “furto della sessione admin” a “voce nel log”.
Fase 4 — Persistenza
Cosa fa l’attaccante. Utente amministratore fantasma (wp_support, admin_backup, wp_support_sys nel caso ShapedPlugin), spesso nascosto dalla UI con un filtro su pre_user_query. Backdoor in wp-config.php, nel functions.php del tema, in un file innocuo dentro uploads/, o — la posizione preferita perché invisibile nel pannello — in wp-content/mu-plugins/. Cron job malevoli via wp_schedule_event che reinstallano la shell ogni ora. Injection in wp_options con autoload='yes', così il payload viene caricato su ogni richiesta senza toccare un solo file PHP. Offuscamento con base64_decode, gzinflate, str_rot13, create_function.
Contromisure.
# Verifica integrità contro i checksum ufficiali
wp core verify-checksums
wp plugin verify-checksums --all
# File PHP modificati negli ultimi 7 giorni
find /var/www/sito -name '*.php' -newermt '-7 days' -printf '%T+ %p\n' | sort
# Pattern di offuscamento tipici
grep -RIlE --include='*.php' \
'eval\s*\(|base64_decode|gzinflate|str_rot13|assert\s*\(|create_function|\$\{?_(POST|GET|REQUEST|COOKIE)' \
/var/www/sito
# Contenuti eseguibili negli upload (non dovrebbero esistere)
find /var/www/sito/wp-content/uploads -type f \( -name '*.php*' -o -name '.htaccess' \)
# Cron e mu-plugins
wp cron event list
ls -la /var/www/sito/wp-content/mu-plugins/
Gli amministratori vanno cercati nel database, non nella UI — perché la UI può essere stata filtrata:
SELECT u.ID, u.user_login, u.user_email, u.user_registered
FROM wp_users u
JOIN wp_usermeta m ON m.user_id = u.ID
WHERE m.meta_key = 'wp_capabilities'
AND m.meta_value LIKE '%administrator%'
ORDER BY u.user_registered DESC;
-- Opzioni autoload anomale: un payload da 200 KB salta all'occhio
SELECT option_name, LENGTH(option_value) AS bytes
FROM wp_options WHERE autoload = 'yes'
ORDER BY bytes DESC LIMIT 25;
E il controllo che chiude la fase:
// wp-config.php
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true); // blocca install/update dal pannello
define('FORCE_SSL_ADMIN', true);
define('WP_DEBUG_DISPLAY', false);
define('AUTOMATIC_UPDATER_DISABLED', true); // se gestite via CI/CD
DISALLOW_FILE_MODS è il punto di svolta: se il pannello non può scrivere plugin, una sessione admin rubata non basta più a ottenere RCE. L’attaccante deve trovare una seconda vulnerabilità a livello file system. Ha un costo operativo (gli aggiornamenti passano da WP-CLI o dalla pipeline) ed è esattamente il costo che dovete essere disposti a pagare.
Fase 5 — Movimento laterale
Cosa fa l’attaccante. Legge wp-config.php per DB_USER/DB_PASSWORD, credenziali SMTP, chiavi API di gateway di pagamento e CRM. Scansiona la subnet interna. Riusa le credenziali DB contro altri host. Su hosting condiviso multi-tenant, salta ai vhost adiacenti se i permessi sono lassi. Cerca chiavi SSH nella home dell’utente web.
Contromisure architetturali.
- Il web server in DMZ o subnet dedicata; regole verso il DB solo sulla porta specifica e solo dall’IP del web server.
- Utente MySQL con permessi minimi:
SELECT, INSERT, UPDATE, DELETEsul solo schema del sito. NienteFILE, nienteSUPER, nienteGRANT.FILEin particolare trasforma una SQLi in lettura arbitraria del file system. - Un utente di sistema per ogni sito; PHP-FPM pool separati;
open_basedirper pool. Su hosting condiviso, verificate che sia così — spesso non lo è. - Nessuna chiave SSH nella home dell’utente che esegue PHP.
- Segreti fuori da
wp-config.phpdove possibile: variabili d’ambiente iniettate dal supervisore di processo, o un secrets manager.
Fase 6 — Azioni sugli obiettivi
SEO spam e doorway pages, defacement, esfiltrazione del database, cryptojacking, uso del server come nodo botnet, e — la variante 2026 su e-commerce — skimmer JavaScript lato client che intercetta i dati di pagamento (Magecart applicato a WooCommerce), spesso iniettato non nei file ma in wp_options o in un widget, per sopravvivere al confronto dei checksum.
Contromisure. Backup immutabili (object lock su S3/B2, non “una copia su un’altra cartella dello stesso server”), testati con restore reale ogni trimestre. Monitoraggio del traffico in uscita: un picco di egress è il segnale più affidabile di esfiltrazione. Subresource Integrity sugli script di terze parti. E, per gli e-commerce, monitoraggio esterno della pagina di checkout che confronti gli script caricati con una baseline approvata.
5. L’architettura di riferimento: deploy immutabile ed egress filtering
Qui usciamo dal “hardening di WordPress” ed entriamo nell’architettura. Sono i due controlli che, in un audit, distinguono un sito difeso da un sito con dei plugin di sicurezza installati.
5.1 Filesystem non scrivibile dal processo web
Il difetto originale di WordPress è che il codice dell’applicazione e i dati dell’applicazione vivono nella stessa directory, scrivibile dallo stesso utente. Si corregge così:
# Proprietà al deployer, non al processo PHP
chown -R deploy:www-data /var/www/sito
find /var/www/sito -type d -exec chmod 750 {} \;
find /var/www/sito -type f -exec chmod 640 {} \;
# Unica eccezione scrivibile: gli upload
chown -R www-data:www-data /var/www/sito/wp-content/uploads
chmod 750 /var/www/sito/wp-content/uploads
# wp-config leggibile solo dal deployer e dal gruppo
chmod 440 /var/www/sito/wp-config.php
Risultato: una web shell caricata negli upload non può essere eseguita (per la regola .htaccess/Nginx) e non può scrivere altrove nel codice. La persistenza via file diventa impossibile senza una escalation locale.
5.2 Gestione a codice con Composer
Plugin e temi dichiarati in composer.json con versione pinnata, installati in pipeline, mai dal pannello:
{
"require": {
"johnpbloch/wordpress-core": "7.0.3",
"wpackagist-plugin/woocommerce": "9.8.2"
}
}
Vantaggi diretti: avete un SBOM dell’applicazione; ogni aggiornamento passa da una pull request revisionabile; il rollback è un git revert; e il diff del pacchetto è ispezionabile prima del deploy — che è l’unico modo pratico di intercettare un backdoor supply chain nella finestra dei 48-72 ore.
5.3 Egress filtering — il controllo più sottovalutato
Nella stragrande maggioranza delle architetture che audito, il web server può aprire connessioni verso qualsiasi IP su Internet. È un regalo.
Quasi ogni catena di attacco moderna ha bisogno dell’egress: il loader a due stadi scarica il payload, la backdoor contatta il C2, l’esfiltrazione trasmette il dump, il miner raggiunge il pool, la botnet riceve gli ordini. Bloccate l’egress in default-deny con allowlist (repository degli aggiornamenti, gateway di pagamento, SMTP, CDN) e disarmate contemporaneamente tutte e cinque le catene — incluse quelle che sfruttano zero-day che non conoscete.
# Esempio concettuale (nftables): default deny in uscita per l'utente web
nft add rule inet filter output meta skuid www-data ip daddr @allowlist accept
nft add rule inet filter output meta skuid www-data log prefix "EGRESS-DENY " drop
Ogni riga in quel log è un incidente potenziale, rilevato senza alcuna firma. È detection gratuita.
5.4 Difesa in profondità, schema riassuntivo
| Livello | Controllo | Cosa neutralizza |
|---|---|---|
| Perimetro | CDN, WAF, DDoS, rate limiting, allowlist admin | Ricognizione, brute force, exploit noti |
| Trasporto | TLS 1.3, HSTS preload, cookie hardening | Hijacking, downgrade |
| Applicazione | CSP, mu-plugin hardening, privilegio minimo, WebAuthn | XSS, CSRF, privilege escalation |
| Runtime | disable_functions, open_basedir, allow_url_fopen=Off | RCE post-exploit, loader a due stadi |
| Filesystem | Codice read-only, no PHP negli upload, DISALLOW_FILE_MODS | Web shell, persistenza |
| Rete | Segmentazione, egress default-deny, DB isolato | C2, esfiltrazione, movimento laterale |
| Supply chain | Composer pinnato, finestra 48-72h, diff review, SBOM | Backdoor negli aggiornamenti |
| Operazioni | FIM, SIEM, backup immutabili testati, IR plan | Tutto il resto |
6. Detection engineering: cosa loggare e cosa cercare
Un WAF che blocca non è detection. Detection è sapere che qualcosa è successo, entro minuti.
Sorgenti da centralizzare (Wazuh, ELK o un SIEM gestito): access log del web server, error log PHP-FPM, log di autenticazione WordPress, audit log delle azioni admin, log del firewall egress, log del FIM.
Le sette regole di alerting che consiglio come baseline:
- Creazione di un utente con ruolo Administrator — sempre, senza soglia. Nel 2026 è il singolo indicatore più affidabile di compromissione riuscita.
- Modifica di un file
.phpfuori da una finestra di deploy dichiarata. - Comparsa di qualunque file in
mu-plugins/non presente nella baseline. - Connessione in uscita negata dall’egress filter, originata dall’utente web.
- Richiesta POST a un file in
wp-content/uploads/. - Variazione di
siteurlohomeinwp_options. - Login riuscito su account admin da ASN o geografia mai vista prima.
Un esempio di regola Wazuh per il punto 1:
<rule id="100210" level="12">
<if_sid>100200</if_sid>
<field name="wp.action">user_register</field>
<field name="wp.role">administrator</field>
<description>WordPress: creato nuovo utente Administrator</description>
<mitre><id>T1136.001</id></mitre>
</rule>
Il FIM va configurato con una baseline firmata: se il codice è read-only e gestito da Composer, qualsiasi cambiamento fuori deploy è per definizione un alert ad alta confidenza. Questa è la ragione per cui l’architettura del capitolo 5 vale più di dieci plugin di sicurezza: rende la detection banale.
7. Runbook di Incident Response
T+0 → 1 ora: contenimento
Non spegnete il server. Mettete il sito in modalità manutenzione dietro il CDN, preservando lo stato: l’immagine forense va acquisita prima di qualunque pulizia, perché conterrà le prove che vi servono per la notifica e per l’assicurazione. Isolate a livello di rete (egress a zero, ingress solo da IP del team). Snapshot di filesystem e database.
1 → 24 ore: eradicazione
- Identificate il pattern zero: primo file modificato, prima richiesta anomala, prima creazione di utente.
- Rotazione totale: password admin, salt di
wp-config.php(invalida tutte le sessioni), credenziali DB, SMTP, chiavi API, token dei gateway di pagamento, e i segreti 2FA di ogni utente. - Ricostruzione, non pulizia. Il ripristino corretto dopo una compromissione con RCE è codice da sorgente pulita (Composer/Git) + database ripristinato da backup antecedente al pattern zero, con contenuti riconciliati. La rimozione selettiva della backdoor lascia quasi sempre qualcosa: nel caso ShapedPlugin la raccomandazione dei ricercatori è stata esplicitamente il ripristino completo del sito da un backup pulito antecedente al 21 maggio 2026, come percorso più affidabile per eliminare i meccanismi di persistenza che un’analisi forense potrebbe non rilevare.
Entro 72 ore: obblighi
Se ci sono dati personali coinvolti, scatta l’art. 33 GDPR: notifica al Garante entro 72 ore dalla conoscenza della violazione, con comunicazione agli interessati se il rischio è elevato (art. 34). Se il soggetto rientra nel perimetro NIS2, si aggiungono i termini di notifica all’ACN — pre-allarme a 24 ore, notifica a 72, relazione finale a un mese.
Preparate in anticipo: chi decide l’isolamento, chi firma la notifica, il template già compilato per le parti stabili, il contatto del legale, il contatto del DFIR esterno. Durante un incidente non si scrivono procedure, si eseguono.
8. Governance: NIS2, GDPR e rischio di terza parte
Molti responsabili IT considerano il sito web fuori dal perimetro di compliance. È un errore di scoping.
In Italia la NIS2 è stata recepita con il D.lgs. 138/2024 e il 1° gennaio 2026 ha segnato la scadenza per due adempimenti operativi: la notifica degli incidenti ai sensi dell’art. 25, con l’obbligo di definire e rendere operativo un processo formale per identificare, gestire e segnalare tempestivamente le violazioni di sicurezza, e l’aggiornamento dell’anagrafica ACN. La direttiva introduce obblighi più stringenti di gestione del rischio, continuità operativa e notifica degli incidenti, prevede responsabilità dirette per il management e sanzioni significative in caso di non conformità.
Tre conseguenze pratiche per chi gestisce siti WordPress aziendali:
- Il sito è un asset in perimetro. Se ospita form di contatto, area clienti, e-commerce o è raggiungibile dalla rete aziendale, entra nella gestione del rischio NIS2. Deve comparire nell’inventario degli asset, con owner, categoria di rilevanza e controlli documentati.
- La supply chain è esplicitamente normata. La NIS2 impone la gestione del rischio dei fornitori. Un plugin premium di un vendor a cui affidate esecuzione di codice sul vostro server è un fornitore. Gli incidenti del 2026 sono l’esempio da manuale: vanno tracciati i componenti (SBOM), valutato il vendor (come gestisce le proprie credenziali di rilascio? ha una security policy pubblica? ha un canale di disclosure?) e contrattualizzata la notifica.
- La responsabilità è del management. Non è più delegabile al webmaster o all’agenzia. Se l’agenzia gestisce trenta siti con un solo account amministratore condiviso, quel rischio è vostro.
Sul fronte prodotto, il Cyber Resilience Act europeo sposterà progressivamente obblighi di sicurezza sui produttori di software con elementi digitali — inclusi, nel medio periodo, molti distributori di componenti. Non è ancora un obbligo operativo per il gestore del sito, ma è la direzione: chi distribuisce codice dovrà dimostrare come lo firma e come lo rilascia.
9. Matrice di controllo e checklist di audit
| Fase | Tecnica avversaria | Controllo prioritario | Livello |
|---|---|---|---|
| Ricognizione | User enumeration, version fingerprinting | REST /users chiuso agli anonimi, ?author= bloccato, errori login uniformi | Base |
| Accesso iniziale | Credential stuffing, XML-RPC multicall, phishing | WebAuthn su Admin/Editor, XML-RPC off, rate limiting, allowlist IP su /wp-admin | Base |
| Supply chain | Backdoor in aggiornamento ufficiale | Finestra 48-72h su update non-security, Composer pinnato, diff review, egress deny | Avanzato |
| Sfruttamento | Arbitrary upload, PHP Object Injection, SQLi | No PHP negli upload, disable_functions, allow_url_fopen=Off, WAF, CSP | Intermedio |
| Persistenza | Web shell, mu-plugin backdoor, admin fantasma | Filesystem read-only, DISALLOW_FILE_MODS, FIM, alert su nuovo admin | Intermedio |
| Movimento laterale | Furto credenziali DB/API, pivot in rete | Segmentazione, utente DB a privilegio minimo, no chiavi SSH lato web | Avanzato |
| Azioni finali | Esfiltrazione, skimmer, cryptojacking | Egress default-deny, backup immutabili testati, monitoraggio traffico uscente | Avanzato |
Checklist di audit — le domande che pongo in un assessment:
- [ ] Esiste un inventario dei plugin con owner, criticità e fonte di distribuzione?
- [ ] L’utente che esegue PHP può scrivere nella directory del codice? (se sì, è il primo finding)
- [ ] Il PHP è eseguibile in
wp-content/uploads/? Verificato con un file di test, non solo dalla configurazione? - [ ]
DISALLOW_FILE_MODSè attivo? Se no, quale controllo compensativo esiste? - [ ] Il web server può aprire connessioni in uscita verso Internet arbitrario?
- [ ] La creazione di un utente Administrator genera un alert entro 15 minuti?
- [ ] L’ultimo test di restore (non di backup) quando è stato eseguito, e quanto è durato?
- [ ] I backup sono immutabili o un attaccante con accesso al server può cancellarli?
- [ ] Gli account amministratore sono nominali o condivisi con l’agenzia?
- [ ] Gli aggiornamenti di sicurezza e quelli ordinari seguono politiche di tempistica distinte?
- [ ] Esiste un IR plan scritto, con nomi e numeri di telefono, testato con un tabletop negli ultimi 12 mesi?
- [ ] Il sito compare nell’inventario asset ai fini NIS2/GDPR?
10. KPI: come si misura se state migliorando
Il security posture non si misura in plugin installati. Si misura così:
| Metrica | Target maturo |
|---|---|
| MTTP — patch di CVE sfruttate attivamente | < 6 ore |
| MTTD — creazione admin non autorizzata | < 15 minuti |
| Copertura WebAuthn su ruoli privilegiati | 100% |
| Plugin attivi per sito | Il minimo funzionale, con giustificazione scritta |
| Plugin senza aggiornamenti da > 12 mesi | 0 |
| Copertura egress default-deny | 100% dei web server |
| Restore test completati con esito positivo | ≥ 4/anno, RTO misurato |
| Tabletop IR eseguiti | ≥ 1/anno |
Se dovete scegliere tre sole cose da fare questo mese, in ordine di rapporto impatto/sforzo:
- Egress default-deny sul web server.
- Filesystem del codice non scrivibile dal processo PHP +
DISALLOW_FILE_MODS. - Alert sulla creazione di utenti Administrator, consegnato su un canale che qualcuno legge davvero.
Queste tre misure non impediscono l’exploit. Impediscono che l’exploit diventi un incidente — che è l’unico obiettivo realistico quando l’avversario si muove in cinque ore e voi in quarantatré giorni.
Conclusione
Il vecchio slogan diceva che in cybersecurity non serve correre più veloce dell’orso, basta correre più veloce dell’altro sito WordPress. Nel 2026 l’orso è automatizzato, scansiona simultaneamente ogni sito del pianeta e non insegue: cammina lungo il canale di distribuzione ufficiale e vi raggiunge mentre fate esattamente la cosa giusta.
Questo non rende WordPress indifendibile. Rende indifendibile un certo modo di gestirlo: installazione in cartella scrivibile, aggiornamenti automatici indiscriminati, venti plugin di cui nessuno ricorda l’origine, un solo account admin condiviso e la speranza che il plugin di sicurezza avvisi in tempo.
La difesa che funziona è architetturale e noiosa: codice immutabile, egress chiuso, privilegi minimi, aggiornamenti governati con politiche differenziate, telemetria che arriva a un umano, backup che qualcuno ha davvero provato a ripristinare. Nessuna di queste cose si compra. Tutte si progettano.
Se il vostro sito genera ricavi, tratta dati personali o rappresenta il vostro marchio, la domanda da portare in consiglio di amministrazione non è “abbiamo un plugin di sicurezza?”. È: “se il nostro sito fosse compromesso questa notte, quanto tempo passerebbe prima che ce ne accorgessimo, e quanto prima di tornare operativi da una sorgente che sappiamo pulita?”. Se non avete due numeri da mettere al posto di quelle parole, avete già la vostra prima azione.
Fonti
- Patchstack, State of WordPress Security 2026 (via WP Umbrella) — tempo mediano allo sfruttamento di massa
- UnfoldCMS / Webmastered — volume vulnerabilità plugin e attacco coordinato al repository, aprile 2026
- Wordfence / Security Affairs / CtrlAltNod — supply chain ShapedPlugin, CVE-2026-10735
- WPPoland — i tre incidenti supply chain di giugno 2026
- SecurityWeek — Elementor Pro CVE-2026-32475; Forminator CVE-2026-15748
- The Hacker News — WPMU DEV, GiveWP e altre CVE critiche; guida CISO al pentesting agentico
- Google Threat Intelligence Group, AI Threat Tracker Q3 2026
- Palo Alto Unit 42 — indagine su intrusione AI-assistita
- Verizon DBIR 2026; Mandiant time-to-exploit
- ACN / D.lgs. 138/2024 — obblighi NIS2 e scadenze 2026
