Dopo aver imparato a versionare il codice sorgente del nostro sito, ed a gestire i permessi delle cartelle per evitare che il malintenzionato di turno trovi una vulnerabilità e si metta a caricare file per portare avanti i suoi loschi intenti, oggi vorrei condividere un semplice pezzo di codice che mi sono scritto per tener d’occhio questi vandali dell’ultima ora. Si, lo so che esistono già soluzioni ben più sofisticate come fail2ban, ma per me è stata l’occasione per spolverare le mie conoscenze da principiante di shell scripting ed imparare un paio di cose su quel misterioso comando che è sempre stato awk
per me. Ti basterà aggiungere una riga al tuo crontab
per invocare lo script ogni cinque minuti. Vediamo dunque di spacchettare le varie operazioni, per capire meglio come funziona questo pezzo di codice.
L’idea di base è quella di spulciare tra i log del server web alla ricerca di stringhe sospette e contare quanti errori HTTP un certo indirizzo IP ha generato in un dato lasso di tempo. Se questi brutti ceffi superano una certa soglia di tolleranza, il loro indirizzo IP viene aggiunto al file .htaccess
(si, questo script funziona solo con Apache al momento) e bloccato in maniera permanente. Per semplicità, gli indirizzi vengono appesi alla fine del file, quindi assicurati di mettere tutte le altre regole di cui hai bisogno prima della parte finale. La prima cosa da fare è aggiungere una sezione come questa al file .htaccess
che probabilmente hai già nel tuo sito, se usi i permalink di WordPress:
# DO NOT DELETE THIS CODE HERE BELOW.
# A ban script appends rows to this file on a recurring basis
Order Allow,Deny
Allow from all
Deny from env=bad_bot
# Start Whitelist
# 66.249.0.0/16 Google_Bot
# 157.55.39.0/24 Microsoft_Bot
# 207.46.13.0/24 Microsoft_Bot
# End Whitelist
#
La whitelist è giusto un esempio ovviamente, cambiala in base alle tue esigenze, usando la notazione CIDR per indicare intere subnet, se necessario. Il mio script leggerà quella lista, ed ignorerà le richieste provenienti da indirizzi in quei gruppi. A questo punto, salva lo script nella tua home directory sul server (io consiglio sempre di creare una cartella bin
all’interno della propria home, dove tenere tutti questi comandi utili), ed aggiungi il comando corrispondente al tuo cron:
*/5 * * * * /path1/ip2ban.sh /path2/.htaccess /path3/access.log
Ovviamente sostituirai i vari path con le stringhe appropriate. Lo script prende due parametri: il percorso completo dove trovare il file .htaccess
a cui appendere gli indirizzi IP dei malintenzionati, ed il percorso dove trovare l’access log di Apache. Se necessario, questo secondo parametro può essere una lista di file separati da uno spazio, nel caso in cui tu voglia controllare, ad esempio, sia l’access.log
che il suo corrispondente sicuro ssl_access.log
.
Se dai un’occhiata al codice sorgente, troverai alcune variabili in cima che ti consentono di personalizzare il comportamento dello script:
LOOKBACK_MINUTES=60
THRESHOLD_4XX_5XX=30
THRESHOLD_KEYWORDS=5
THRESHOLD_DOS=10000
La prima definisce il periodo di tempo da analizzare, ad esempio gli ultimi 60 minuti. La seconda rappresenta la soglia di errori 400 e 500 che un singolo indirizzo può generare nell’intervallo di tempo prima di essere aggiunto alla lista nera. In altre parole, guardando all’esempio qui sopra, se un indirizzo IP ha generato più di 30 errori 404 (perché sta cercando una pagina da sfruttare per i suoi loschi affari) negli ultimi 60 minuti, allora verrà aggiunto alla blacklist. La terza variabile ha un significato analogo, ma legato a parole specifiche contenute nella richiesta ricevuta: se ad esempio hai disattivato le richieste XMLRPC, puoi aggiungere quella parola chiave al file keywords.txt
(qui trovi un template di come compilare questo file) e lo script conterà tutte le occorrenze e bloccherà gli indirizzi IP che hanno superato la soglia corrispondente. Infine l’ultima variabile conta il numero totale di accessi di un dato indirizzo nell’intervallo di tempo.
Come ho accennato, puoi piazzare il file keywords.txt
nella stessa cartella dove hai salvato lo script, per definire parole chiave sospette che intendi tener d’occhio. Un’altra cosa da tenere a mente è che lo script assume che il formato dei log di Apache da analizzare sia quello standard con data all’inizio, ecc. Ovviamente se la tua situazione è differente, ti toccherà personalizzare le corrispondenti stringhe di AWK per analizzare l’informazione corretta.
Commenti
Interessante!
Risposte al commento di kOoLiNuS
Spero la serie ti sia piaciuta finora 🙂
Considera che con l’IPv6 puoi avere praticamente un numero infinito di indirizzi, la tecnica del blocco per indirizzi singoli è fallimentare, in quanto gli attacchi DDoS usano decine di migliaia di indirizzi (sfruttando ad esempio le falle dei vari IoT che possono essere utilizzati a dovere…).
Ovviamente un hacker degno del suo nome non perderà tempo coi sitarelli…
Risposte al commento di Trap
Hai ragione, questo script non tiene conto dei possibili indirizzi IPv6 che gli hacker potrebbero sfruttare. Tophost, il provider che ospita questo blog, riceve attacchi DDoS con cadenza periodica, e sarebbe interessante sapere come si proteggono. Riguardo al perdere tempo con siti piccoli, ho invece notato sui siti che gestisco al lavoro che ci provano comunque, perché a loro non interessa la “qualità” (o dimensione) ma la “quantità” di siti: più ne bucano, più ne possono usare per lanciare attacchi su altri siti e via dicendo. Ed i siti piccoli sono spesso quelli meno protetti. Questo script è più mirato a bloccare gli “sniffer”, quei bot a caccia di vulnerabilità sui siti, che tentano di accedere percorsi per trovare plugin che hanno delle falle note.
Risposte al commento di camu
A proposito di sniffer… ho notato che cambiando la porta standard per SSH riduce di tantissimo il numero di attacchi.
Risposte al commento di Tra
Verissimo. Sia al lavoro che sul server dove tengo il sito per il mio plugin WordPress, la porta non è la 22. Peccato che non si possa fare lo stesso con la porta del server web 😀
Perché no? È facile cambiare la porta del web server
Si si, intendo per un sito pubblico…