WordPress alimenta una fetta enorme del web, e questo la rende irresistibile per chi cercano vulnerabilità. Non per un motivo tecnico, ma economico: un bug in un plugin con due milioni di installazioni vale più di un bug in un software che gira su tre server.
Il punto che quasi tutti sbagliano è questo: le vulnerabilità in WordPress non si cercano "dentro WordPress". Il core è scritto da un team che ne fa un audit continuo, ha una pagina di sicurezza dedicata, e rilascia patch regolari. Il terreno fertile è un altro.
Dove si cercano davvero i problemi
Tre bersagli, in ordine di redditività per chi attacca:
I plugin. È qui che si concentra il rischio. Un plugin è scritto da una persona, spesso una sola, che non percepisce il plugin come superficie d'attacco e ci mette dentro un form che chiama $_GET e lo passa a una query. Il core ha duecento sviluppatori e una coda di segnalazioni; un plugin ha uno sviluppatore e nessuna.
I temi. Meno diffusi dei plugin, spesso venduti a pochi euro, spesso venduti e abbandonati. Un tema "nulled" — cioè comprato e craccato — è già un vettore: contiene spesso backdoor aggiunte da chi l'ha piratato, non dal tema originale.
Il multisite e i plugin che toccano l'autenticazione. Qui il guadagno è alto perché il componente è in posizione privilegiata. Un plugin che gestisce login, permessi o ruoli ha accesso a cose che un plugin di galleria non ha.
La catena di lavoro, in ordine
Il lavoro serio ha dei passi, e saltarli è la ragione per cui la maggior parte delle persone non trova niente.
1. Inventory: sapere cosa c'è dentro
Prima di qualsiasi attacco, sapere cosa gira. Il numero di plugin installati è il miglior predittore del rischio: un sito con 82 plugin è un sito con 82 possibili vettori.
Il modo più rapido per fare inventory è guardare la sorgente della pagina e il file di licenza che ogni tema lascia.
# Estrae il percorso dei temi dagli URL dei fogli di stile
curl -s https://target.example | grep -oE '/wp-content/themes/[^/]+' | sort -u
# Cerca i nomi dei file di licenza dei plugin, uno per riga
curl -s https://target.example | grep -oE '/wp-content/plugins/[^/]+' | sort -u
Il motivo per cui questo funziona è che WordPress stampa i path dei temi e dei plugin in chiaro nel sorgente. Non è una vulnerabilità: è il CMS che dice dove tiene i suoi file. Ma espone l'inventario completo.
2. L'inventario delle versioni
Sapere quale versione è installata trasforma il lavoro da esplorazione a ricerca. Se sai che il plugin è alla 1.2.3, puoi cercare la patch 1.2.4 e leggere il changelog: quello che è stato corretto nella 1.2.4 è la vulnerabilità che stai cercando.
# Legge la versione dichiarata nell'intestazione di un plugin
curl -s https://target.example/wp-content/plugins/EXAMPLE/example.php \
| head -20 | grep -i version
# Elenco dei plugin con le versioni, se il sito espone rest-api
curl -s "https://target.example/wp-json/wp/v2/plugins" | head -40
Il secondo comando restituisce quasi sempre 401 o 404 su un sito in regola, ma va provato: su alcuni setup resta esposto per errore di configurazione, ed è una violazione di per sé.
3. Diff delle patch: il metodo più redditizio
Questo è il trucco che quasi nessuno conosce, ed è il più efficace.
Quando un vendor rilascia una patch di sicurezza, il diff tra la versione vulnerabile e quella corretta è la descrizione esatta della vulnerabilità. Non devi indovinare: la chiarezza la fa il vendor.
Il flusso è:
- Scarichi la versione dichiarata e quella successiva da un mirror come WordPress.org
- Fai il diff
- Quello che è cambiato è il punto debole
- Se il fix aggiunge un escaping o un controllo di permessi, hai trovato il buco
# Scarica due versioni di un plugin e confrontale
mkdir -p ~/wp-audit && cd ~/wp-audit
svn co https://plugins.svn.wordpress.org/EXAMPLE/tags/1.2.3 v123
svn co https://plugins.svn.wordpress.org/EXAMPLE/tags/1.2.4 v124
# Il diff è la vulnerabilità, in chiaro
diff -ru v123 v124 --exclude='*.min.*' --exclude='readme.txt' > patch.diff
wc -l patch.diff
Questo funziona anche su plugin abbandonati, che è il caso peggiore: se il vendor non rilascia più patch, non c'è nessun diff da leggere, e il bug è ancora lì.
4. Lettura del codice nei posti giusti
Quando il diff non basta, si legge il codice nei punti dove l'input dell'utente arriva vicino a una query o a un comando di sistema.
I tre schemi da cercare, in ordine di pericolosità:
Input non validato in una query — SQL injection:
// pericoloso: $id arriva da $_GET e finisce in una query grezza
$id = $_GET['id'];
$row = $wpdb->get_row("SELECT * FROM wp_posts WHERE ID = $id");
// il controllo minimo: forzare un intero
$id = absint($_GET['id']);
$row = $wpdb->get_row("SELECT * FROM wp_posts WHERE ID = %d", $id);
Input in un comando di shell — command injection:
// pericoloso: nome del file in una shell
$file = $_GET['file'];
system("convert " . $file . " out.png");
// sicuro: escapeshellarg() mette il valore tra apici e lo neutralizza
system("convert " . escapeshellarg($file) . " out.png");
Input in un include o un require — LFI, e spesso RCE:
// pericoloso: l'utente sceglie il file da includere
$lang = $_GET['lang'];
include("lang/$lang.php");
// l'attaccante passa ../../wp-config.php e legge le credenziali
Questi tre schemi coprono la maggior parte delle vulnerabilità nei plugin che si trovano in giro. Non sono un Giovan Battista: sono la stessa struttura, ripetuta.
Difesa: la checklist che conta davvero
Se gestisci un WordPress, queste cinque cose eliminano la quasi totalità del rischio, in ordine di efficacia:
Meno plugin, meglio. Ogni plugin che non usi è un plugin che non patcherai mai. I temi "child" sono quasi sempre gratuiti e funzionano bene.
Aggiornare entro una settimana dall'uscita della patch. La finestra di sfruttamento medio dopo una CVE pubblicata su un plugin popolare si misura in giorni, non mesi. Chi automatizza gli aggiornamenti vince.
Un WAF davanti al sito. Wordfence o Cloudflare filtrano le richieste malformate prima che arrivino al PHP. Non sostituiscono la patch, ma riducono il rumore fino a renderlo leggibile.
Meno privilegi. L'utente del database non deve poter creare tabelle, e l'utente FTP non deve poter eseguire codice PHP. Sono due limiti che, se ti violano, allargano la superficie invece di tenerla stretta.
Log in lettura. Il file di log è l'unica difesa che funziona dopo. Molti siti hanno un solo accesso, dal 2019, e nessuno lo ha notato.
Due note di etica, visto che il tema è sensibile
Questo articolo descrive come si cercano vulnerabilità, e serve a chi deve correggerle. Due cose restano vere comunque, indipendentemente da come è andata la tua giornata.
La prima: senza autorizzazione scritta, cercare vulnerabilità in un sistema che non è tuo è reato. Non è una discussione etica, è il Codice Penale. Questo vale in Italia come in ogni altro Paese, e le eccezioni "era solo per vedere" non esistono. Se trovi una falla su un sito altrui, la segnali al proprietario e basta.
La seconda, che vale per chi lavora davvero nel settore: la differenza tra chi è bravo e chi è utile non è la tecnica, è la trasparenza. Chi ti assume vuole sapere che cosa guardi, perché, e cosa farai quando trovi qualcosa. Un pentester che non sa dire "ho accesso al database" non è discreto, è solo bravo a nascondere. La relazione con il cliente si costruisce su quello, e spesso è l'unica cosa che distingue un tester da un criminale.
Se vuoi fare questo lavoro per davvero, la strada non passa per un exploit trovato a caso: passa per capire come funziona un sistema dall'interno, per leggere il codice di qualcun altro con attenzione, e per accettare che il lavoro vero è spesso una email con una descrizione chiara di un problema. Quello, e non la foto dello score, è ciò che ti rende credibile.