Introduzione
Nell' articolo sui chmod (a cui rinviamo per qualsiasi dubbio relativo al sistema dei permessi sui files) avevamo constatato come qualsiasi script richiamato dal Webserver ne erediti le autorizzazioni, e operi con tali permessi anzichè quelli proprii dell'utente a cui appartiene il file "*.php".
Questa particolarità comporta che in un server condiviso (è il caso tipico dei VirtualHost) tutti gli "users" di spazi WEB differenti eseguano i propri script come se appartenessero al medesimo utente: in questo modo uno script del Sig. X teoricamente sarebbe perfettamente in grado di leggere un file di dati che si trovi nello spazio del Sig. Y, o che comunque non gli appartenga (come succede ad esempio per i file di sessione).
Decisamente si tratta di un' eventualità da evitare e per fortuna esistono diverse soluzioni che consentono di correre ai ripari, ed esamineremo le più importanti nelle prossime pagine.
La modalità sicura
safe_mode è una direttiva di configurazione di Php, impostarla a On rappresenta il metodo più radicale (anche troppo) per mettere fine alla questione dei permessi, la sua attivazione comporta le seguente serie di restrizioni:
- Php verifica sempre lo UID ("User ID") del file in esecuzione e opera simulando tale utente (wrapping)
- Gran parte delle operazioni sui files come fopen(), copy() e readfile() (vedi manuale per una lista completa) non potranno più coinvolgere file e directory appartenenti ad utenti diversi dal proprietario dello script in esecuzione.
- Anche include() e require() risentono della restrizione al punto 2, a meno che non coinvolgano file inseriti nella "safe_mode_include_dir" indicata.
- Qualsiasi chiamata di sistema (vedi exec(), system(), passtru()) può riguardare esclusivamente gli eseguibili inseriti nella "safe_mode_exec_dir" indicata.
- Funzioni come set_time_limit(), dl(), shell_exec() e così pure l'operatore backtick (``) vengono totalmente disabiltate.
Vi sarebbero altre particolarità ma per tutti i dettagli è preferibile rivolgersi al manuale.
Queste limitazioni sono in qualche modo mitigabili attivando "safe_mode_gid", in questo caso la verifica sull' identità di appartenenza, tra lo script e il file a cui lo script tenta di accedere, riguarda soltanto il "group".
Come attivare la modalità sicura?
È possible intervenire direttamente sul php.ini (valido per tutto il server). Ad esempio:
safe_mode = On
safe_mode_include_dir = /usr/local/php/safe_include
safe_mode_exec_dir = /usr/local/php/safe_exec
safe_mode_gid = Off
Oppure nel file di configurazione di Apache (httpd.conf) (coinvolge soltanto il singolo sito)
<VirtualHost www.micro-net.it>
ServerName micro-net.it
DocumentRoot /www/siti/dominio1
php_admin_value safe_mode On
php_admin_value safe_mode_include_dir /usr/local/php/safe_include
php_admin_value safe_mode_exec_dir /usr/local/php/safe_exec
php_admin_value safe_mode_gid Off
</VirtualHost>
Problemi derivanti dal passaggio alla modalità sicura
Se improvvisamente vi doveste accorgere che gli script che fino ad ieri funzionavano correttamente ora danno uno strano errore:
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not
allowed to access /path/file.ext owned by uid 44 in /path/script.php on line 2
Niente paura! Probabilmente l'amministratore ha passato il server in modalità sicura e si è dimenticato di avvertirvi...
Ora i file appartenenti all'utente apache-php, cioè quelli che erano stati generati attraverso l'esecuzione di uno script, non sono più accessibili in quanto continuano a presentare lo UID di Apache, mentre i vostri script ora agiscono con i permessi dell'utente dello spazio WEB, e quindi il "wrapper" li blocca.
Non resta che chiedere all'ISP di modificare il proprietario dei file divenuti inacessibili; oppure tentare di farne il download, cancellarli sul server e ri-uplodarli (sperando di avere i permessi adeguati sulla directory che li contiene) affinchè acquisiscano lo UID dell'utente titolare dello spazio WEB.
È davvero necessaria la modalità sicura?
Il manuale php recita testualmente:
"La modalità sicura in PHP è un tentativo di risolvere i problemi di sicurezza relativi ala condivisione del server. È concettualmente scorretto tentare di risolvere questo problema a livello di PHP, ma giacchè le alternative a livello di Webserver e sistema operativo non sono molto realisiche, molte persone, e specialmente gli ISP, per ora ricorrono al safe mode".
L'opinione che personalmente mi sono fatto è che si tratti di un modo per risolvere comodamente, e in un sol colpo, tutta una serie di problemi che sarebbero comunque gestibili con configurazioni più mirate, ma che richiederebbero un maggior lavoro.
Non a caso è la soluzione adottata da servizi di tipo gratutito o molto economico, i quali si trovano spesso a gestire un numero elevatissimo di VirtualHost sullo stessa macchina. Inutile precisare che uno spazio su server dedicato non avrà bisogno di alcuna di queste cautele.
Alternative meno radicali
open_basedir
safe_mode non rappresenta l'unico sistema per limitare il campo di azione degli script, è possibile indicare per ogni VirtualHost una sorta di DocumentRoot entro cui limitare l'ambito degli script php.
Detta così sembra una cosa difficile, in realtà si tratta di aggiungere una riga:
<VirtualHost www.micro-net.it>
ServerName micro-net.it
DocumentRoot /www/utente1/docs
php_admin_value open_basedir /www/utente1
</VirtualHost>
Come si vede la "root" di Php è stata settata un po' più "alta" rispetto alla DocumentRoot di Apache, in questo modo sarà possibile ottenere anche un altro effetto molto utile: eventuali file ".inc" che verranno inseriti nella directory "utente1", sono leggibili o includibili dagli script php ma allo stesso tempo non saranno raggiungibili qualora il navigatore tentasse di visualizzarli sul browser digitandone l'URL preciso.
disable_functions
Questa direttiva consente di disabilitare le funzioni di Php e in modo particolare si rivela utile con quelle potenzialmente pericolose, può essere inserita soltanto nel php.ini. Esempio:
disable_functions readfile,system[,altra_funzione]
gabbia Chroot
Ho lasciato per ultima l'ipotesi meno diffusa ma più sofisticata ed efficace.
Consiste, grossomodo, nel creare attraverso il comando Unix chroot una sorta di "gabbia di protezione" intorno alla DocumentRoot. Con questo sistema l'utente dello spazio WEB viene ad assumere poteri simili a quelli di root ma limitati alla directory in questione.
Si tratta di una tecnica appannaggio degli amministratori Unix con una certa esperienza, inoltre con i settaggi Php ha poco a che vedere, quindi per qualsiasi informazione vi rinvio a questo interessante articolo che rappresenta un utile punto di partenza (in lingua inglese).
Conclusioni
Con questo articolo spero di aver fornito una panoramica sulle tecniche utili a rendere più sicuri i settaggi di uno spazio WEB in cui sia disponibile Php, per ogni approfondimento vi invito a consultare la documentazione relativa ad Apache, Linux e, ovviamente, lo stesso manuale Php.