Comment empêcher chgrp d'effacer le "bit setuid"?

8

Nous avons des images Linux basées sur RH; sur lequel je dois "appliquer" certaines "archives spéciales" afin de les mettre à niveau vers la dernière version de développement de notre produit.

La personne qui a créé l'archive a pensé que dans notre image de base, certaines autorisations étaient incorrectes; donc on nous a dit de courir

sudo chgrp -R nobody /whatever

Nous l'avons fait; et plus tard, lorsque notre application est en cours d'exécution, des problèmes obscurs sont survenus.

Ce que je trouve plus tard: l'appel à chgrp va effacer les informations bit setuid sur nos binaires dans les / whatever.

Et le problème réel est: certains de nos binaires doivent avoir ce bit setuid pour fonctionner correctement.

Pour faire court: existe-t-il un moyen d'exécuter cette commande "chgrp" sans tuer mes bits setuid?

Je viens de lancer ce qui suit sur mon Ubuntu local; conduisant au même résultat:

mkdir sticky
cd sticky/
touch blub
chmod 4755 blub 
ls -al blub 

-> me montre le nom du fichier avec un fond rouge -> oui, oui, setuid

chgrp -R myuser .
ls -al blub 

-> me montre le nom du fichier sans fond rouge -> setuid a disparu

GhostCat
la source
1
Le 4XXXbit est appelé bit setuid ( s), pas collant. Sticky est le tbit et son but est un peu différent: en.wikipedia.org/wiki/Sticky_bit
zuazo
2
(1) Vous définissez le setuidbit, pas le stickybit. (2) Ne pas effacer le setuidbit lorsque vous le faites chgrpou chownserait un problème de sécurité.
Satō Katsura
1
Ce comportement change entre les distributions. Mais comme expliqué ici , le changement du bit setuid dépend du comportement sous-jacent de syscall.
zuazo
Merci à tous. Vous avez raison, il s'agit du bit setuid! Merci de votre aide. Et j'accepte également que cela "fonctionne comme prévu". Maintenant, j'ai juste besoin de trouver la manière la plus sensée de faire ce qui doit être fait sans tuer ces bits. J'envisage d'utiliser gefacl pour créer un vidage de texte, retravailler la config de texte puis l'appliquer. Cela devrait me donner un contrôle total sur ce qui va se passer.
GhostCat

Réponses:

7

Si vous souhaitez implémenter votre chgrp -R nobody /whatevertout en conservant le bit setuid, vous pouvez utiliser ces deux findcommandes

find /whatever ! -type l -perm -04000 -exec chgrp nobody {} + \
                                      -exec chmod u+s {} +
find /whatever ! -type l ! -perm -04000 -exec chgrp nobody {} +

L' find ... -perm 04000option récupère les fichiers avec le bit setuid défini. La première commande applique ensuite le chgrppuis un chmodpour rétablir le bit setuid qui a été supprimé. Le second s'applique chgrpà tous les fichiers qui n'ont pas de bit setuid.

Dans tous les cas, vous ne voulez pas appeler chgrpou chmodsur des liens symboliques car cela affecterait leurs cibles à la place, d'où le ! -type l.

roaima
la source
Notez que cela chgrpefface également le bit setgid (et les capacités sous Linux) qui pourraient également avoir besoin d'être restaurés.
Stéphane Chazelas
@ StéphaneChazelas vous avez raison, mais comme personne n'a mentionné setgid, je ne m'inquiétais pas de fournir une solution. La solution est trivialement extensible, cependant, avec un troisièmefind
roaima
Et bien ça ne peut pas être une 3ème trouvaille, il faudrait couvrir les cas u + g, u seul, g seul. Dans tous les cas, vous devriez pouvoir le faire en une seule fois find. Je n'aime pas les longues lignes en SE lorsque vous devez faire défiler le texte. Mon ajout du! -type l a fait passer le cap
Stéphane Chazelas
Eh bien, la seule findapproche avec -exec +peut être difficile à faire de manière fiable si cela finit par diviser le chmod/ chgrps en plusieurs invocations.
Stéphane Chazelas
1
En fait, je pense que ça find . ! -type l -exec chgrp nobody {} + \( -perms -6000 -exec chmod gu+s {} + -o -perms -4000 -exec chmod u+s {} + -o -perms -2000 -exec chmod g+s {} + \)devrait aller. Parce que les chgrpcorrespondances pour plus de fichiers, pour chaque fichier, il doit être fait avant le chmods.
Stéphane Chazelas
5

La suppression des bits SUID et SGID sur chgrp(ou chown) est parfaitement raisonnable. Il s'agit d'une mesure de sécurité afin d'éviter les problèmes de sécurité. Pour SGID (sur les exécutables, je suppose) signifie exécuter ce programme avec le groupe effectif du propriétaire du groupe .

