Blindare httpd con mod_security

2 novembre 2013

Fabrizio Soppelsa

- RHCE, Autore di Linux&C, Autore di Linux Journal

mod_security

 

Mod_security è un potente tool per il filtraggio livello HTTP. Permette di definire regole personalizzate per prevenire e bloccare gli attacchi noti alle applicazioni web, e comprende caratteristiche utili per analizzare e rispondere a questi attacchi.

Mod_security è disponibile come modulo sia per Apache che per NginX, ed è distribuito in forma pacchettizzata nel repository EPEL. Perciò è necessario abilitare EPEL prima di procedere con l’installazione vera e propria (che di default su CentOS è legata ad Apache):

# yum install mod_security.x86_64 mod_security_crs.noarch mod_security_crs-extras.noarch

Questo comando installa mod_security ed alcune firme base relative alle best practice di sicurezza web. Le firme sono necessarie a mod_security perché mod_security confronta il contenuto delle richieste HTTP con queste firme e se c’è una corrispondenza scatena un evento. Risulta così facile per l’amministratore di sistema intercettare gli attacchi e patchare le applicazioni al volo.

Tornando all’installazione di mod_security, dopo aver riavviato httpd si può controllare dall’error_log se il modulo è stato correttamente caricato:

[Tue Oct 01 13:27:02 2013] [notice] ModSecurity for Apache/2.7.3 (http://www.modsecurity.org/) configured.
[Tue Oct 01 13:27:02 2013] [notice] ModSecurity: APR compiled version="1.3.9"; loaded version="1.3.9"
[Tue Oct 01 13:27:02 2013] [notice] ModSecurity: PCRE compiled version="7.8 "; loaded version="7.8 2008-09-05"
[Tue Oct 01 13:27:02 2013] [notice] ModSecurity: LUA compiled version="Lua 5.1"
[Tue Oct 01 13:27:02 2013] [notice] ModSecurity: LIBXML compiled version="2.7.6"

Il pacchetto installa varie configurazioni aggiuntive in /etc/httpd/modsecurity.d. Qui sono contenute le regole di base (che prevengono gli attacchi web standard, controllano l’input, evitano fughe tipo ../.. e così via) più le regole raccomandate da OWASP, organizzate nella directory activated_rules.

Mod_security si rivela utile, come detto, per sistemare al volo i problemi delle applicazioni web: exploit noti, attacchi di forza bruta, e tentativi di Denial Of Service.

Tuttavia, proteggere un’applicazione con delle regole personalizzate richiede una comprensione della sintassi di SecRule ma, con la pratica, può essere memorizzata facilmente. SecRule confronta una specifica variabile, verbo, header o metodo HTTP, con una stringa definita dall’utente. Se il confronto è positivo, viene lanciata un’azione specificata in un terzo parametro. Questa azione può loggare (log), bloccare (deny) o accettare (accept) la richiesta, o perfino (è il caso di exec) interagire con il sistema.

Ipotizziamo la presenza di una pagina con dei problemi su /bugged.php, che vogliamo rendere inaccessibile finché non verranno fixati i bug. Grazie a mod_security è possibile intervenire immediatamente sull’istanza dell’applicativo e correggerlo senza dover aspettare che gli sviluppatori aggiustino il problema e rilascino una nuova versione del software. È sufficiente caricare l’engine di regole di mod_security, specificare che si vogliono loggare solo le request che corrispondono alle regole specificate, impostare un’azione di default, e scrivere la regola vera e propria nel VirtualHost dell’applicativo. Infine, è necessario un restart di httpd. Ecco il codice:

SecRuleEngine On
SecAuditEngine RelevantOnly
SecDefaultAction allow
SecRule REQUEST_URI "/bugged.php" "deny"

Ciò che rende mod_security più potente delle direttive standard di Apache (per esempio Deny sulla risorsa) è la possibilità di interagire con i dati scambiati tra il server e il client, e perfino con SSL. Si può confrontare tutto ciò che riguarda il protocollo HTTP. Si possono intercettare molte variabili interessanti, per esempio con REQUEST_HEADERS si può lavorare sullo user-agent e fermare i tool di scansione automatica:

SecRule SecRule REQUEST_HEADERS:User-Agent "nikto" "deny"

Un’altra applicazione utile di mod_security è l’interazione con il sistema per bloccare gli IP che stanno sferrando un attacco. Una volta un cliente aveva un’applicativo sotto attacco. L’attacker stava cercando di fare dei brute force sul form di login, facendo provenire le richieste da una grande quantità di host geograficamente sparsi. Anche se le credenziali di accesso erano difficili da violare, questa serie di POST stava rallentando l’intero server. Così, ho installato mod_security e con vim ho scritto qualche riga nel VirtualHost. Dopo aver impostato lo script esterno e riavviato Apache, iptables ha iniziato pian piano a bloccare gli IP. Ecco le direttive del VirtualHost:

SecRuleEngine On
SecAuditEngine RelevantOnly
SecDefaultAction allow
SecRule REQUEST_URI "/login.php" "chain,deny"
SecRule REQUEST_METHOD "POST" "exec:/root/bin/ipt.rb"

Qui, ogni tentativo di fare POST su login.php invoca un evento di sistema (/root/bin/ipt.rb). Entrambe (chain) le regole di SecRule devono fare match con le stringhe specificate per far eseguire lo script. chain è un’azione speciale che concatena le regole come un AND logico. Infine, ecco lo script che blocca gli IP a livello netfilter:

#!/usr/bin/ruby
system("/sbin/iptables -A INPUT -s " + ENV['REMOTE_ADDR'] + " -j DROP")

Ovviamente lo script che uso in questi casi è leggermente più complesso e robusto, ma in questo esempio ciò che voglio porre in risalto è l’uso delle variabili HTTP. L’azione exec non permette di passare argomenti agli script di sistema, ma allo script sono accessibili le variabili d’ambiente tramite l’hash ENV. Nel caso di Ruby, si accede a REMOTE_ADDR con una sintassi del tipo ENV[‘REMOTE_ADDR’].

Dopo un po’ di lavoro questo piccolo accorgimento ha fermato l’attacco e quando l’attaccante ha esaurito gli host da cui cercava di eseguire i suoi tentativi di forza bruta, il problema è stato risolto.

Un altro uso recente di mod_security riguarda una potenziale infezione partita da php.net. Si osservi come una policy di sicurezza proattiva è stata applicata con immediatezza grazie a mod_security.

Un’applicazione web dovrebbe essere monitorata e sviluppata con tutti i crismi, e rilasciata come software affidabile e senza bug, ma questo succede solo nei sogni. Mod_security può aiutare per proteggere le applicazioni critiche, se ci si può permettere un minimo sacrificio in termini di performance.