Comment empêcher les utilisateurs sudo d'exécuter des commandes spécifiques?

29

J'ai une configuration réseau très sensible et je ne veux vraiment pas la gâcher. Mon réseau est composé d'un groupe d'utilisateurs qui ont le privilège sudo.

Je veux les empêcher de courir

service NetworkManager restart
service network restart

commandes.

Existe-t-il un moyen d'y parvenir?

shekhar
la source
Quelle distribution utilisez-vous? Les noms de service sont spécifiques à la distribution et je ne connais aucune distribution qui utilise les noms que vous y avez. Voulez-vous dire networkinget network-manager? Aussi, pourquoi vos utilisateurs y ont-ils sudoaccès? Ils ne devraient pas, sauf si vous voulez qu'ils aient des privilèges root complets.
terdon
@terdon Je l'ai résolu. Merci. Je ne peux pas le poster comme réponse parce que je suis un nouvel utilisateur
shekhar
Oui, vous pouvez le faire. J'aimerais également connaître la réponse que vous avez trouvée.
terdon
@terdon bien sûr, mais son dicton, je dois attendre 8 heures pour poster ma propre réponse parce que je n'ai même pas 10
points de
1
Ah, oui, désolé, vous devez en effet attendre. Je viens de voter, vous avez le représentant maintenant :)
terdon

Réponses:

47

L'utilisation de CmndAlias ALLne sera jamais sûre

Il y a 1000 façons de fonctionner service network restartsans faire sudo service network restart. Voici un exemple de ce qu'un utilisateur méchant pourrait essayer:

$ echo "service network restart" > /tmp/hax
$ chmod a+x /tmp/hax
$ sudo /tmp/hax

Si vous fournissez aux utilisateurs l' ALLalias de commande, puis essayez de créer une liste noire, ils pourront toujours trouver un moyen de la contourner. Blacklist bash, et ils utiliseront python. Liste noire python, et ils utiliseront Perl. Mettez Perl en liste noire et ils utiliseront PHP. Personne ne veut ça!

Si vous ne voulez vraiment pas que quelqu'un fasse quelque chose, vous devez faire comme Thomas le dit et créer une liste blanche des choses qu'il est autorisé à faire.


Configuration d'une liste blanche avec une exception

Un exemple de petite liste blanche avec exclusion peut être trouvé vers le bas de man sudoers:

 pete           HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root

The user pete is allowed to change anyone's password except for root on the HPPA
machines.  Note that this assumes passwd(1) does not take multiple user names
on the command line.

