Le premier problème rencontré après ma migration vers CentOS a été l'upload de fichiers qui ne fonctionne plus.
Pourtant, après avoir vérifié sur le web, les droits de mon répertoire d'upload étaient bien ajustés :
sudo chown apache:apache /var/www/upload_dir
sudo chmod 774 /var/www/upload_dir
Rien à faire, j'ai toujours un « permission denied » dans mon /etc/httpd/logs/ssl_error_log …
Que s'est-t-il passé ? La gestion traditionnelle des droits sur les répertoires est soumises à SELinux (Security-Enhanced Linux). Le principe est que les utilisateurs et les applications peuvent changer les droits d'accès aux répertoires du serveur et pas toujours de la bonne manière. L'administrateur ne peut contrôler tous ces changements de droits.
SELinux va donc recouvrir tous les dossiers du serveur par un niveau ré-haussé de sécurité. Par exemple, il va interdire les accès autres que lecture seule pour http (apache) dans mon /var/www/.
On peut changer le statut de SELinux en modifiant /etc/selinux/config (selinux=enfocing, permissive ou disabled) ou en écrivant
Setenforce 0
Cette commande va permettre de désactiver SELinux mais ne résiste pas à un reboot. Si on modifie le fichier /etc/selinux/config, ça résiste à un reboot.
Passer en disabled ou permissive permet de retrouver l'accès écriture à mon dossier et donc l'upload des fichiers fonctionne à nouveau. Le problème, c'est qu'on perd l'avantage de SELinux.
Comment configurer le système pour ouvrir les droits d'écriture sur certains répertoires (/var/www/upload_dir) et pas sur le reste ?
Voici quelques commandes utiles de SELinux.
Tout d'abord, on peut afficher le « contexte SELinux » associé à un fichier :
ls -Z /var/www/index.php
=> -rw-r--r-- username username system_u:object_r:httpd_sys_content_t /var/www/html/index.html
system_u:object_r:httpd_sys_content_t nous renseigne sur le contexte SELinux sous le format utilisateur:rôle:type:mls. (mls n'est pas affiché)
On peut tester cette commande sur quelques fichiers du serveur pour mieux cerner son fonctionnement.
Pour résumé, apache (httpd_t) peut lire des fichier de type httpd_sys_content_t. Par exemple, apache ne pourrait pas lire un fichier dans le home d'un utilisateur.
Comment modifier le contexte des fichiers ?
chcon -v --type=httpd_sys_content_t /var/www/newfile.php
En récursif :
chcon -vR –type=httpd_sys_content_t /var/www/newdir
Finalement, voici le type qu'on va appliquer aux fichiers dans lesquels on souhaite uploader des fichiers :
chcon -vR unconfined_u:object_r:httpd_sys_rw_content_t:x0 /var/www/upload_dir
Maintenant qu'on a ouvert l'accès à l'upload de fichier, il reste à faire ça correctement en modifiant le code php pour :
- vérifier que l'extension du fichier est dans une « white list » (gif, jpg, png, pdf, doc, etc.) ;
- vérifier que le type du fichier correspond bien à ce que son extension prétend être.