WordPress e alcuni consigli per migliorare la sicurezza (1)
da Massimo Della Rovere · pubblicato il 3 Marzo, 2013 · modificato il 13 Agosto, 2016

Con tutte le operazioni che possono essere eseguite nel miglioramento della sicurezza di WordPress potremmo scrivere una divina commedia, inoltre internet è pieno di informazioni che riguardano proprio questo aspetto, alcuni articoli sono ben fatti ed altri lasciano il tempo che trovano. Molte persone preferiscono utilizzare i plugin messi a disposizione, altre preferiscono mettere le mani al codice sorgente ed inserire direttamente delle protezioni. In questo articolo cercherò di affrontare il discorso in maniera diversa, cioè dando più peso all’aspetto sistemistico, oltre ovviamente agli aspetti che sono assolutamente necessari, quindi affronteremo l’analisi del file system, le varie autorizzazioni, il pannello di amministrazione, il database ed altro ancora.

Un piccolo chiarimento

Prima di iniziare vorrei fare un dovuto chiarimento, infatti le tecniche che riporterò in questo articolo non sono state scelte perché ritenute più importanti di quelle già conosciute o perché i vari plugin non vengono ritenuti validi, anzi …, ma semplicemente come ho già accennato, voglio affrontare un’argomento che in internet è meno presente degli altri e a cui non gli viene data la giusta importanza.

In ogni caso, sappiamo tutti quanti che il server più sicuro al mondo è quello spento, e se vi devo dire la verità, anche in questo specifico caso avrei i miei forti dubbi …

Un’altro aspetto, che invece escludo in quanto la penso differentemente, è quello di cambiare la struttura delle directory di WordPress, infatti in internet si trovano molti articoli su come cambiare la directory degli upload, l’indirizzo della cartella admin, cambiare il nome alla famosa wp-content, ect. Tutte tecniche, secondo me, non solo inutili, in quanto per scoprire le nuove directory bastano 5 minuti, guardando il sorgente html, ma può anche portare a dei problemi di funzionamento del core in generale e di molti plugin che purtroppo non utilizzano correttamente le costanti.

Consiglio (1) – Tenere sempre WordPress aggiornato

Su questo aspetto veramente tutto internet è d’accordo, gli unici che non lo sono, sono quelli che si dimenticano di aggiornarlo e rimandano sempre a domani. Invece questo è proprio il primo aspetto fondamentale della sicurezza WP. Ci sono due motivi principali che aumentano la possibilità di violazione di un sito internet non aggiornato, il primo motivo è una questione tecnica, il secondo, una probabilità  matematica.

L’aspetto tecnico è dovuto al fatto che i sorgenti delle vecchie release sono stati più tempo in mano alle tante persone che cercano falle di sicurezza, quindi non solo è più probabile che abbiano trovato dei malfunzionamenti, ma hanno avuto sicuramente più tempo per distribuire tools di violazione nella rete ad un numero di persone sempre più grande, se a questo aggiungiamo, che non aggiornando il nostro WordPress diventiamo sempre di meno in questa release, questo significa che statisticamente diventiamo sempre più vulnerabili, in quanto da un parte crescono le persone che conoscono la vulnerabilità e dall’altra diminuiscono quelle che la posseggono, quindi rimanere in mezzo a questa situazione non è la migliore delle cose.

Consiglio (2) – Secret Keys e password in wp-config.php

Sicuramente questo passaggio lo avete fatto quasi tutti, ma un piccolo controllo non fa male, sinceratevi di aver impostato dei valori nel file wp-config.php per le chiavi segrete, che servono a criptare informazioni legate al funzionamento del vostro blog, come sessioni, cookie, password ed altro ancora. A questo aggiungete il fatto di scegliere una password molto complessa per l’accesso al database, tanto questa password la dovete usare pochissime volte una volta memorizzata nel file, quindi non fatevi problemi di difficoltà a ricordarla e rendetela più complessa possibile.

// Definizione password per accesso al database
define('DB_PASSWORD','e3wuU99nuq3TW5Gc');

// Definizione secret keys
define('AUTH_KEY','g]rDj*+=$G;>k}[E+RT-MFJ<TDf.M$ErBrPZHtZ AKcEE?q>');
define('SECURE_AUTH_KEY','|!JKNW-b-bLcuse:BqKtHk5{sXAdSd#23$`<griB=');
define('LOGGED_IN_KEY',';,k+Z[prA~:BJ)&i,}lV2y)-#.+z1OD:E-Bp4+5Rkn)');
define('NONCE_KEY','%iXrJXpdFSi^B+l. 6av4q|=/NgD^{wcIaE*a+~N3NKiQj~');

