Hello hello ! Cette semaine on continue sur notre lancée de la semaine dernière et on va voir comment utiliser le(s) fichier(s) des sudoers.
Malgré son statut privilégié (tous les utilisateurs de Linux connaissent l’existence de sudo, ce qui est souvent beaucoup moins vrai des SUID/SGID), j’ai choisi de garder ce sujet pour la fin car il est bien plus complexe qu’il n’y paraît si on s’y intéresse un peu.
Sudo : le meilleur pour la fin
La base
On va parler de la façon la plus connue d’augmenter ses privilèges : la commande sudo.
Il est possible de définir dans des fichiers de configurations des règles précises qui donnent aux utilisateurs le droit d’exécuter des commandes au nom d’autres utilisateurs, ce qui inclut la possibilité d’avoir les mêmes droits que root sur tout ou partie des commandes de votre machine. C’est pas beau ça ?
Alors ceux qui suivent se disent que c’est une énorme faille potentielle de sécurité, et ils ont bien raison. C’est donc encore une fois quelque chose à ne pas prendre à la légère.
Ces notions devraient être (bien) expliquées aux utilisateurs de Linux dès leurs premiers pas sur ces systèmes tant c’est important mais ironiquement, c’est l’une des raisons d’être de ce blog car c’est l’un des sésames de Linux les moins bien documentés que vous trouverez : la plupart des sites ne donnent que des exemples simples sans trop les détailler et occultent donc les utilisations les plus fines de ces fichiers ce qui – encore une fois – peut engendrer de graves carences dans la sécurité de vos systèmes.
Le fichier des SUDOERS
Pour vous expliquer comment tout ça fonctionne, je vais devoir soulever le paradoxe de l’œuf et de la poule car le fichier central derrière tout ça n’est visible que si vous avez déjà les droits qu’il peut vous octroyer. Vous suivez ?

Lire le fichier dit “des sudoers” nécessite que vous soyez root ou que vous ayez une délégation de ses droits en ce sens. Pour vous éviter un exercice de pensée je le fais chez moi et je vous montre ce que ça donne.
> sudo cat /etc/sudoers
# User privilege specification
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
@includedir /etc/sudoers.d
Dans les faits le fichier est beaucoup plus gros que ça mais le reste n’est qu’un gros tas de commentaires et mise en place de variables par défaut.
Ici, les commentaires dans la langue de Willy-Will sont assez clairs : la ligne qui concerne root lui donne un accès open bar à la machine (pas de panique on le savait déjà ; cela confirme juste qu’il ne faut pas se connecter avec root à tout bout de champ : laissez ce compte à un administrateur de confiance et réservez le aux tâches d’administrations de la machine) et la ligne sur %sudo indique que les membres du groupe “sudo” peuvent aussi lancer toute commande en tant que n’importe quel utilisateur (ce qui inclut root lui-même). Enfin, la dernière ligne précise que les fichiers présents dans le dossier /etc/sudoers.d seront lus et interprétés comme si leur contenu était listé ici également.
Je vais commencer par le @includedir pour ne plus avoir à s’en soucier. Le contenu de /etc/sudoers est standard et ne devrait jamais être modifié. Rien ne vous empêche de le faire en soit (et cela fonctionnera comme vous le souhaitez) mais à chaque changement de version de votre OS ce fichier va être de nouveau fourni dans sa version par défaut. A partir de là, l’installeur de votre distribution va vous dire qu’il y a un conflit à résoudre. Vous pouvez alors garder votre version (mais perdre les éventuels nouveaux standards de ce fichier apportés par la nouvelle version de l’OS), l’écraser avec le standard (et perdre vos modifications à vous), ou prendre la situation en main (et surtout à la main pour résoudre le conflit en plein milieu de votre mise à jour).
Pour éviter ce scénario pénible, vous pouvez par contre ajouter vos spécificités dans un ou des fichier(s) que vous mettrez dans le répertoire /etc/sudoers.d pour qu’ils ne soient pas écrasés en cas de montée de version. Dès lors, la directive @includedir fait que votre fichier sera bien interprété sans pour autant interférer avec le contenu standard de /etc/sudoers. Malin, non ?
Bon maintenant le cœur du sujet : comment on lit les lignes de délégation de droits et comment on en écrit de nouvelles ?