(En fait, cet exemple de la page de manuel n'est pas sûr et peut être exploité pour changer le mot de passe de root! Voir les commentaires ci-dessous pour savoir comment.)

Nous pouvons essayer d'adapter cela à votre cas, de proposer toutes les servicecommandes au groupe du personnel, mais d' exclure les service networkcommandes qui vous concernent:

%staff ALL =   /usr/sbin/service *,                            \
             ! /usr/sbin/service *network*,                    \
             ! /usr/sbin/service *NetworkManager*

(Le ALLdans cette position fait référence à Host_Alias, pas à Cmnd_Alias ​​- confus n'est-ce pas?)

L'utilisateur ne pourra pas exécuter sudo bashou sudo teeou sudo wgetou sudo /path/to/malicious_script. Vous pouvez ajouter à la liste blanche plus de commandes d'administration pour vos utilisateurs si vous faites attention. Soyez précis!

Remarque: J'ai ajouté l' *avant le mot networkci-dessus, juste au cas où un drapeau inoffensif serait ajouté à l' serviceoutil à l'avenir. Imaginons qu'un --verboseindicateur ait été ajouté à l'avenir, les utilisateurs pourront alors exécuter ce qui suit:

$ sudo service --verbose network restart

Nous avons donc besoin de *pour consommer tous les drapeaux avant le nom du service. Le seul inconvénient est que cela pourrait bloquer d'autres services qui ne gênent pas réellement les utilisateurs, par exemple un service appelé safe-networkou network-monitorserait également rejeté.


Autoriser les utilisateurs à modifier un fichier à l'aide des autorisations de groupe

Ci-dessous, vous trouverez différentes tentatives d'utilisation de rnanothrough sudopour permettre aux utilisateurs de modifier un ou plusieurs fichiers. Mais en réalité, ils sont plus complexes et plus dangereux qu'ils ne devraient l'être.

Une solution beaucoup plus simple et plus sûre consiste à modifier les autorisations de groupe sur les fichiers spécifiques pour lesquels vous souhaitez ouvrir les droits de modification. Voici quelques exemples:

### Give steve the ability to edit his nginx config:
$ chgrp steve /etc/nginx/sites-available/steves_dodgy_project
$ chmod g+rw /etc/nginx/sites-available/steves_dodgy_project

### Let all members of the staff group edit the group_website config:
$ chgrp staff /etc/nginx/sites-available/group_website
$ chmod g+rw /etc/nginx/sites-available/group_website

Si vous avez besoin d'un contrôle plus précis (par exemple: accès pour seulement 3 utilisateurs, mais pas pour tous les membres du personnel), vous pouvez créer un nouveau groupe à l'aide de la addgroupcommande et y ajouter seulement quelques utilisateurs.


Permettre aux utilisateurs de modifier un fichier via sudo

Le reste de cette réponse est devenu une enquête sur la facilité avec laquelle il est possible de laisser des trous dans votre sudoconfiguration lorsque vous essayez d'offrir de la flexibilité à vos utilisateurs. Je ne recommanderais pas de faire l'une des choses suivantes!

Si vous souhaitez autoriser vos utilisateurs à modifier un fichier spécifique, vous pouvez essayer d'utiliser rnano:

%staff ALL = /bin/rnano /etc/nginx/sites-available/host

rnanone leur permettra que de modifier le fichier spécifié. Cela est important pour empêcher un utilisateur malveillant de modifier un service différent (par exemple /etc/init.d/urandom) et d'y ajouter une ligne qui s'exécuterait service network restart.

Malheureusement, je n'ai pas trouvé de moyen de restreindre rvimsuffisamment (l'utilisateur peut toujours ouvrir n'importe quel fichier en utilisant :e), nous sommes donc coincés avec nano.

Malheureusement, permettre aux utilisateurs de modifier plusieurs fichiers est beaucoup plus difficile ...


Laissez les utilisateurs éditer plusieurs fichiers (beaucoup plus difficile qu'il ne devrait l'être)

1. Approches dangereuses

Attention aux caractères génériques! Si vous offrez trop de flexibilité (ou toute flexibilité), elle peut être exploitée:

%staff ALL = /bin/rnano /etc/nginx/sites-available/*                # UNSAFE!

Dans ce cas, un utilisateur malveillant pourrait modifier tout autre script de service parvenu, puis l'exécuter:

$ sudo rnano /etc/nginx/sites-available/../../../any/file/on/the/system

(Sudo empêche .et ..développe réellement la commande, mais malheureusement pas les arguments.)

J'espérais que quelque chose comme ça pourrait fonctionner, mais ce n'est toujours pas sûr:

%staff ALL = /bin/rnano /etc/nginx/sites-available/[A-Za-z0-9_-]*   # UNSAFE!

Étant donné sudoqu'actuellement ne propose que des modèles globaux , cela *correspondra à tout - ce n'est pas une expression régulière!

(Edit: J'ai envisagé si vous pouviez vous en sortir avec ce qui précède dans votre situation, car il n'y a pas de sous-dossiers en dessous sites-available. Nous avons demandé qu'un caractère soit mis en correspondance après le dossier, et /..devrait échouer après un nom de fichier. Cependant, ce n'est pas un solution réalisable, car rnanoaccepte plusieurs arguments. Et en général, cela ne serait pas sûr sur un dossier qui avait des sous-dossiers!)

Même si nous n'avons pas de sous-dossiers, et que nous excluons toutes les lignes contenant /../, la règle offrant un *glob pourrait toujours être exploitée, car rnanoaccepte plusieurs arguments (en les parcourant <C-X>, et l'espace est heureusement accepté par le *glob.

$ rnano /etc/nginx/sites-available/legal_file /then/any/file/on/the/system

2. Pousser l'enveloppe (également finalement dangereux)

Et si nous rejetons toutes les lignes contenant des espaces ou essayons d'atteindre /..? Ensuite, une solution finale réalisable pourrait être la suivante:

# I tried hard to make this safe, but in the end I failed again.
# Please don't use this unless you are really smart or really stupid.

%staff ALL =   /bin/rnano /etc/nginx/sites-available/*,    \
             ! /bin/rnano */..*,                           \
             ! /bin/rnano /etc/nginx/sites-available/,     \
             ! /bin/rnano */.,                             \
             ! /bin/rnano * *

# CONCLUSION: It is still NOT SAFE if there are any subfolders, due to
# the bug in rnano described below.

Nous acceptons tout ce qui est "sous" le dossier mais nous rejetons également tout appel à rnanosi /..ou /.ou sont passés, ou si le dossier est ciblé directement. (Techniquement, l' /.exclusion rend l' /..exclusion redondante, mais j'ai laissé les deux pour plus de clarté.)

J'ai trouvé le dossier et les /.exclusions étaient nécessaires car sinon l'utilisateur pourrait cibler le dossier lui-même. Maintenant, vous pourriez penser rnanoque bloquerait si pointé vers un dossier, mais vous auriez tort. En fait, ma version (2.2.6-1ubuntu1) démarre avec un léger avertissement et un fichier vide, puis <C-X>me demande d'entrer le nom de fichier dans lequel je souhaite enregistrer, ouvrant un nouveau vecteur d'attaque! Eh bien, au moins, il a refusé d'écraser un fichier existant (dans le seul test que j'ai fait). Quoi qu'il en soit, puisqu'il n'y a aucun moyen de mettre les sous-dossiers sur liste noire avec sudo, nous devons conclure que cette approche est à nouveau dangereuse. Désolé les utilisateurs!

Cette découverte m'a fait douter de la rigueur du nanomode "restreint" de. Ils disent qu'une chaîne n'est aussi forte que son maillon le plus faible. Je commence à ressentir la combinaison de la sudoliste noire de la magie noire et je ne suis rnanopeut-être pas plus sûr qu'une chaîne de marguerites.

3. Approches sûres mais limitées

Les globes sont très restreints - ils ne nous permettent pas de faire correspondre plusieurs fois une classe de personnage. Vous pouvez proposer plusieurs modifications de fichiers si tous vos noms de fichiers ont la même longueur (dans ce cas, hostsuivis d'un seul chiffre):

%staff ALL = /bin/rnano /etc/nginx/sites-available/host[0-9]       # SAFE

Mais si vous souhaitez autoriser l'utilisateur à modifier divers fichiers, vous devrez peut-être spécifier explicitement chaque fichier:

%staff ALL = /bin/rnano /etc/nginx/sites-available/hothost    \
             /bin/rnano /etc/nginx/sites-available/coldhost   \    # SAFE
             /bin/rnano /etc/nginx/sites-available/wethost    \
             /bin/rnano /etc/nginx/sites-available/steves_dodgy_project

Ne soyez pas tenté d'utiliser un*à tout moment. Voir les sections 1. et 2. ci-dessus pour savoir pourquoi! N'oubliez pas: une petite fiche peut compromettre l'ensemble du compte superutilisateur et l'ensemble du système.

4. Écrivez votre propre vérificateur d'arguments (la sécurité est maintenant de votre responsabilité)

J'espère qu'ils ajouteront un support regexp à sudol'avenir; il pourrait résoudre de nombreux problèmes s'il est utilisé correctement. Mais nous pouvons également avoir besoin de la possibilité de vérifier les propriétés des arguments (pour autoriser uniquement les fichiers, uniquement les dossiers ou uniquement certains indicateurs).

Mais il existe une alternative pour créer de la flexibilité dans sudo. Passez la balle:

%staff ALL = /root/bin/staffedit *

Ensuite, écrivez votre propre staffeditscript ou exécutable pour vérifier si les arguments transmis par l'utilisateur sont légaux, et exécutez leur demande uniquement s'ils le sont.

joeytwiddle
la source
5
Cette réponse a pris beaucoup de temps, mais finalement je pense que je comprends comment fonctionne sudo. J'ai abandonné à plusieurs reprises dans le passé, trouvant ALL=(ALL:ALL) ALLtrop manquant de sémantique, mais j'ai toujours supposé quelque part qu'il aurait un vérificateur d'argument décent ... J'avais tort. C'est vraiment très limité. Même l'exclusion des racines passwd offert dans l'homme-page peut être rompu avec un argument de ligne de commande simple, sudo passwd -q root. Eh bien, les auteurs de sudo répertorient [quelques alternatives] (sudo.ws/sudo/other.html) sur leur site Web. J'espère qu'ils ajouteront le support regexp à l'avenir.
joeytwiddle
Utilisez-vous spécifiquement rnanodans votre description ici parce que c'est une version de nano qui n'a pas de fonction «enregistrer sous»? Je ne connais pas le programme.
Shadur
Oui. Si nous nous soucions de la sécurité, l'éditeur doit uniquement modifier celui fichier spécifié, et ne doit pas être en mesure d'ouvrir un shell. Pour info, $ man nanoalors/-R<Enter>
joeytwiddle
Correction: Pour briser l'exemple pete, le -qdoit venir après: sudo passwd root -q. L'exemple Pete peut être durci en excluant *root*.
joeytwiddle
Pensez à utiliser sudoeditpour activer en toute sécurité la modification de fichier avec sudo.
Totor
5

Tout d'abord, ouvrez le fichier sudoers avec sudo visudo. L'ajout de user ALL=!/usr/sbin/servicevolonté, IIRC, interdira la servicecommande pour l'utilisateur user.

Sources: http://nixcraft.com/showthread.php/15132-Sudo-Exclude-Commands-And-Disable-sudo-su-Bash-Shell

Zeb McCorkle
la source
Cela cessera également d'exécuter d'autres services et je n'en veux pas. Merci d'avoir répondu. :)
shekhar
alors que votre réponse ne m'a pas aidé exactement mais cela a aidé à trouver une solution merci. mais vous savez, soit pour vous donner un vote positif, soit pour poster ma réponse, je n'ai pas assez de réputation. Je vous remercierai sûrement une fois que je serai. Merci.
shekhar
2
Oui, mais comme d'autres l'ont dit, vous devez faire très attention à cela. Il existe de nombreuses façons d’y accéder. Toute commande pouvant générer un obus et ainsi de suite. C'est plus facile de comprendre de quelles commandes ils ont vraiment besoin et de les autoriser, au lieu d'essayer d'exclure toutes les commandes "interdites".
Bonsi Scott
3
Les listes blanches ne sont pas gérables dans de nombreux scénarios. Le véritable objectif n'est peut-être pas de les empêcher de faire quelque chose, mais plutôt de les empêcher de faire quelque chose de mal par erreur sans les restreindre autrement. Les listes noires sont bonnes dans ces cas. Vous mettez sur liste noire les façons dont un utilisateur raisonnable effectuerait la tâche. Mais la liste noire via sudo peut ne pas être suffisante - les gens peuvent utiliser et utilisent 'sudo bash'. Une approche consisterait à encapsuler la commande «service», et dans les cas où vous ne voulez pas qu'ils utilisent, informez-les. Mais vous ne répertorierez jamais toutes les bonnes actions dans une liste blanche, ni toutes les mauvaises dans une liste noire.
Bob Kerns
1
Je suis d'accord avec toi Bob. Pour permettre la flexibilité, sans autoriser un accès complet, vous devrez souvent déployer votre propre solution, en tant que script auxiliaire, et mettre en liste blanche uniquement ce script. Les listes blanches sudo peuvent faire ce dont vous avez besoin, mais souvent elles seront soit trop limitées, soit trop faciles à exploiter.
joeytwiddle
5

J'ai trouvé la solution.

J'ai ouvert le terminal et me transforme en utilisateur root avec su -puis j'ai tapé visudopour modifier.

puis à la fin j'ai écrit des lignes comme

user ALL=!/etc/init.d/NetworkManager restart
user ALL=!/etc/init.d/network restart

Ensuite, j'ai enregistré et fermé et redémarré aussi.

Maintenant, si je tape comme service network restartou service NetworkManager restartalors ce ne me permet pas et donne une erreur comme

Sorry user is not allowed to execute '/sbin/service NetowkrManager restart' as root on localhost.localdomain

et de même pour le service network restartcommandement également.

shekhar
la source
12
Cela fonctionnera pour les utilisateurs inexpérimentés et malfaisants, mais il est facile de contourner les restrictions sudo (par exemple sudo cp -p /etc/init.d/network /etc/init.d/network-not-in-sudo, puis sudo /etc/init.d/network-not-in-sudo restart). C'est pourquoi il est beaucoup plus sûr de créer des inclusions au lieu d'exclusions dans le fichier sudoers, par exemple indiquer avec quels services ils sont autorisés à interagir.
Thomas
Tout ce que fait le «redémarrage du réseau de service», vous pouvez le faire avec d'autres commandes, telles que celles du script network init.d. Je n'essaierai même pas de les énumérer ici. Mais si vous voulez, par exemple, empêcher réellement les modifications de l'état de l'interface, alors une politique SELinux me semble être la voie à suivre. C'est un sujet complexe, mais lorsqu'une liste blanche est trop restrictive ou trop contraignante et qu'une liste noire est inadéquate, c'est probablement votre meilleure option. Il est implémenté dans le noyau et vous permet de restreindre l'accès aux interfaces réseau (et autres ressources) même aux utilisateurs sudo'd.
Bob Kerns
Si c'est possible avec SELinux, ce serait plus agréable. @BobKerns Merci. Je vais essayer de cette façon.
shekhar
3

La vraie réponse à cela est que vous ne pouvez pas vraiment empêcher cela. Vous pouvez empêcher quelqu'un non malveillant d'exécuter accidentellement cette commande via les méthodes décrites dans les autres réponses, mais si quelqu'un veut vraiment l'exécuter et figure sur la liste des sudoers, il peut l'exécuter. Par exemple, ils pourraient faire ce qui suit:

joe@box:~$ sudo bash root@box:~# service network restart

Ou une autre commande amusante qu'ils pourraient utiliser pour contourner vos restrictions dans le fichier sudoers:

sudo visudo

En bref, si vous pouvez sudo et que cela ne se limite pas à l'exécution de commandes particulières, vous pouvez faire à peu près tout ce que vous voulez. Même si vous les limitez à un ensemble de commandes donné, vous devez vous assurer qu'il n'est pas possible pour l'utilisateur de copier une autre commande qu'il voulait exécuter sous le même nom que celle qu'il était autorisé à exécuter ( comme en écrasant la commande qu'ils ont l'autorisation d'exécuter.)

reirab
la source
Ouais. Il faut éviter les commandes qui peuvent engendrer un shell de l'intérieur.
Bonsi Scott
1
Le problème est que ce ne sont pas les commandes que vous souhaitez protéger, mais l'état des objets du noyau, tels que les tables de routage, les interfaces, etc., quelle que soit la commande (ou l'appel système) utilisée. Et vous voulez le protéger de certains, mais pas de tous, les utilisateurs root. SELinux est conçu autour de ce type de scénario. Mais d'abord, je commencerais par un examen des raisons pour lesquelles tous ces utilisateurs ont accès à sudo. S'ils ont seulement besoin de faire quelques choses spécifiques, les opérations de liste blanche dans les sudoers peuvent être tout ce dont vous avez besoin.
Bob Kerns
2

Utilisez Firejail pour restreindre les utilisateurs avec des bacs à sable.

https://github.com/netblue30/firejail/

Définissez firejail comme shell au lieu de bash dans / etc / passwd, pour chaque utilisateur que vous souhaitez restreindre. Il est très facile à utiliser et possède une bonne documentation.

Exemple:

user:x:1000:1000:user:/home/user:/usr/bin/firejail
Jeff
la source