9 votes

Comment puis-je utiliser SELinux pour confiner des scripts PHP ?

Je veux compartimenter différentes applications PHP sur mon serveur web SL6.4 (reconstruction de RHEL 6.4) afin qu'elles ne puissent pas accéder aux données des autres. Il semble que SELinux puisse le faire, mais je ne suis pas sûr des détails. Ma question comporte deux parties :

  1. Comment SElinux gère-t-il les scripts PHP s'exécutant dans le processus Apache avec mod_php ? Le processus entre-t-il d'une manière ou d'une autre dans le contexte du script lors de l'exécution du script PHP, ou cela fonctionne-t-il uniquement lorsque les scripts sont exécutés hors du processus via CGI ou FastCGI ? S'il effectue une transition vers un contexte de script pour exécuter le script PHP, qu'empêche un bug PHP de déclencher une transition vers le contexte principal httpd ? S'il me faut une méthode de déploiement PHP alternative, il serait bon de le savoir.
  2. Comment puis-je séparer les scripts/applications afin que, par exemple, TinyTinyRSS ne puisse pas accéder aux éléments appartenant à OpenCloud ? Il semble que je devrais être en mesure de le faire en désactivant httpd_unified et en fournissant des ensembles de contextes distincts httpd_ttrss_* et httpd_opencloud_*, parallèles à httpd_user_foo et httpd_sys_foo. Il pourrait même me suffire d'utiliser la distinction sys/user sans nouveaux contextes, étant donné le nombre d'applications que je peux utiliser. Mais je n'ai pas trouvé beaucoup de documentation sur les implications exactes de la désactivation de httpd_unified, ni sur la manière de configurer différents contextes HTTP. Particulièrement avec des scripts PHP exécutés via mod_php.

Je suis prêt à créer de nouveaux modules de politique SELinux, mais j'aimerais disposer de documentation indiquant ce que je dois inclure dans la nouvelle politique et comment la faire intégrer harmonieusement avec la politique ciblée SELinux.

Si c'est une cause perdue d'essayer de réaliser cette séparation uniquement avec SELinux et que j'ai besoin de lancer des httpd séparés dans des contextes différents, ou éventuellement même des conteneurs LXC, cela constituerait également une réponse utile.

0 votes

Cela peut dépendre du moyen par lequel vous voulez exécuter PHP, vous avez marqué 'mod-php' mais je voulais juste confirmer que c'est la méthode que vous souhaitez utiliser.

0 votes

@MIfe Je suis actuellement en train d'utiliser mod_php, mais je suis prêt à passer à une méthode de déploiement différente si cela simplifie les choses.

6voto

Matthew Ife Points 22370

La meilleure façon d'atteindre ce niveau de séparation est de ne pas utiliser de transitions de type mais des transitions de catégorie / MCS. Cela agit un peu comme la mise en oeuvre svirt dans les trucs libvirt KVM.

D'accord, la première chose que vous allez devoir faire est de télécharger un module httpd appelé mod_selinux. Il circule dans les dépôts fedora depuis un certain temps, mais n'a malheureusement jamais vraiment été intégré aux systèmes EL6.

Quoi qu'il en soit, vous pouvez reconstruire le paquet à partir des sources fedora. J'ai fait cela sur une machine fedora mais vous pouvez simplement télécharger le même paquet depuis un miroir. J'ai utilisé F16 comme base car il exécute httpd-2.2.

yumdownloader --source mod_selinux --releaserver=16
...
mod_selinux-2.2.2454-3.fc15.src.rpm                        |  23 kB   00:00

Ensuite, une fois téléchargé, reconstruisez-le sur votre boîte EL6.

rpmbuild --rebuild mod_selinux-2.2.2454-3.fc15.src.rpm
...
Wrote: /home/build/rpmbuild/RPMS/x86_64/mod_selinux-2.2.2454-3.el6.x86_64.rpm

Enfin, installez le module.

rpm -i /home/build/rpmbuild/RPMS/x86_64/mod_selinux-2.2.2454-3.el6.x86_64.rpm

Le RPM installe un module pour httpd dont vous aurez besoin et aussi une politique pour httpd qui est également nécessaire pour que cela fonctionne.

Le fichier de ce module est installé dans /etc/httpd/conf.d/mod_selinux.conf.

