Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

comprendre le suid et le sgid : petit exemple

17 réponses
Avatar
Francois Lafont
Bonjour à tous,

J'essaye de comprendre les droits sur Linux et j'avoue avoir du mal à
bien comprendre le fonctionnement de suid et sgid. Voici mon exemple.

Dans toute la suite, le fichier exécutable touch.exe est un fichier issu
de la compilation du source en langage C suivant :

(je précise que j'ai bien vu sur le Web que cette manière de coder n'est
pas un exemple à suivre, mais ce n'est pas du tout l'objet de ce fil.
L'objet de ce fil c'est suid et sgid.)
//----------------------
#include <stdio.h>
#include <stdlib.h>

int main (void)
{
system("touch fichier.txt");
return 0;
}
//----------------------




J'ai un dossier d qui contient l'exécutable touch.exe :

#-----------------------------
# ls -l
drwxrwxr-x 2 sophie sophie 4096 2011-02-06 03:28 d


# ls -l d/
---------x 1 sophie sophie 7141 2011-02-06 03:28 touch.exe

# chmod u+s d/touch.exe

# ls -l d/
---S-----x 1 sophie sophie 7141 2011-02-06 03:28 touch.exe
#-----------------------------

Vous pouvez constater que seul l'utilisateur sophie ainsi que les
membres du groupe sophie peuvent créer des fichiers dans le dossier d.
De plus, le fichier touch.exe est exécutable pour "les autres" et le
suid est activé (mais pas le droit x pour l'utilisateur sophie).

Maintenant, j'ouvre un shell avec l'utilisateur francois qui ne fait pas
partie du groupe sophie (son groupe effectif s'appelle francois) :

#-----------------------------
$ cd d/

$ ./touch.exe

$ ls -l
-rw-r--r-- 1 sophie francois 0 2011-02-06 03:32 fichier.txt
---S-----x 1 sophie sophie 7141 2011-02-06 03:28 touch.exe
#-----------------------------

Q1) le fichier fichier.txt est bien créé car, avec le suid, tout se
passe comme si le programme avait été lancé par sophie. Pourquoi est-ce
que le groupe propriétaire de fichier.txt est francois ? J'aurais plutôt
parié pour que ce soit sophie (ce qui se serait passé si l'utilisateur
sophie avait lui-même exécuté le programme touch.exe).


Mais la suite me surprend encore plus.

Sous root, je supprime fichier.txt et je change les droits de touch.exe
comme ceci (suppression de suid et activation de sgid) :

#-----------------------------
# rm d/fichier.txt

# chmod u-s,g+s d/touch.exe

# ls -l d/
------S--x 1 sophie sophie 7141 2011-02-06 03:28 touch.exe
#-----------------------------

Ensuite, sous le compte francois, je tente d'exécuter touch.exe :

#-----------------------------
$ cd d/

$ ls -l
------S--x 1 sophie sophie 7141 2011-02-06 03:28 touch.exe

$ ./touch.exe
touch: impossible de faire un touch «fichier.txt»:
Permission non accordée
#-----------------------------

Q2) Pourquoi est-ce que francois n'a pas la permission de faire un touh
? Pour moi, à cause du sgid sur touch.exe, l'utilisateur francois
bénéficie des droits du groupe propriétaire du fichier touch.exe, à
savoir le groupe sophie et donc il devrait pouvoir créer un fichier dans
le dossier d, non ?

Je pense que la question suivante est liée à la précédente.

Q3) Si au lieu d'avoir '------S--x' dans les permissions de touch.exe
j'ai '------s--x' (c'est-à-dire qu'avec root j'ai fait chmod g+x
d/touch.exe), alors là francois peut exécuter touch.exe et il a bien les
permissions pour créer fichier.txt. Pourquoi ?

Je suis surpris de cette dissymétrie entre le suid et le sgid : en effet
avec '---S-----x' comme droits sur touch.exe (ou même avec
'---s-----x'), pas de souci dans l'exécution de touch.exe. Mais en
revanche, côté sgid, je n'ai pas le même comportement suivant que j'ai
les droits '------S--x' ou '------s--x' sur touch.exe.


J'espère avoir été clair.
Merci d'avance pour votre aide.


--
François Lafont

10 réponses

1 2
Avatar
Luc.Habert.00__arjf
Francois Lafont :

system("touch fichier.txt");



Attention, certains shells se débarrassent de droits obtenus via des bits s.
Il vaudrait mieux un open("fichier.txt", O_CREAT, 666).

Q1) le fichier fichier.txt est bien créé car, avec le suid, tout se
passe comme si le programme avait été lancé par sophie. Pourquoi est-ce
que le groupe propriétaire de fichier.txt est francois ?