Per la password potete usare un pò di fantasia, anche se in internet si trovano parecchi tools di generazione password complesse, per quanto riguarda invece le secret keys vi conviene utilizzare il tools su http://api.wordpress.org/secret-key/1.1/. Non dovete fare altro che fare un copia e incolla delle righe che trovate nella pagina del link.

Consiglio (3) – Proteggere il file system da accessi HTTP

Quando installiamo WordPress nella nostra directory, vengono installati tanti file .PHP che servono al funzionamento del core in generale, in quanto vengono usati nelle inclusioni, ma non servono a niente se richiamati tramite un’indirizzo URL. Addirittura se usiamo i permalink personalizzati, i file che vengono richiamati dall’indirizzo URL sono veramente pochissimi se non quasi sempre ed esclusivamente il file index.php.

Però purtroppo, dato che questi file sono raggiungibili anche con una semplice richiesta http e dato che tutti conoscono la struttura standard di WordPress, se qualcuno di essi contiene un possibile exploit, può essere richiamato per eseguire una violazione al nostro server web. Quindi la prima cosa corretta da fare, ancora prima di andare a vedere i privilegi di lettura e scrittura legati all’utente, è quella di bloccare la richiesta http per tutti questi file php che appartengono al core interno di WordPress.

Sicurezza WordPress

Partiamo dai file della root: nella directory principale ci sono parecchi file php che iniziano con il suffisso (wp-), di questi in base ai casi ne servono pochi, specialmente come ho detto, se usiamo i permalink personalizzati. Quindi la prima cosa da fare è bloccare tutti questi file tramite il file di configurazione di apache o se permesso inserire le regole nel file .htaccess. Ovviamente è possibile fare queste operazioni anche con altri web server, ad esempio nginx, il concetto non cambia, ma sicuramente cambieranno i comandi e la modalità di inserimento nei vari file di configurazione.

# Protezione dei file che non devono essere letti in HTTP
# Blocco tutti i file PHP meno le azioni di login, cron e commenti.

RewriteCond %{REQUEST_URI} !^/wp-(login|cron|comments-post)\.php$
RewriteRule ^wp-([_0-9a-zA-Z-]+)\.php [R=404,L]

Come potete vedere ho preferito gestire un’errore 404 invece che un messaggio di non autorizzato, proprio ad indicare che il file non c’è ed è inutile cercarlo in qualche maniera. Se volete fare una prova andate su https://emarket.pe/wp-config.php e vedrete che ottenete un codice 404 a differenza di un’installazione standard, in questo caso senza pericoli, però questo non possiamo saperlo per tutti gli altri file.

Sicuramente il file .htaccess è già protetto dalla configurazione di apache che non ne permette l’accesso, però per sicurezza, proprio per non fidarsi mai, inserite nuovamente la regola nel vostro file, prima di quelle del rewrite che abbiamo specificato in precedenza. A questo punto fate una prova su https://emarket.pe/.htaccess e controllate di riceve il messaggio di mancata autorizzazione.

<Files .htaccess>
  order allow,deny
  deny from all
</Files>

Directory wp-includes e wp-content: Queste due directory contengono il cuore di wordpress, infatti ci sono tutti i file PHP più importanti del core, però è anche il posto dove si nascondono i problemi più gravi che una volta scoperti sono usati come porta di entrata al nostro server. Siccome in queste directory ci sono anche molti file che servono e devono essere raggiungibili tramite richiesta HTTP/HTTPS, non possiamo bloccare tutta la directory, ma dobbiamo selezionare solo gli scripts specifici che hanno un’estensione PHP. Le regole da inserire sono le seguenti:

# Protezione dei file che non devono essere letti in HTTP
# Blocco tutti i file PHP meno le azioni di login, cron e commenti.

RewriteCond %{REQUEST_URI} !^/wp-(login|cron|comments-post)\.php$
RewriteRule ^wp-([_0-9a-zA-Z-]+)\.php [R=404,L]

# Protezione file che non devono essere letti in HTTP
# Qui blocco alcuni file PHP del core e altri che danno informazioni 