Une ligne de décompose comme suit :
[qui] [host]=([quel user]:[quel groupe]) [tag]:[cmd]
- qui : le user à qui on est en train de donner une délégation de droits ; précédé d’un ‘%’ cela désigne un groupe plutôt d’un user
- host : sur quelles machines cette délégation est valable (utile quand le fichier sudoer est partagé entre plusieurs machines/hosts), généralement ALL est un bon pari pour vos projets persos
- quel user : au nom de quel user puis-je lancer la commande (qui me délègue ses droits)
- quel groupe : au nom de quel groupe puis-je lancer la commande
- tag : options ; c’est facultatif mais vous verrez souvent NOPASSWD (on y revient plus bas) ou NOEXEC (on y reviendra, mais dans un autre article), le “:” qui suit va avec donc si on n’a pas d’option on n’a pas de “:” en préfixe de [cmd]
- cmd : quelles commandes font l’objet de cette délégation
Donc si je reprends “%sudo ALL=(ALL:ALL) ALL”, on nous dit (dans l’ordre de gauche à droite) que les membres du groupe sudo ont le droit sur tous les hosts d’utiliser les permissions de tout user et tout groupe et ce pour lancer toute commande.
Notez qu’en l’absence du tag NOPASSWD (on y revient dans quelques instants), le mot de passe de l’utilisateur lui sera demandé au moment de la tentative d’utilisation des droits délégués (dans les faits il s’agit la plupart du temps d’une session et le mot de passe ne sera donc demandé qu’à la première utilisation puis après un certain temps d’inactivité vis-à-vis des droits délégués).
Créer une entrée sudoer
Pour écrire dans le fichier /etc/sudoers ou dans un fichier sous /etc/sudoers.d, on doit utiliser visudo.
# Ouvrir le fichier /etc/sudoers pour l'éditer
> sudo visudo
# Ouvrir un autre fichier pour le créer ou l'éditer
> sudo visudo -f /etc/sudoers.d/nom-de-fichier
Alors avant que les petits malins essaient de faire autrement et cassent leur machine, je vous le dis : dans les faits vous pouvez éditer ces fichiers avec n’importe quel éditeur tant qu’il est lancé avec les droits de root mais c’est alors à vous risques et périls : un fichier sudoers mal formatté peut foutre votre machine en l’air et c’est là que visudo prend tout son sens. visudo vérifie la syntaxe des fichiers au moment de l’enregistrement et vous préviens avant qu’il ne soit trop tard s’il y a un problème.
S’il-vous-plaît, ne jouez pas au héros et utilisez le bon outil pour la bonne tâche : ici le bon outil c’est visudo.

Cas pratiques
Je vais lister tout un tas de cas pratiques pour que vous compreniez bien toute la finesse qu’il est possible d’obtenir avec le fichier des sudoers. Notez que je laisse ALL pour les hosts dans tous les cas car les débutants n’auront jamais besoin d’être plus précis et car on n’a pas encore parlé de ces notions sur le blog.
prims ALL=(ALL:ALL) ALL
“prims” a les droits complets sur la machine (mais son mdp lui sera demandé). Dans les faits, cela revient à inclure prims dans le groupe “sudo”.
prims ALL=(ALL) ALL
“prims” peut lancer toutes les commandes en émulant tout utilisateur (ce qui inclut root), mais pas en émulant un groupe.
prims ALL=(:ALL) ALL
“prims” peut lancer toutes les commandes en émulant n’importe quel groupe (ce qui inclut le groupe sudo, qui a lui-même les droits de root), mais ne pourra pas émuler d’autres utilisateurs.
prims ALL=() /usr/bin/systemctl
“prims” peut lancer systemctl avec sudo, mais sans préciser d’utilisateur ou de groupe : on ne peut donc émuler que les droits de root directement (cas du sudo sans options).
Notez que les exécutables concernés doivent être notées avec leur chemin absolu (/usr/bin/systemctl dans le cas ci-dessus). Essayez la commande which si vous n’être pas sûrs du chemin en question.
> which systemctl
/usr/bin/systemctl
Jusque-là ça va ? On tente un exemple un peu plus complexe ? Il est possible de séparer différentes valeurs avec des virgules pour éviter d’avoir à écrire de multiples lignes.
prims ALL=(webapps, www, games:devs, webdevs) /usr/bin/cat, /usr/bin/ls, NOPASSWD:/usr/bin/whoami, /usr/bin/touch
Je vous laisse une minute pour analyser ça ?

Ce qu’on dit ici c’est que “prims” peut émuler au choix les utilisateurs “webapps” ou “www” ou “games” les groupes “devs” ou “webdevs” et ce pour lancer cat ou ls avec demande de mot de passe ou pour lancer whoami ou touch sans demande de mot de passe.
Dans ce cas précis, “prims” ne peut donc ni emprunter les droits de l’utilisateur root, ni ceux du groupe sudo. On est donc dans un cas de paramétrage assez fin des possibilités.
Allez maintenant c’est à vous, soyez imaginatifs mais surtout restez vigilants. Une porte un peu trop ouverte peut vite devenir une porte grande ouverte pour qui sait s’infiltrer (on s’en reparle dans un ou des articles futurs sur le privesc et l’escape).
NOPASSWD
Parlons enfin un peu plus de NOPASSWD. Le fait qu’il faille taper son mot de passe lors de l’utilisation de sudo pose un problème majeur : vous ne pouvez pas utiliser sudo en plein milieu d’un script ou automatiser son lancement en tâche de fond. Bah oui, qui tape le mot de passe dans ce cas-là ? Personne, donc il ne se passe rien !
NOPASSWD est une bonne parade face à cela : pas de prompt pour le mot de passe donc la commande utilisée via sudo peut désormais être utilisée dans les cas de figure cités ci-dessus.
Revers de la médaille ? Vous l’avez vu venir : cela ouvre une brèche dans la sécurité. Il convient donc de ne jamais utiliser NOPASSWD sur une ligne du fichier sudoers qui est open bar : ALL=(ALL:ALL) NOPASSWD:ALL c’est NON !!!