Les groupes sont orthogonaux aux utilisateurs. Le seul lien entre le groupe
sophie et l'utilisateur sophie est qu'au login, si on se logue en tant que
sophie, on se fait attribuer le groupe sophie, mais c'est juste parce que
c'est marqué dans /etc/passwd, ce n'est pas un lien intangible.

Q2) Pourquoi est-ce que francois n'a pas la permission de faire un touh
? Pour moi, à cause du sgid sur touch.exe, l'utilisateur francois
bénéficie des droits du groupe propriétaire du fichier touch.exe, à
savoir le groupe sophie et donc il devrait pouvoir créer un fichier dans
le dossier d, non ?



goto premier paragraphe
(Je ne sais pas si c'est le problème, mais c'est la première chose à faire
pour clarifier la situation.)
Avatar
Benoit Izac
Bonjour,

le 06/02/2011 à 04:23, Francois Lafont a écrit dans le message
<4d4e1420$0$31862$ :

$ ls -l
-rw-r--r-- 1 sophie francois 0 2011-02-06 03:32 fichier.txt
---S-----x 1 sophie sophie 7141 2011-02-06 03:28 touch.exe
#-----------------------------

Q1) le fichier fichier.txt est bien créé car, avec le suid, tout se
passe comme si le programme avait été lancé par sophie. Pourquoi est-ce
que le groupe propriétaire de fichier.txt est francois ? J'aurais plutôt
parié pour que ce soit sophie (ce qui se serait passé si l'utilisateur
sophie avait lui-même exécuté le programme touch.exe).



Parce que le groupe effectif n'a pas changé. Tu peux essayé ce programme
pour voir les appartenances réelles et effectives :

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

int main(void)
{
const char *filename = "test.txt";
FILE *fp;
struct stat s;

printf("uid: %5d, gid: %5dn", getuid(), getgid());
printf("euid: %5d, egid: %5dn", geteuid(), getegid());

fp = fopen(filename, "w");
if (fp == NULL) {
perror("fopen");
exit(1);
}

if (stat(filename, &s) == -1) {
perror("stat");
exit(2);
}
printf("%s uid: %5d, gid: %5d, mode: %on",
filename, s.st_uid, s.st_gid, s.st_mode);

fclose(fp);
unlink(filename);
return 0;
}

Q2) Pourquoi est-ce que francois n'a pas la permission de faire un touh
? Pour moi, à cause du sgid sur touch.exe, l'utilisateur francois
bénéficie des droits du groupe propriétaire du fichier touch.exe, à
savoir le groupe sophie et donc il devrait pouvoir créer un fichier dans
le dossier d, non ?

Je pense que la question suivante est liée à la précédente.

Q3) Si au lieu d'avoir '------S--x' dans les permissions de touch.exe
j'ai '------s--x' (c'est-à-dire qu'avec root j'ai fait chmod g+x
d/touch.exe), alors là francois peut exécuter touch.exe et il a bien les
permissions pour créer fichier.txt. Pourquoi ?



C'est du au fait qu'avoir le bit S_ISGIG a 1 et le bit S_IXGRP a 0 permet
de faire du "mandatory locking".

C'est expliqué dans chmod(2) :
| S_ISGID (02000) set-group-ID (set process effective group ID on
| execve(2); mandatory locking, as described in
| fcntl(2); take a new file's group from parent direc‐
| tory, as described in chown(2) and mkdir(2))

et dans fnctl(2) :
| To make use of mandatory locks, mandatory locking must be enabled both
| on the file system that contains the file to be locked, and on the file
| itself. Mandatory locking is enabled on a file system using the "-o
| mand" option to mount(8), or the MS_MANDLOCK flag for mount(2). Manda‐
| tory locking is enabled on a file by disabling group execute permission
| on the file and enabling the set-group-ID permission bit (see chmod(1)
| and chmod(2)).

--
Benoit Izac
Avatar
Francois Lafont
Le 06/02/2011 12:03, Luc Habert a écrit :

Les groupes sont orthogonaux aux utilisateurs. Le seul lien entre le groupe
sophie et l'utilisateur sophie est qu'au login, si on se logue en tant que
sophie, on se fait attribuer le groupe sophie, mais c'est juste parce que
c'est marqué dans /etc/passwd, ce n'est pas un lien intangible.



Ok, mais justement à ce propos, je me suis souvent demandé ce qui
rendait particulier le groupe primaire d'un utilisateur ? Je m'explique.