RewriteRule ^readme.html(.*)        [R=404,L]
RewriteRule ^license.txt(.*)        [R=404,L]
RewriteRule ^licenza.txt(.*)        [R=404,L]
RewriteRule ^wp-content/(.*)\.php$  [R=404,L]
RewriteRule ^wp-includes/(.*)\.php$ [R=404,L]

Ovviamente anche se non l’ho specificato prima, tutte queste operazioni fatele in un’ambiente di prova prima di metterle sul vostro server reale, adesso che avete messo le nuove regole provate un link di prova /wp-includes/shortcodes.php e controllate se tutto funziona, ad esempio con il link riportato potete vedere una differenza sostanziale, nel link postato del mio blog dove c’è il controllo, il server restituisce un 404, se invece prendiamo un’altro sito, anche famoso, vedrete che viene eseguito un codice PHP che non doveva essere accessibile.

NB: Le regole che iniziano con il carattere (^) hanno il significato (iniziare con), quindi la regola va bene se WordPress è installato nella directory radice la quale viene riportata anche nel formato URL. Se ad esempio avete il sito che viene raggiunto con un’indirizzo dominio.com/blog allora la regola diventa ^blog/etc,etc.

Consiglio (4) – Cambiare il suffisso del database

Questo è invece un’aspetto conosciutissimo e lo inserisco in quanto lo ritengo quasi obbligatorio, infatti il suffisso è molto utile per evitare le SQL injection che vanno a tentativi, infatti sapendo il nome delle tabelle e il prefisso di default, se riescono a trovate un URL difettato riescono anche a scrivere nel nostro database, cosa assolutamente da evitare. La scelta del suffisso per il database, se viene fatta nella fase iniziale di installazione è semplicissima, se invece la dobbiamo eseguire dopo allora bisogna seguire attentamente alcuni passaggi ben precisi.

File wp-config.php: In questo file dobbiamo cambiare il valore della variabile che viene usata in tutto il core di wordpress, scegliete un prefisso difficile senza esagerare:

$table_prefix = 'wp_a987654_'

Rinominare le tabelle: Dopo questa operazione, salvate il file wp-config.php e andate nel pannello di amministrazione del vostro database per cambiare i nomi di tutte le tabelle di WordPress con il nuovo prefisso, se avete un’installazione standard ve la cavate con molto poco, se invece avete un’installazione multi site con parecchi database allora armatevi di tanta pazienza. Ovviamente se avete accesso al database dalla linea comandi, potete anche utilizzare direttamente il comando di RENAME per ogni tabella presente in WordPress. Io sinceramente utilizzo phpmyadmin con cui mi trovo molto bene ed eseguo le operazioni che mi servono senza perdere tempo.

Sicurezza WordPress

Update delle tabelle: Purtroppo, ancora non abbiamo finito, infatti bisogna andare sui file di Option e UserMeta per cambiare i record che contengono il vecchio suffisso con quello nuovo, per trovare i record eseguire su ogni tabella il seguente comando SQL:

SELECT * FROM `suffisso_options` WHERE `option_name` LIKE '%wp_%'
SELECT * FROM `suffisso_usermeta` WHERE `meta_key` LIKE '%wp_%'

Consiglio (5) – Usare il protocollo HTTPS per l’amministrazione

Uno degli aspetti più importanti della sicurezza generale di WordPress è proprio quello di dividere le operazioni del frontend da quelle del backend, infatti per il backend è raccomandata una chiave SSL da utilizzare con il protocollo HTTPS, in questa maniera le comunicazioni del nostro browser con il server web saranno criptate e non possono essere lette in chiaro da chi sta facendo uno sniffing di rete, cosa che ultimamente è diventata molto probabile, grazie alle reti wireless, per non parlare delle reti condivise con il condominio o quelle che utilizziamo negli uffici. Quindi non proteggere in maniera seria la trasmissione delle credenziali di accesso, significa in poche parole, rendere completamente inutili tutti i passi che abbiamo visto fino in questo momento.

Sicurezza WordPress

Esistono diversi certificati che si possono comprare per un collegamento SSL, dipende dal tipo di applicazione web e dall’utilizzo che può avere il certificato stesso, ad esempio se può essere usato anche per altre sezioni come pagine di e-commerce o forum privati. Se il sito è gestito solo per uso personale, in realtà il certificato può essere creato anche da noi stessi, non sarà riconosciuto dal browser che emetterà un messaggio di avviso, però la sostanza di quello che ci serve non cambia. In ogni caso visto i prezzi ormai bassi di un certificato vi consiglio di dare un’occhiata in internet e vedere se conviene comprarlo, io normalmente utilizzo https://www.rapidssl.com/.