La première étape de ce processus est d'augmenter le nombre de catégories dans lesquelles le processus httpd principal s'exécute, afin qu'il puisse produire des threads enfants qui couvrent la plage correcte. Dans le fichier, changez :

selinuxServerDomain     *:s0

À

selinuxServerDomain     *:s0-s0:c0.c1023

Ensuite, vous devez attribuer à chaque hôte virtuel dans apache une catégorie. Cela se fait en ajoutant une ligne comme dans l'exemple ci-dessous appelée selinuxDomainVal.

    DocumentRoot /var/www/vhosts/host1
    ServerName host1.virtual
    selinuxDomainVal *:s0:c0

    DocumentRoot /var/www/vhosts/host2
    ServerName host2.virtual
    selinuxDomainVal *:s0:c1

Ensuite, dans le répertoire de documents racine de chaque hôte, reétiquetez leurs répertoires de documents à la même catégorie que ceux étiquetés dans la configuration httpd.

chcon -R -l s0:c0 /var/www/vhosts/host1
chcon -R -l s0:c1 /var/www/vhosts/host2

Si vous voulez que l'étiquetage soit pris en compte si vous faites une retouche système, vous feriez mieux de mettre à jour la politique locale aussi !

semanage fcontext -a -t httpd_sys_content_t -r s0-s0:c0 '/var/www/vhosts/host1(/.*)?'
semanage fcontext -a -t httpd_sys_content_t -r s0-s0:c1 '/var/www/vhosts/host2(/.*)?'

Et c'est tout ! Il est impossible de quitter votre répertoire de documents et d'explorer les autres maintenant.

3 votes

Notez que mod_selinux ne protège pas complètement contre les bugs PHP - si un attaquant peut effectuer une corruption de mémoire contrôlée après avoir exploité un hôte virtuel avec un contexte restreint, il peut être en mesure d'injecter du code dans le processus Apache pour être exécuté dans le contexte httpd par défaut, ou de désactiver mod_selinux pour les requêtes ultérieures gérées par le même processus de travail. Les caches comme APC seront également partagés entre tous les hôtes virtuels. Si cela est une préoccupation, une séparation complète des processus est nécessaire (en utilisant CGI ou FastCGI pour PHP, ou même des instances httpd séparées si vous voulez vous protéger contre les bugs httpd aussi).

0 votes

Les threads ne peuvent effectuer que des transitions de 'limites de type', on ne peut pas passer à une autre confinement 'vraiment' donc ceci est tout à fait valide. Néanmoins -- même dans les circonstances décrites ci-dessus, un attaquant ne peut manipuler que Apache dans son confinement SELinux.

0 votes

@SergeyVlasov Merci pour l'avertissement. Le modèle de menace principal qui me préoccupe est quelqu'un exploitant des bogues dans une application PHP pour manipuler les données ou la configuration d'une autre. Les bogues dans PHP en eux-mêmes sont préoccupants, mais en équilibrant la difficulté de configuration par rapport à la protection, cette solution semble capable d'accomplir ce dont j'ai besoin.

2voto

Nicholas Tung Points 151

Je sais que cette question a 7 ans, cependant la réponse donnée par @MatthewIfe ci-dessus a été essentielle mais nécessitait quelques étapes supplémentaires. Nous utilisons CentOS8 qui ne comprend toujours pas mod_selinux par défaut, donc la réponse ci-dessus était parfaite pour l'installer.

Cependant, après l'installation et une configuration correcte, Apache échouait aux tests AVC et refusait de démarrer. Les erreurs disponibles dans les fichiers /var/log/httpd/error.log, /var/log/messages et /var/log/audit/audit.log n'étaient pas très utiles.

Finalement, j'ai dû installer deux utilitaires supplémentaires qui m'ont permis de résoudre les erreurs AVC de SELinux, ce qui indiquait que je devais créer une politique personnalisée pour permettre à le service httpd d'accéder à la commande setcurrent dans SELinux.

Vous pouvez trouver la solution ici: Apache vhost privilege separation using SELinux contexts on CentOS8

J'espère que cela aidera toute personne rencontrant le même problème.

1 votes

La politique a beaucoup évolué en 7 ans. Félicitations pour avoir mis à jour la réponse.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X