Si vous changez le propriétaire du groupe, en termes de sécurité et de contrôle d'accès, c'est quelque chose de complètement différent, c'est-à-dire qu'au lieu de s'exécuter avec un groupe efficace, uvwle programme s'exécute maintenant avec un groupe efficace xyz.

Ainsi, vous devez restaurer le bit SUID ou SGID explicitement lors du changement de propriétaire.

Addendum: sur l'affirmation selon laquelle chgrp (ou chown) ne devrait effacer que SGID (ou SUID, resp.)

En changeant chownou chgrpen modifiant le paramètre de sécurité d'un exécutable, c'est une raison suffisante pour effacer tout attribut d'élévation de privilèges. La puissance d'Unix vient de la simplicité conceptuelle, et la sécurité Unix est déjà assez délicate. À cette fin, la suppression de SUID et SGID sur tout changement de propriétaire est simplement un filet de sécurité - après tout, dans l'histoire d'Unix / Linux, il y avait pas mal de vulnérabilités en raison de paramètres SUID ou SGID malavisés.

Il n'y a donc aucune raison plus profonde pour laquelle Unix se comporte de cette façon, c'est juste une décision de conception conservatrice.

contre-mode
la source
1
Cela explique parfaitement pourquoi le changement de propriétaire efface le bit SUID et le changement de groupe efface le bit SGID. Mais la question concerne le bit SUID lors d'une opération de changement de groupe qui n'affecte pas l'utilisateur sous lequel s'exécute SUID. Il doit donc y avoir une explication différente.
Ben Voigt
1
@BenVoigt: ça explique assez bien. Chown et chgrp appellent le chown () syscall, qui efface suid et sgid sur les fichiers normaux quoi qu'il arrive.
Joshua
1
@Joshua: C'est une description. L'explication est "pour éviter le cas où au lieu de s'exécuter avec un groupe efficace, uvwle programme s'exécuterait maintenant avec un groupe efficace xyz", mais cela ne s'applique pas au cas en discussion.
Ben Voigt
Cela fait. En modifiant chownou chgrpen modifiant le paramètre de sécurité, c'est une raison suffisante pour effacer les attributs d'élévation de privilèges. Il y a de fortes chances que cela frappe autrement les imprudents.
contre-mode du
4

La compensation du setuid, setgidbit (au moins sous Linux) sur les non-répertoires se fait par le noyau lors de l' chown()appel système fait par chgrp, non pas par chgrplui - même. Le seul moyen est donc de le restaurer par la suite.

Il efface également les capacités de sécurité.

Donc, sur GNU Linux:

chown_preserve_sec() (
  newowner=${1?}; shift
  for file do
    perms=$(stat -Lc %a -- "$file") || continue
    cap=$(getfattr -m '^security\.capability$' --dump -- "$file") || continue
    chown -- "$newowner" "$file" || continue
    [ -z "$cap" ] || printf '%s\n' "$cap" | setfattr --restore=-
    chmod -- "$perms" "$file"
  done
)

Et exécutez (as root):

chown_preseve_sec :newgroup file1 file2...

pour changer le groupe tout en essayant de conserver les autorisations.

Récursivement, vous pourriez faire:

# save permissions (and ACLs). Remove the "# owner" and "# group" lines
# to prevent them being restored!
perms=$(getfacl -RPn . | grep -vE '^# (owner|group): ')
# save capabilities
cap=$(getfattr -Rhm '^security\.capability$' --dump .)

chgrp -RP nobody .

# restore permissions, ACLs and capabilities
printf '%s\n' "$perms" | setfacl --restore=-
[ -z  "$cap" ] || printf '%s\n' "$cap" | setfattr -h --restore=-

(c'est tout en supposant que rien ne gâche autrement les fichiers en même temps).

Stéphane Chazelas
la source
1

Comme d'habitude dans l'administration, il y a plusieurs façons de procéder.

La solution que j'ai mise en place se présente comme suit:

cd /home/me
getfacl -R /whatever > whatever-permissions.org 2> /dev/null

# A) change lines starting with      # group: root
# to                                 # group: whatineed
sed 's/^# group: root/# group: whatineed/g' whatever-permissions.org > whatever-permissions.new

# B) change lines with               group::x.y
# to                                 group::xwy
# (where x, y mean: whatever was there before)
sed 's/^group::\(.\).\(.\)/group::\1w\2/g' whatever-permissions.new > whatever-permissions.new

cd /
setfacl --restore /home/me/whatever-permissions.new
GhostCat
la source