Un utilisateur peut appartenir à plusieurs groupes (c'est le cas de
l'utilisateur francois sur mon système). Le groupe primaire est celui
qui apparaît dans /etc/passwd. Mais à part ça, c'est quoi sa
particularité ? Par exemple, si je change le groupe primaire
(personnellement, j'avais bêtement édité /etc/passwd et je m'étais
reconnecté au système), l'utilisateur a les mêmes droits. J'avais
l'impression qu'au niveau des droits le groupe primaire ne joue pas de
rôle particulier (si un fichier f a pour groupe propriétaire G, j'ai les
mêmes droits sur f que G soit mon groupe primaire ou non, me semble-t-il).

En fait, la *seule* chose que j'ai pu constater et qui rend le groupe
primaire particulier, c'est au niveau de la création des fichiers, où le
groupe propriétaire du fichier est toujours le groupe primaire du
créateur au départ.



--
François Lafont
Avatar
Benoit Izac
Bonjour,

le 06/02/2011 à 18:20, Francois Lafont a écrit dans le message
<4d4ed859$0$20786$ :

En fait, la *seule* chose que j'ai pu constater et qui rend le groupe
primaire particulier, c'est au niveau de la création des fichiers, où le
groupe propriétaire du fichier est toujours le groupe primaire du
créateur au départ.



Pas toujours vrai : si le répertoire dans lequel tu souhaites créer un
fichier a le bit set-group-ID (S_ISGID), ton fichier appartiendra au
même groupe que le répertoire.

--
Benoit Izac
Avatar
Francois Lafont
Le 06/02/2011 13:14, Benoit Izac a écrit :

Q1) le fichier fichier.txt est bien créé car, avec le suid, tout se
passe comme si le programme avait été lancé par sophie. Pourquoi est-ce
que le groupe propriétaire de fichier.txt est francois ? J'aurais plutôt
parié pour que ce soit sophie (ce qui se serait passé si l'utilisateur
sophie avait lui-même exécuté le programme touch.exe).



Parce que le groupe effectif n'a pas changé.



Ok, alors après quelques recherches sur le Web, si j'ai bien compris un
processus possède (entre autres) :

- un UID qui est l'id réel de l'utilisateur qui a lancé le processus
- un EUID qui l'id effectif du processus (c'est lui qui conditionne les
droits d'accès)

Sachant qu'en général UID == EUID, sauf si le prog exécutable
responsable du processus avait le suid activé où dans ce cas le EUID est
l'identifiant du propriétaire de l'exécutable. C'est bien cela ?

Et on a la même chose, si j'ai bien compris, avec le GID et le EGID d'un
processus. Et dans mon test de la question Q1, c'est seulement le EUID
qui a changé mais le GUID est resté égal à celui de l'utilisateur francois.

Mais il y a une chose que je n'arrive pas trop à comprendre. Sur mon
système (Ubuntu 10.04), *au niveau des groupes*, les droits d'accès ne
dépendent pas seulement du groupe primaire de l'utilisateur mais de
l'ensemble des groupes auxquels il appartient. Or dans dans un
processus, seul le groupe primaire est stocké. Comment le processus fait
pour savoir qu'en tant que membre du groupe toto (par exemple) j'ai le
droit de lire tel fichier si toto n'est pas mon groupe primaire ?

Tu peux essayé ce programme
pour voir les appartenances réelles et effectives : [snip]



Parfait, merci bien, ça sera pour moi instructif. Je n'y connais rien en
C, mais en lisant le programme, je crois comprendre qu'il crée un
fichier fichier.txt dans le répertoire courant. Or, pourtant, même en
effectuant le programme sous root, aucun fichier n'est créé, est-ce normal ?

C'est du au fait qu'avoir le bit S_ISGIG a 1 et le bit S_IXGRP a 0 permet
de faire du "mandatory locking".



Clairement, vu les citations, il est évident que tu as montré du doigt
la réponse à la question, merci.

et dans fcntl(2) :
| To make use of mandatory locks, mandatory locking must be enabled both
| on the file system that contains the file to be locked, and on the file
| itself. Mandatory locking is enabled on a file system using the "-o
| mand" option to mount(8), or the MS_MANDLOCK flag for mount(2).



Je fais mes tests dans le /home en général et pourtant dans le montage
de /home il n'y a pas d'option qui pourrait ressembler à ce qui est
écrit ci-dessus ?

$ mount | grep '/home '
/dev/sdb1 on /home type ext3 (rw,relatime)

Par ailleurs, j'ai bien tenté de lire fcntl(2), notamment avant ce que
tu cites, et j'ai compris comment on activait le "mandatory locking" sur
un fichier (exactement en faisant ce que j'ai fait sur le test de la
question Q2), mais je ne comprends pas :

a) ce que fait exactement le "mandatory locking"
b) et a fortiori à quoi ça sert

Je tente une réponse pour a) seulement :

a) il désactive l'effet du sgid si le droit x pour le groupe est à 0 (en
fait, ça c'est ce que j'ai pu constater avec mon test, mais à lire la
page man, c'est bien plus compliqué que ça).



--
François Lafont
Avatar
Luc.Habert.00__arjf
Francois Lafont :