define('FORCE_SSL_LOGIN',true);
define('FORCE_SSL_ADMIN',true);

Per eseguire questa operazione di sicurezza vi conviene leggere un’articolo che ho dedicato a questo “Configurazione pannello amministrazione SSL“, dove potete vedere anche come crearvi un certificato, inserire le righe di configurazione su apache e impostare le costanti del file wp-config.php che forzano WordPress su SSL.

Consiglio (6) – Utilizzare SSH per i collegamenti

Per facilitarci la vita, tutti quanti utilizziamo sempre un client FTP per il trasferimento dei file di WordPress e/o per fare le modifiche di programmazione necessarie al nostro lavoro, a questo viene aggiunto molte volte anche il software phpmyadmin che ci permette di gestire il database MySQL con un’applicazione grafica, senza utilizzare comandi e sintassi complicate. Purtroppo però questo aggiunge dei problemi di sicurezza, quindi non dico di rinunciarci, ma di utilizzarli almeno in maniera diversa.

Una tecnica che utilizzo molto è quella del tunneling SSH, quindi non uso mai le porte standard FTP che non sono sicure, ma solo SFTP. Per quello che riguarda applicazioni particolari che possono essere pericolose se lasciate pubbliche e raggiungibili dal web come proprio phpmyadmin, utilizzo un virtual host che è raggiungibile solo tramite il tunneling SSH e quindi dall’esterno è come se quella directory non esistesse proprio.

sudo ssh -L 7379:localhost:80 -i chiave.pem utente@dominio.com

Se non conoscete questa tecnica vi consiglio di approfondirla, in quanto aumenta in maniera significativa la sicurezza e riduce la possibilità di essere derubati delle credenziali di accesso. Potete partire da questo Wikipedia Tunneling Protocol.

Indice generale degli articoli correlati

