Ticket #251 (new defect)

Opened 4 years ago

Last modified 2 years ago

séparation des domaines avec SuExecPhp

Reported by: anarcat Assigned to: anarcat
Priority: normal Milestone: alternc-2.0
Component: Bureau: domaines Version:
Severity: feature Keywords:
Cc:

Description (Last modified by anarcat)

Une solution élégante aux multiples problèmes de permissions (bug 145, par exemple) serait d'utiliser SuExecPhp? et d'avoir des véritables utilisateurs. Ceci ouvrirait un problème de sécurité, certes, mais en fermerait un autre, et permetterait des choses très intéressantes.

ADDITIONAL INFORMATION: Idéalement, cette patch serait couplé au bug 191. Les groupes UNIX serait alors des utilisateurs PHP, et les scripts rouleraient comme ce groupe. On aurait donc les fichiers:

-rw-r----- alternc:www-data fichier1 -rw-rw---- alternc:user1 fichier2

Le fichier1 serait lisible par le webserver, mais pas inscriptible. Le fichier2 lui, serait inscriptible par le webserver, mais seulement pour les domaines hébergés par l'usager AlternC user1.

L'usager UNIX "alternc" pourrait être utilisé pour le FTP ou les autres accès.

Change History

05/05/05 16:44:45 changed by arnaud_lb

J'ai commencé à regarder un peu comment ça pourais etre mis en place.

Ta solution serait en fait parfaite, mais il y a un problème:

Tous les fichiers appartiennent à alternc. Donc un hébergé peut lire les fichiers de son voisin. Si on enlève à alternc le droit de lire un fichier, il ne poura pas le lire, meme si le process tourne sous le meme gid que le fichier ou que le fichier est lisible par tout le monde. Donc un hébergé ne peut pas rendre un fichier non lisible par les autres sans le rendre non lisible pour lui meme. Par contre l'inverse ne marche pas, c'est à dire que si on enlève le droit de lire au groupe d'un fichier, le propriétaire du fichier poura le lire meme si le process tourne sous le meme groupe que le fichier.

Mon explication n'est pas des plus claire.. Un exemple: Dans l'exemple on dit que alternc à l'uid 200.

# ls -l -rw-r--r-- 1 alternc 2001 0 YYYY-MM-DD file2001 -rw-r--r-- 1 alternc 2002 0 YYYY-MM-DD file2002

# #Le groupe 2001 peu lire ses propres fichiers # php -r 'posix_setgid(2001);posix_setuid(200);var_dump(fopen("file2001", "r"));' resource(4) of type (stream)

# #Le groupe 2001 peu lire aussi les fichiers du voisin # php -r 'posix_setgid(2001);posix_setuid(200);var_dump(fopen("file2002", "r"));' resource(4) of type (stream)

# #Le groupe 2002 se protège # chmod u-rw file2002 # ls -l -rw-r--r-- 1 alternc 2001 0 YYYY-MM-DD file2001


# #Le groupe 2001 ne peu plus lire le fichier du voisin # php -r 'posix_setgid(2001);posix_setuid(200);var_dump(fopen("file2002", "r"));' Warning: fopen(file2002): failed to open stream: Permission denied in Command line code on line 1 bool(false)

# #Le groupe 2002 non plus # php -r 'posix_setgid(2002);posix_setuid(200);var_dump(fopen("file2002", "r"));' Warning: fopen(file2002): failed to open stream: Permission denied in Command line code on line 1 bool(false)

# #Le groupe 2002 peut lire le fichier si le process ne tourne pas sous l'uid d'alternc # php -r 'posix_setgid(2002);posix_setuid(33);var_dump(fopen("file2002", "r"));' resource(4) of type (stream)

Donc j'ai regardé la solution "donner un uid à chaque membre plutot qu'un gid"

Au niveau configuration, ça ne fait pas énormément de changements. La plupart du temps il suffit d'inverser gid/uid. Pour postfix, il suffit de modifier un peu main.cf et mygid.cf Pour courier, courier/authmysqlrc Pour le FTP, une ligne à modifier dans proftpd.conf Dans /src, il faut modifier mem_add.c (un chmod), quota_edit.sh et quota_get.sh (remplacer -g par -u), mail_add.c (quelques chmod)