En fait, la *seule* chose que j'ai pu constater et qui rend le groupe
primaire particulier, c'est au niveau de la création des fichiers, où le
groupe propriétaire du fichier est toujours le groupe primaire du
créateur au départ.



C'est ça.
Avatar
Benoit Izac
Bonjour,

le 06/02/2011 à 18:49, Francois Lafont a écrit dans le message
<4d4edf31$0$26423$ :

Sachant qu'en général UID == EUID, sauf si le prog exécutable
responsable du processus avait le suid activé où dans ce cas le EUID est
l'identifiant du propriétaire de l'exécutable. C'est bien cela ?



Oui.

Et on a la même chose, si j'ai bien compris, avec le GID et le EGID d'un
processus. Et dans mon test de la question Q1, c'est seulement le EUID
qui a changé mais le GUID est resté égal à celui de l'utilisateur francois.

Mais il y a une chose que je n'arrive pas trop à comprendre. Sur mon
système (Ubuntu 10.04), *au niveau des groupes*, les droits d'accès ne
dépendent pas seulement du groupe primaire de l'utilisateur mais de
l'ensemble des groupes auxquels il appartient. Or dans dans un
processus, seul le groupe primaire est stocké. Comment le processus fait
pour savoir qu'en tant que membre du groupe toto (par exemple) j'ai le
droit de lire tel fichier si toto n'est pas mon groupe primaire ?



C'est via /etc/group. Tu peux taper la commande « id » pour avoir une
idée précise de ton uid, ton gid et les groupes auxquels tu appartiens.

Tu peux essayé ce programme
pour voir les appartenances réelles et effectives : [snip]



Parfait, merci bien, ça sera pour moi instructif. Je n'y connais rien en
C, mais en lisant le programme, je crois comprendre qu'il crée un
fichier fichier.txt dans le répertoire courant. Or, pourtant, même en
effectuant le programme sous root, aucun fichier n'est créé, est-ce normal ?



Oui. ;-)

En fait j'aurais du ajouter un commentaire : tu as la fonction unlink(2)
qui fait le ménage à la fin ; tu peux la commenter/supprimer si tu
souhaites conserver le fichier.

a) ce que fait exactement le "mandatory locking"
b) et a fortiori à quoi ça sert



Le locking, c'est un méthode pour empêcher que plusieurs processus
accèdent au même fichier en même temps (lock = verrouiller).

Imagine par exemple un fichier de log avec un programme qui a plusieurs
instances : il serait fâcheux que le processus A commence à écrire
quelque chose et que quelques instants plus tard, alors que A n'a pas
fini d'écrire, un autre processus B écrive aussi. Tu te retrouverais
avec un fichier de log incompréhensible car tout mélangé.

Après, le mandatory locking tel que défini dans fcntl(2) est quelque
chose que je ne maîtrise pas ; je ne m'aventurerai donc pas dans sa
description.

--
Benoit Izac
Avatar
Nicolas George
Francois Lafont , dans le message
<4d4edf31$0$26423$, a écrit :
Or dans dans un
processus, seul le groupe primaire est stocké.



Qu'est-ce qui te fait dire ça ?

Comment le processus fait
pour savoir qu'en tant que membre du groupe toto (par exemple) j'ai le
droit de lire tel fichier si toto n'est pas mon groupe primaire ?



Ce n'est pas le processus qui le sait, c'est le noyau.
Avatar
Francois Lafont
Le 06/02/2011 20:03, Nicolas George a écrit :

Or dans dans un
processus, seul le groupe primaire est stocké.



Qu'est-ce qui te fait dire ça ?



Et bien, peu de chose à vrai dire. En essayant de glaner des infos sur
le Web, je suis tombé sur cette page :

http://tldp.org/HOWTO/Secure-Programs-HOWTO/processes.html

Et je vois qu'il y a comme attribut le GID et le EGID, mais pas un truc
qui ressemblerait à la liste des GID de tous les groupes auquel
l'utilisateur (ayant lancé le processus) appartient.

Mais dans l'absolu, je ne suis sûr de rien. J'essaye juste de comprendre
un petit peu.


Comment le processus fait
pour savoir qu'en tant que membre du groupe toto (par exemple) j'ai le
droit de lire tel fichier si toto n'est pas mon groupe primaire ?



Ce n'est pas le processus qui le sait, c'est le noyau.



Ok, merci pour la précision.


--
François Lafont
Avatar
Nicolas George
Francois Lafont , dans le message
<4d4ef481$0$23921$, a écrit :
le noyau ira consulter le
fichier /etc/group pour voir si l'utilisateur est membre ou non du
groupe G. C'est bien cela ?



Non, pas du tout. D'une manière générale, le noyau ne va presque jamais lire
de lui-même des fichiers, et jamais des fichiers texte qu'il faudrait
interpréter.
1 2