14 Commenti

  1. Ciao Massimo bellissima guida. Una domanda relativa al consiglio 3 nel caso di un dominio di terzo livello che contiene l'installazione wp su di una cartella come ad es. terzo.secondo.it/cartella/ come devo scrivere RewriteRule ^readme.html(.*) [R=404,L]

  2. Ciao Alessandro, grazie per il tuo commento. Se vuoi eseguire il comando di rewrite in una sottocartella devi usare il path senza indicare lo slash iniziale. Il domino di terzo livello è ininfluente.
    RewriteRule ^cartella/readme.html(.*) [R=404,L]

    Esempio: http://stackoverflow.com/questions/5494921/htaccess-rewriterule-not-working-in-subdirectory

  3. strano non me lo da... e neppure quello relativo all'enumerazione degli utenti (quest'ultima posso sistemarla anche a livello di tema facendo redirect se la pagina è di tipo autore)

    RewriteEngine On
    RewriteBase /prototipo-07652/

    # Protezione dei file che non devono essere letti in HTTP
    # Blocco tutti i file PHP meno login, cron e commenti.

    RewriteCond %{REQUEST_URI} !^/wp-(login|cron|comments-post).php$
    RewriteRule ^wp-([_0-9a-zA-Z-]+).php [R=404,L]

    # Protezione file che non devono essere letti in HTTP
    # Qui blocco alcuni file PHP del core e altri

    RewriteRule ^prototipo-07652/readme.html(.*) [R=404,L]
    RewriteRule ^prototipo-07652/license.txt(.*) [R=404,L]
    RewriteRule ^prototipo-07652/licenza.txt(.*) [R=404,L]
    RewriteRule ^prototipo-07652/wp-content/(.*).php$ [R=404,L]
    RewriteRule ^prototipo-07652/wp-includes/(.*).php$ [R=404,L]

  4. Ciao Alessandro, se usi RewriteBase allora la cartella non la devi specificare, in quanto cambi la base dell'indirizzo, la dovrai usare solo se ti riferisci a una sottocartella di RewiteBase.

    Esempio: http://stackoverflow.com/questions/704102/how-does-rewritebase-work-in-htaccess

  5. Salve Massimo, ho iniziato a leggere l'articolo ed ho iniziato a mettere in pratica le modifiche. Per quanto riguarda il punto 3 ho creato la pagina 404: sito.com/404-page/ e modificato il file .htaccess con questo codice:

    # BEGIN WordPress
    RewriteEngine On
    RewriteBase /xxx/xxx/

    # Protezione dei file che non devono essere letti in HTTP
    # Blocco tutti i file PHP meno le azioni di login, cron e commenti.

    RewriteCond %{REQUEST_URI} !^/wp-(login|cron|comments-post).php$
    RewriteRule ^/xxx/xxx/wp-([_0-9a-zA-Z-]+).php [R=404,L]

    # Protezione file che non devono essere letti in HTTP
    # Qui blocco alcuni file PHP del core e altri che danno informazioni

    RewriteRule ^/xxx/xxx/readme.html(.*) [R=404,L]
    RewriteRule ^/xxx/xxx/license.txt(.*) [R=404,L]
    RewriteRule ^/xxx/xxx/licenza.txt(.*) [R=404,L]
    RewriteRule ^/xxx/xxx/wp-content/(.*).php$ [R=404,L]
    RewriteRule ^/xxx/xxx/wp-includes/(.*).php$ [R=404,L]

    RewriteRule ^index.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /xxx/xxx/index.php [L]

    # END WordPress

    ma aprendo http://www.miosito.com/xxx/xxx/.htaccess mi apre la pagina 403: Forbidden You don't have permission to access /mmagazine/mmagazine/.htaccess on this server. Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the request. Evidentemente ho sbagliato qualcosa nel file .htaccess, ma cosa? Grazie per l'aiuto!

  6. Non penso che ci siano degli errori, semplicemente il file .htaccess non puoi leggerlo con una richiesta HTTP altrimenti lo leggono tutti e addio la sicurezza (è giusto che il server web dia errore di permesso). Il file htaccess lo puoi leggere accedendo al file con un editor, PTF o altro.

  7. Ottima guida Massimo. Quello che fatico a capire è perché questi accorgimenti non siano già inseriti di default in WordPress che invece nelle ultime versioni introduce funzionalità dalla dubbia utilità invece di implementare misure di sicurezza.

  8. Ciao Francesco, penso che WordPress si concentri sull'aspetto che riguarda il core applicativo, e a livello di programmazione mette a disposizione molte funzioni per la sicurezza, come ad esempio la pulizia delle stringhe e le classi del database con molti controlli sulla sintassi SQL. Quello che presento in questo articolo sono consigli che riguardano il sistema in generale e forse non è competenza di WP dedicarsi a questo.

  9. Ciao Massimo, grazie per le dritte. Una risposta sul punto 4 per cortesia. Sono obbligato ad utilizzare il suffisso wp o posso utilizzare altro suffisso o sigla? Grazie!

  10. Puoi usare qualsiasi suffiso il prefisso wp_ è una convenzione non è una regola. Ad esempio puoi usare mydb_ o mywebsite_ etc etc.

  11. Complimenti Massimo! Un articolo veramente ben fatto e molto chiaro! in rete si trovano sempre tips molto spezzettate e vecchie! Grazie!

  12. Ciao, ho provato a eseguire le modifiche al file .htaccess da te consigliate al punto 3, il problema è che così facendo mi scompare l’editor negli articoli e il testo degli articoli nel pannello di amministrazione diventa bianco :(

    Ho fatto diverse prove inserendo i codici prima e dopo# BEGIN WordPress ma non funziona in entrambi i casi. Utilizzo l’ultima versione aggiornata di wordpress la 3.5.2

  13. Il punto esatto dove inserire le istruzioni è subito dopo il RewriteBase, ti allego il codice che io utilizzo attualmente su un sito senza nessun problema con apache e wordpress.

    # Attivazione modulo di rewrite per URL e

    RewriteEngine On
    RewriteBase /

    # Protezione file che non devono essere letti in HTTP
    # Gestione errore 404 se vengono richiamati file PHP

    RewriteCond %{REQUEST_URI} !^/(wp-login\.php|wp-cron\.php|wp-comments-post\.php)$
    RewriteRule ^wp-([_0-9a-zA-Z-]+)\.php [R=404,L]
    RewriteRule ^wp-content/(.*)\.php$ [R=404,L]
    RewriteRule ^wp-includes/(.*)\.php$ [R=404,L]

  14. Grazie Massimo: molto utile
    Un paio di dritte cosi ben fatte non fanno male!

condividi