Hardening di un web server Apache: differenze tra le versioni
Riga 395: | Riga 395: | ||
=== Come scrivere nuove regole === | === Come scrivere nuove regole === | ||
Il modulo <code>mod-security</code> può utilizzare due tipi di filtro: | |||
* Simple Filter: nella forma <code>SecFilter directive</code> | |||
* Advanced Filter: nella forma <code>SecFilterSelective directive</code> | |||
I filtri Simple Filter | |||
Simple filter directives apply on any filters you turned on, so in our case, on GET and POST request. | |||
the syntax of simple filter directive is: | |||
SecFilter KEYWORD [ACTIONS] | |||
KEYWORD can be a string or a regular expression, ACTIONS is optionnal, if it is not defined, mod-security will use the SecFilterDefaultAction value (log and return 500 error page as we defined earlier, in mod-security skeleton file). | |||
Advance filters do filter specific streams. Its syntax is: | |||
SecFilterSelective LOCATION KEYWORD [ACTIONS] | |||
Same here, ACTIONS is optionnal, LOCATION consist of a serie of location identifier separated by pipes (|). An advance filter looks like: | |||
SecFilterSelective "REMOTE_ADDR|REMOTE_HOST" KEYWORD | |||
you can get the full list of keywords from mod-security site . For actions, you might want to refer to mod-security documentation action page. | |||
Among the most important actions, we could highlight: | |||
pass:Allow request to continue on filter match. This action is useful when you want to log a match but otherwise do not want to take action. | |||
allow:This is a stronger version of the previous filter. After this action is performed the request will be allowed through and no other filters will be tried. | |||
deny:Interrupt request processing on a filter match. Unless the status action is used too, ModSecurity will immediately return a HTTP 500 error code | |||
status:Use the supplied HTTP status code when request is denied. | |||
redirect:On filter match redirect the user to the given URL. | |||
exec:Execute a binary on filter match. Full path to the binary is required | |||
log: Log filter match to the Apache error log. | |||
nolog:Do not log the filter match. This will also prevent the audit logging from taking place. | |||
chain: Rule chaining allows you to chain several rules into a bigger test. Only the last rule in the chain will affect the request but in order to reach it, all rules before it must be matched too. | |||
auditlog/noauditlog: Log/Do not log the transaction information to the audit log. |
Versione delle 20:57, 11 nov 2010
Introduzione
Apache come ogni software usato in rete, è soggetto a bug che lo possono rendere vulnerabile ad attacchi di diversa natura: Denial of Service, Information Disclosure, System Violation, Data Corruption...
La storia di Apache ha avuto vulnerabilità anche serie, prontamente corrette, e problemi minori, applicabili a situazioni particolari.
Al giorno d'oggi in realtà la maggior parte dei problemi di sicurezza di un sito web non è dovuta al software che fa da server web (Apache), ma dalle applicazioni web, basate su diversi linguaggi.
In questa guida vedremo come modificare alcune direttive dei file di configurazione di Apache per migliorare la sicurezza del demone, installeremo alcuni moduli aggiuntivi molto utili per aumentare la robustezza del nostro servizio web e, infine, vedremo alcuni consigli per sviluppare con un occhio rivolto alla sicurezza le nostre applicazioni in PHP, Perl o in altri linguaggi.
Direttive di Apache
Debian prevede un file specifico per la configurazione e la gestione della sicurezza di Apache: /etc/apache2/conf.d/security
.
Si consiglia quindi di apportare in questo file tutte le modifiche seguenti che desiderate implementare nella vostra configurazione.
Impedire il controllo degli accessi per directory
Tramite l'uso dei file .htaccess è possibile definire direttive di configurazione specifiche in ogni singola directory, direttamente da parte di chi ci uploada file. Su un server su cui possono uploadare documenti anche webmaster non noti, è opportuno limitare il più possibile questa funzionalità con una radicale disabilitazione dell'uso degli .htaccess su ogni directory:
<Directory /> AllowOverride None </Directory>
E' poi possibile "aprire" per directory e funzionalità selezionate, la possibilità di fare l'override della conf generale tramite i file .htaccess locali.
Le diverse opzioni di AllowOverride
controllano quali direttive possono essere definite nei file .htaccess: All, AuthConfig, FileInfo, Indexes, Limit, Options, None
.
Impedire la lettura via Web a file .htaccess
Nella configurazione di Apache di default è presente un provvidenziale:
<Files ~ "^\.ht"> Order allow,deny Deny from all Satisfy All </Files>
che impedisce la lettura via Web di file che iniziano con .ht e di conseguenza evita che un utente via Web possa leggere le informazioni delicate che possono essere presenti nei file .htaccess. Ovviamente se si decide di cambiare il nome del file che controlla gli accessi sulle singole directory (direttiva di default: AccessFileName .htaccess
) si dovrà adattare anche questa configurazione.
Impedire la lettura via Web a file di configurazione
Analogamente al caso precedente può essere utile impedire l'accesso diretto a file che possono contenere parametri di configurazione (che finiscono con inc o conf):
<FilesMatch \.(inc|conf)> Order Allow,Deny Deny from all </FilesMatch>
Disattivare l'uso di .cgi e .shtml al di fuori di directory predefinite
Tramite la direttiva AddHandler
si può dire al server web di trattare file con determinate estensioni con un apposito handler (per esempio un modulo per gestire pagine dinamiche). Di default sulla conf di Apache sono disattivati gli handler per script .cgi e .shtml:
#AddHandler cgi-script .cgi #AddType text/html .shtml #AddHandler server-parsed .shtml
per cui se si vogliono usare dei Server Side Includes o degli script CGI al di fuori della directory predefinita con la direttiva ScriptAlias /cgi-bin/ "@@ServerRoot@@/cgi-bin/"
, queste righe vanno scommentate.
Disabilitare l'accesso pubblico a server-info e server-status
Apache prevede due location speciali che possono essere utilizzate per visualizzare informazioni utili al sysadmin sullo stato del server web e la sua configurazione. Di default questo sono disabilitate, ma possono essere abilitate limitando gli IP da cui possono essere visualizzate. In genere è consigliabile non renderle visibili pubblicamente (in particolare server-info, che di fatto espone la configurazione completa di Apache).
#<Location /server-status> # SetHandler server-status # Order deny,allow # Deny from all # Allow from .your-domain.com #</Location> #<Location /server-info> # SetHandler server-info # Order deny,allow # Deny from all # Allow from .your-domain.com #</Location>
Se si vogliono visualizzare server-status e server-info, scommentare queste righe e specificare i domini o gli IP da cui è permesso visualizzarli.
Disabilitare il file listing in directory senza index.html (o analoghi nomi di file predefiniti)
Con la direttiva DirectoryIndex
si definiscono quali file Apache automaticamente cerca, e visualizza, quando il client richiede un URI che contiene solo il nome di una directory, senza specificare il nome della pagina web. Se il client accede ad una directory che non contiene uno di questi index predefiniti, Apache visualizza direttamente tutti i file contenuti nella directory stessa, esponendo infomazioni potenzialmente riservate.
Se si vuole disabilitare il listing di tutti i file presenti in una directory, quando non è presente il file di indice, si usa la direttiva Options -Indexes
:
<Location /> Options -Indexes </Location>
Per disabilitare il directory listing si può anche direttamente rimuovere il caricamento (o la compilazione) del modulo mod_autoindex; se invece si vuole abilitarlo, ma al contempo escludere dal listing dei file potenzialmente sensibili si può usare una direttiva come:
IndexIgnore .??* *.bak *.swp *# HEADER* README* RCS
Limitare le richieste del client
Di default Apache permette al client di eseguire richieste particolarmente esose che possono essere impropriamente utilizzate per un Denial Of Service attack. Esistono alcune direttive che limitano alcune caratteristiche delle richieste che il client può eseguire:
LimitRequestBody 10240
: Limita a meno di 10 Kb le dimensioni del body di una richiesta HTTP (PUT o POST). Di default questo valore è 0 (infinito). Si può specificare un valore in byte diverso, avendo cura di non interferire con il normale funzionamento di un sito.LimitRequestFields 30
: Imposta a 30 il numero massimo di header HTTP che il client può inserire nella sua richiesta. Il valore di default è 100, in genere è difficile avere richieste che abbiamo più di 20-30 header.LimitRequestFieldSize 500
: Imposta a 500 byte la dimensione massima di ogni singolo header HTTP in una richiesta. Il valore di default è 8190.LimitRequestLine 500
: Imposta a 500 byte le dimensioni della richiesta HTTP (metodo, URL e protocollo), limitando di fatto le dimensioni dell'URL stesso che un client può chiedere (attenzione a dimensionarlo secondo i nomi e i parametri passati negli URL del proprio sito). Valore di default 8190.
Disabilitare l'uso di symlink
Di default Apache se trova in una directory di un suo sito Web un link simbolico all'infuori della directory stessa, prova a seguirlo e fornire il file linkato. Questo comportamento può essere usato per far vedere via web dati che non dovrebbero essere visibili (immaginare un webmaster che digita il seguente comando nella sua home:
ln -s /etc/passwd passwd.html.
Per impedirlo si deve definire, nella conf generale o in un specifico contenitore:
Options -FollowSymLinks
Esiste anche la possibilità di configurare Apache per seguire solo i symlink a file posseduti dall'utente, permettendo il symlinking all'interno del proprio sito web (e appesantendo non poco il server, per la quantità di controlli aggiuntivi che deve fare per ogni file servito):
Options -FollowSymLinks +SymLinksIfOwnerMatch.
Modificare la direttiva ServerTokens
Di default il valore della direttiva è:
ServerTokens Full
e indica quante informazioni vengono inviate dal server nell'header. Può essere utile modificare il valore di default per una questione di sicurezza: meno informazioni forniamo sul nostro server, sulla versione di Apache e sui moduli installati, e meno facile sarà trovare un exploit per bucarci.
Le possibili opzioni sono:
- Full
Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny3 with Suhosin-Patch Server at demo
- OS
Apache/2.2.9 (Debian) Server
- Minimal
Apache/2.2.9 Server
- Minor
Apache/2.2 Server
- Major
Apache/2 Server
- Prod
Apache Server
Pur sembrando una cosa da poco, si noti che è assai semplice recuperare le informazioni di questa direttiva, ad esempio inviando una richiesta GET sbagliata al web server da attaccare:
ferdy@server:~$ telnet 127.0.0.1 80 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. GET /index.ht PIPPO/1.1 host: 127.0.0.1 HTTP/1.1 404 Not Found Date: Wed, 10 Nov 2010 23:23:00 GMT Server: Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch mod_ssl/2.2.9 OpenSSL/0.9.8g Vary: Accept-Encoding Content-Length: 347 Connection: close Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>404 Not Found</title> </head><body> <h1>Not Found</h1> <p>The requested URL /index.ht was not found on this server.</p> <hr> <address>Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch mod_ssl/2.2.9 OpenSSL/0.9.8g Server at 127.0.0.1 Port 80</address> </body></html> Connection closed by foreign host.
Il modulo mod_evasive
di Apache
Il modulo di Apache mod_evasive
(Debian Package, Sito web ufficiale) è un modulo aggiuntivo di Apache studiato per fornire un po' di protezione contro gli attacchi DDoS e di brute force.
Per installarlo è sufficiente:
# aptitude install libapache2-mod-evasive
Durante l'installazione del modulo il servizio Apache sarà riavviato e il modulo automaticamente caricato al successivo riavvio. E' possibile verificare il corretto caricamento del modulo con:
# find /etc/apache2/ | xargs fgrep -nH evasive
Su alcuni siti viene suggerito di aumentare la sicurezza del modulo aggiungendo alcuni parametri di configurazione al file /etc/apache2/mods-available/mod-evasive.load
:
<IfModule mod_evasive20.c> DOSHashTableSize 3097 DOSPageCount 5 DOSSiteCount 100 DOSPageInterval 1 DOSSiteInterval 1 DOSBlockingPeriod 600 </IfModule>
Un riavvio del server Apache caricherà la nuova configurazione:
# /etc/init.d/apache2 restart
E possibile testare il corretto funzionamento del modulo con il seguente script, installato insieme al modulo stesso:
# perl /usr/share/doc/libapache2-mod-evasive/examples/test.pl
Dovreste ottenere un risultato del genere:
HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 200 OK HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 200 OK HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden
Il modulo mod_security
di Apache
Il modulo di Apache mod_security
e’ un modulo che permette di loggare i piu’ comuni attacchi ad Apache come XSS, remote command execution, file disclosure e tutto quello che puo’ essere considerato dannoso nei confronti di un povero web server. Il sito ufficiale del modulo è http://www.modsecurity.org , ma per fortuna esiste un pacchetto Debian, presente in Squeeze e nei Backport di Lenny.
Per installarlo è quindi sufficiente:
- Lenny:
# apt-get -t lenny-backports install libapache-mod-security
- Squeeze:
# apt-get install libapache-mod-security
Abilitiamo il modulo appena installato e ci troveremo già con una configurazione minimale funzionante:
# a2enmod mod-security # /etc/init.d/apache2 restart
La forza di questo modulo, però, risiede nella sua possibilità di tuning. Creiamo quindi il file /etc/apache2/conf.d/mod_security
e impostiamo una prima configurazione di base personalizzata:
<IfModule mod_security.c> # Basic configuration options SecRuleEngine On SecRequestBodyAccess On SecResponseBodyAccess Off # Handling of file uploads # TODO Choose a folder private to Apache. # SecUploadDir /opt/apache-frontend/tmp/ SecUploadKeepFiles Off # Debug log SecDebugLog /var/log/apache2/modsec_debug.log SecDebugLogLevel 0 # Serial audit log SecAuditEngine RelevantOnly SecAuditLogRelevantStatus ^5 SecAuditLogParts ABIFHZ SecAuditLogType Serial SecAuditLog /var/log/apache2/modsec_audit.log # Maximum request body size we will # accept for buffering SecRequestBodyLimit 131072 # Store up to 128 KB in memory SecRequestBodyInMemoryLimit 131072 # Buffer response bodies of up to # 512 KB in length SecResponseBodyLimit 524288 </IfModule>
In questo primo template di default abbiamo impostato alcune regole:
- SecFiterEngine (On|Off): abilita o disabilita il modulo
- SecFilterCheckUrlEncoding (On|Off): controlla se i caratteri speciali vengono encodati prima di essere passati all'URL
- SecFilterCheckUnicodeEncoding (On|Off): controlla se l'encoding Unicode è valido
- SecFilterForceByteRange: forza le richiest dentro un range predefinito di bytes. Può aiutare a prevenire attacchi stack overflow. Il range può essere impostato da 0 a 255.
- SecServerSignature: cambia la signature nella risposta agli header. Perchè funzioni è necessaria la direttiva Apache
ServerTokens Full
. - SecAuditEngine (On|Off|RelevantOnly): abilita o disabilita il loggind di mod-security. RelevantOnly logga solo le richieste che coincidono con una regola impostata.
- SecAuditLog /path/to/audit_log: define the file where mod-security will write its logs.
- SecFilterDebugLog /path/to/debug_log: il percorso del log di debug.
- SecFilterDebugLevel (0-9): mod-security ha 10 livelli di debug: 0 (non vengono loggate informazioni di debug) - 9 (viene loggato tutto).
- SecFilterScanPost (On|Off): di default, mod-security scansiona solo le richieste GET datas. Abilitando questa direttiva gli faremo scansionare anche i dati POST
Verifichiamo la nuova configurazione:
# apache2ctl -t Syntax OK
e riavviamo Apache:
/etc/init.d/apache restart
A questo punto potremmo voler abilitare la protezione per alcuni attacchi comuni attraverso le cosiddette Core Rules, che possiamo scaricare da qui: http://sourceforge.net/projects/mod-security/files/modsecurity-crs/0-CURRENT/modsecurity-crs_2.0.8.tar.gz/download
Una volta scaricato il file delle regole (al momento della stesura di questa guida il file più aggiornato è modsecurity-crs_2.0.8.tar.gz), copiamolo al posto giusto e scompattiamolo:
# cp -rpf ~/modsecurity-crs_2.0.8.tar.gz /etc/apache2/ # cd /etc/apache2/; tar -zxvvf modsecurity-crs_2.0.8.tar.gz # mv modsecurity-crs_2.0.8 modsecurity-crs
Apriamo il file di configurazione di mod_security:
# nano /etc/apache2/conf.d/mod_security
e aggiungiamo alla fine del file le righe:
Include /etc/apache2/modsecurity-crs/*.conf Include /etc/apache2/modsecurity-crs/base_rules/*.conf
Verifichiamo la nuova configurazione:
# apache2ctl -t Syntax OK
e riavviamo Apache:
/etc/init.d/apache restart
Il modulo mod_security
e Drupal
Sembra che alcune regole possano interferire con l'installazione e/o le normali operazioni di amministrazione del CMS Drupal. A questo indirizzo è possibile trovare un how-to per ovviare al problema.
Documentazione di mod_security
A questo indirizzo è possibile trovare la documentazione ufficiale di ModSecurity, unitamente a diversi esempi di regole personalizzate.
Come scrivere nuove regole
Il modulo mod-security
può utilizzare due tipi di filtro:
- Simple Filter: nella forma
SecFilter directive
- Advanced Filter: nella forma
SecFilterSelective directive
I filtri Simple Filter
Simple filter directives apply on any filters you turned on, so in our case, on GET and POST request. the syntax of simple filter directive is: SecFilter KEYWORD [ACTIONS]
KEYWORD can be a string or a regular expression, ACTIONS is optionnal, if it is not defined, mod-security will use the SecFilterDefaultAction value (log and return 500 error page as we defined earlier, in mod-security skeleton file).
Advance filters do filter specific streams. Its syntax is: SecFilterSelective LOCATION KEYWORD [ACTIONS] Same here, ACTIONS is optionnal, LOCATION consist of a serie of location identifier separated by pipes (|). An advance filter looks like: SecFilterSelective "REMOTE_ADDR|REMOTE_HOST" KEYWORD you can get the full list of keywords from mod-security site . For actions, you might want to refer to mod-security documentation action page. Among the most important actions, we could highlight: pass:Allow request to continue on filter match. This action is useful when you want to log a match but otherwise do not want to take action. allow:This is a stronger version of the previous filter. After this action is performed the request will be allowed through and no other filters will be tried. deny:Interrupt request processing on a filter match. Unless the status action is used too, ModSecurity will immediately return a HTTP 500 error code status:Use the supplied HTTP status code when request is denied. redirect:On filter match redirect the user to the given URL. exec:Execute a binary on filter match. Full path to the binary is required log: Log filter match to the Apache error log. nolog:Do not log the filter match. This will also prevent the audit logging from taking place. chain: Rule chaining allows you to chain several rules into a bigger test. Only the last rule in the chain will affect the request but in order to reach it, all rules before it must be matched too. auditlog/noauditlog: Log/Do not log the transaction information to the audit log.