Par contre, ce n’est pas forcément un problème si on est sur un cas plus fin et maîtrisé. Cela ne me choquerait par exemple pas de voir quelque chose du genre :
prims ALL=(some-user:some-group) NOPASSWD:some-command
Dans ce cas pourquoi pas (notez que ce n’est pas un ok définitif). Vous avez peut-être une bonne raison de faire comme ça, mais réfléchissez-y à deux fois. On peut peut-être parvenir au même résultat en faisant autrement, par exemple en mettant “prims” dans “some-group” ? Dans tous les cas, assurez-vous que ce que vous faites et sans danger et en particulier qu’on ne peut pas faire un escape (possibilité de lancer une commande depuis une autre commande) par le biais de some-command.
UTILISER LA DELEGATION
Bon, maintenant qu’on comprend de quoi il retourne : comment ça se passe dans les faits ? Si j’ai le droit s’exécuter une commande en tant que “toto”, je fais quoi exactement pour recourir à ce droit ?
L’utilisation la plus courante de la délégation de droit permet à un utilisateur d’usurper les permissions de root le temps d’une commande. Pour ça, rien de plus simple, on préfixe notre commande par sudo (et là des ampoules s’allument chez certains car on a déjà rencontré ce mot clé sans l’expliquer dans plusieurs articles). Petit exemple très simple avec la commande whoami qui indique quel utilisateur l’a appelée :
> whoami
prims
> sudo whoami
[sudo] Mot de passe de prims :
root
Notez encore une fois qu’on me demande mon mot de passe. Si je le rentre avec succès cela créé une fenêtre de quelques minutes (5 minutes par défaut) pendant lesquelles je pourrais relancer sudo sans qu’on me le demande.
Utiliser sudo comme ça sans plus de détails indique qu’on veut obtenir les droits de root. C’est malheureusement là que s’arrêtent les connaissances de beaucoup d’utilisateurs de Linux et ça, c’est un vrai problème.
Plus haut on a vu comment préciser un utilisateur ou groupe précis auquel on peut se substituer. Pour recourir à ces possibilités, on utilisera des options pour la commande sudo :
# lancer une commande en émulant un utilisateur
> sudo -u webapps whoami
webapps
# lancer une commande en émulant un groupe
> sudo -g group-name command-name
Un dernier mot
Bon c’était pas si terrible, si ?! Puisque ce n’est pas si dur à comprendre, je vous invite à partager cet article auprès de tous les utilisateurs de Linux de votre entourage dont vous ne pensez pas qu’ils connaissent ces subtilités.
Pourquoi ? C’est simple : si la plupart des gens ne connaissent que la version “classique” du sudo c’est tout simplement parce qu’ils ont des droits sudo complets sur leurs machines (ils appartiennent au groupe “sudo” dont on a étudié les droits plus haut). Si cela peut paraître souhaitable pour une utilisation perso d’un PC perso, c’est un gros problème de sécurité sur un serveur destiné à héberger une application ou un service.
Reprenons notre éternel scénario catastrophe où un hacker (on reviendra un jour sur ce terme, que j’utilise par simplicité car c’est celui qu’utilisent la plupart des gens même s’il est inexact dans ce contexte ; on devrait parler de cracker), souhaite obtenir des informations sur votre serveur. S’il existe un compte, appelons le “app”, que vous avez inclus dans le groupe “sudo”, alors obtenir un accès à “app” nous met très (trop) proche d’avoir des droits root : si l’accès a été fait via votre mdp qui a été préalablement cracké, c’est d’ailleurs déjà gagné car c’est la seule information qui sépare notre hacker de sudo.
Restez donc encore et toujours vigilants lorsque vous paramétrez vos droits d’accès. En mettre trop peu peut certes provoques des bugs dans vos applications mais en mettre trop peut mettre en péril toutes les informations que vous détenez, que ce soient les vôtres ou celles de vos utilisateurs. Au choix : prenez la rage de l’utilisateur qui rencontre un bug plutôt que celle de celui qui observe, impuissant, le leak ses nudes de vacances.
J’en ai déjà parlé mais en phase de développement une bonne pratique est de commencer avec des droits minimums (voire inexistants) et de ne les rajouter qu’au fur et à mesure des besoins. C’est beaucoup plus facile à maîtriser que si vous développez en open bar avec l’optique de resserrer l’étau “un jour quand j’aurais le temps”.

Leave a Reply