Voir le script d'upgrade plus bas.

A ce niveau, alternc doit fonctionner à peu pret correctement avec suPHP.

Le problème va venir des scripts qui écrivent ou lisent dans le home des hébergés et qui ne tournent pas en root. Ces scripts doivent avoir des droits équivalents au membre sur ses propres fichiers pour pouvoir les lire ou en créer avec les meme uid/gid. Donc dans la liste de ce qui ne va plus marcher ou devra etre modifié, on a: le gestionnaire de fichier, les backup mysql, et les stats apache. (Et certainement d'autres trucs).

Un autre petit problème: Avec le VirtualDocumentRoot?, suPHP rale parce que les scripts ne sont pas dans le document root.

Et il reste quelques trucs à voir avant de virer open_basedir et safe_mode

Une esquisse de script d'upgrade qui met le gid à la place de l'uid dans les fichiers et les mails des membres, et les quotas. Le gid est remplacé par $WEBUSERS.

#!/bin/bash # Modification du propriétaire des fichiers des membres # Modification des quotas # Modification du propriétaire des mails

. /etc/alternc/local.sh WEBUSERS=200

for d in /var/alternc/html/*; do

for i in ls -l $d | awk /www-data/\ '{print $4"/"$8}'; do

o=echo "$i" | awk -F/ '{print $1}' h=echo "$i" | awk -F/ '{print $2}'

#Propriétaire des fichiers

cmd="chown -R $o.$WEBUSERS $d/$h" echo $cmd

# $cmd #Quotas

q=/usr/bin/quota -g $o | awk /${DATA_PART//\//\\\/}/\ {print\ '$3'} cmd="/usr/sbin/setquota -g $o 0 0 0 0 $DATA_PART" echo $cmd

# $cmd

cmd="/usr/sbin/setquota -u $o $q $q 0 0 $DATA_PART" echo $cmd

# $cmd

done

done

#Propriétaire des mails for d in /var/alternc/mail/*; do

for i in ls -l $d | awk /www-data/\ '{print $4"/"$8}'; do

o=echo "$i" | awk -F/ '{print $1}' h=echo "$i" | awk -F/ '{print $2}'

cmd="chown -R $o.$WEBUSERS $d/$h" echo $cmd

# $cmd

done

done EOF

modifié le : 05/05/05 16:38

05/05/05 20:17:22 changed by anarcat

C'est absolument fantastique ça! Je suis très heureux que quelqu'un reprenne l'idée là où je l'avais laissée!!

Faire des vrais usagers avec les membres alternc est évidemment la bonne solution, je ne vois pas pourquoi je n'y avais pas pensé plus tôt. Je crois que ceci règle tous les problèmes, même. Voyons voir les bobos que arnaud y voit:

""" Le problème va venir des scripts qui écrivent ou lisent dans le home des hébergés et qui ne tournent pas en root. Ces scripts doivent avoir des droits équivalents au membre sur ses propres fichiers pour pouvoir les lire ou en créer avec les meme uid/gid. """

Disons qu'un fichier "normal" (pas inscriptible par le webserver), va avoir les permissions suivantes:

-rw-rw-r-- 1 anarcat alternc 0 2005-05-05 11:43 foo

où "anarcat" est le nom d'usager. En fait, ça va probablement ressembler à ça à moins que l'on branche également nss_mysql:

-rw-rw-r-- 1 2001 alternc 0 2005-05-05 11:43 foo

Le webserver roule en:

User www-data Group www-data

comme d'habitude, et ne peut donc pas écrire ces fichiers. *Par contre*, le bureau lui, roule en:

User alternc Group alternc

et a donc accès aux fichiers!

Je ne vois aucun problème avec cette approche, si ce n'Est que les problèmes dont tu as parlé au sujet du conflit suexec <-> VirtualDocumentRoot?, qui sont très ennuyeux... Il faudrait effectivemnet détruire les openbasedir, et le safe_mode deviendra (ENFIN!) inutile, car les fichiers de conf seront lisible seulement par l'usager "alternc".

J'ai commité et commencé à travailler sur ton script dans le CVS. Tu veux un accès? :)

http://cvs.alternc.org/cgi-bin/viewcvs.cgi/alternc/install/scripts/upgrades/suexec.test?rev=1.4&view=log

A.

05/05/05 20:48:48 changed by arnaud_lb

Oui je veux bien un accès :)

05/06/05 14:27:11 changed by arnaud_lb

""" *Par contre*, le bureau lui, roule en:

User alternc Group alternc

et a donc accès aux fichiers! """

Si tous les fichiers des membres appartiennent au groupe alternc, le bureau poura les lire/écrire si le groupe est autorisé en lecture/écriture. Mais si le groupe est autorisé en lecture/écriture, ça veut dire que tous les autres hébergés peuvent aussi lire/écrire ces fichiers. Donc le bureau ne poura pas lire/écrire tous les fichiers. On devra aussi créer les fichiers avec les propriétaires user.alternc, et ça n'est pas possible avec un process qui tourne en alternc.altenrc. Et c'est pareil pour les backup SQL et les statistiques brutes.

05/06/05 15:20:30 changed by arnaud_lb

La solution à ce problème serait donc d'avoir un process qui tourne en root, puis qui fait un setgid/setuid dés que possible pour tourner sous l'uid de l'hébergé. On a besoin d'etre sous l'uid et gid de l'hébergé uniquement pour faire des opérations sur des fichiers, et uniquement dans son home. Le FTP fait exactement ça, pourquoi ne pas l'utiliser ?

Comme on est pas sur d'avoir un compte FTP à la racine du home de l'hébergé, on peut créer un compte temporaire qui donne sur le home de l'hébergé, avec son uid et le gid d'alternc. Après on fait les opérations dont on a besoin puis on détruit le compte FTP.

ça n'est pas la solution idéale, mais ça fait exactement ce dont on a besoin. Pour le bureau, je verrais bien une classe wrapper pour faire ça. Pour ouvrir le fichier d'un membre, ça donnerais par exemple: fopen('membre: //nom_du_membre@fichier_du_membre', 'r');

modifié le : 06/05/05 14:56

05/06/05 19:21:11 changed by anarcat

Houla... Tu me perds la:

""" Mais si le groupe est autorisé en lecture/écriture, ça veut dire que tous les autres hébergés peuvent aussi lire/écrire ces fichiers. Donc le bureau ne poura pas lire/écrire tous les fichiers. """

Les autres hébergés ne pourront pas lire écrire les autres fichiers, car:

""" Le webserver roule en:

User www-data Group www-data

"""

Donc pas de problème, non? C'est seulement le bureau qui va rouler en:

"""

User alternc Group alternc

"""

05/06/05 19:29:35 changed by arnaud_lb

En fait j'était parti sur l'idée que tout le monde allait tourner sous suPHP, justement pour séparer les domaines. suPHP fait tourner les scripts sous l'uid/gid du propriétaire/groupe du fichier. Donc les scripts de chaque domaine tournent sous un uid différent. A partir de là, il est possible de séparer les domaines rien qu'avec les permissions Unix, et donc sans safe_mode ou open_basedir.

05/06/05 19:47:21 changed by anarcat

en ayant tous les domaines qui roulent sous www-data:www-data et les fichiers USER:alternc, le webserver ne peut pas écrire nulle part, et donc les membres ne peuvent pas écrire par dessus les fichiers des autres...

ils peuvent lire, par contre. :(

05/06/05 20:40:45 changed by arnaud_lb

Donc on est plus ou moins obligé d'utiliser suPHP pour tout le monde si on veut se passer de safe_mode, non ?

05/16/05 19:54:41 changed by anarcat

Seulement si on veut empêcher de *lire* les autres fichiers...

Aussi: il a été décidé à meeting de mai que ceci ne ferait pas partie de la 1.0, car suphp demande l'exécution des PHP en mode "cgi", ce qui provoque un overhead trop grand pour les utilisations courantes. Toute recherche est bienvenue pour prouver que c'est faux ou trouver d'autres pistes de solutions.

05/17/05 20:43:28 changed by arnaud_lb

J'ai fait un petit argumentaire sur le Wiki, avec une solution intermediaire: http://www.alternc.org/wiki/suPHP

04/01/06 22:45:36 changed by anarcat

  • type set to defect.
  • description changed.
  • milestone set to 2.0.

04/02/06 00:51:01 changed by anarcat

  • owner changed from anonymous to anarcat.