Utilisateurs, groupes et sudo
Pourquoi
L'ancien administrateur de sig-app-1 travaillait seul. Il se connectait en root, avec un mot de passe que trois autres personnes connaissaient « pour dépanner », et l'application tournait elle aussi en root, parce que « c'était plus simple pour les permissions ». Il est parti il y a six mois. Personne ne sait si le mot de passe a été changé depuis, ni qui s'en sert encore.
Cette situation, courante sur les serveurs installés à la main, cumule trois défauts :
- On ne sait pas qui a fait quoi. Tout le monde est
root; les journaux ne disent rien d'utile. - On ne peut retirer l'accès de personne sans changer le mot de passe de tous.
- La moindre faille de l'application donne tout le serveur, puisque l'application elle-même a tous les droits.
La réponse de Linux tient en trois idées : un compte par personne, un compte par service, et une élévation de privilèges ponctuelle, tracée et limitée avec sudo. Cette leçon vous montre ce qu'est un compte pour le système, comment créer celui de Signalements, comment gérer les groupes sans piège, et comment écrire des règles sudo qui donnent un droit précis plutôt que tous.
Les concepts
Pour le noyau, un utilisateur est un numéro
Le noyau Linux ne connaît pas les noms. Chaque processus porte des identifiants numériques : un UID (user identifier) et un GID (group identifier), plus une liste de groupes supplémentaires. Chaque fichier porte de même un UID propriétaire et un GID. Quand un processus ouvre un fichier, le noyau compare ces numéros (leçon 9). La page credentials(7) précise qu'un processus a même plusieurs UID : l'UID réel (qui l'a lancé), l'UID effectif (dont il utilise les droits) et un UID sauvegardé. Ils ne diffèrent que pour des programmes particuliers comme sudo, vus plus bas.
Les noms (camille, www-data) sont une commodité pour les humains. La traduction entre noms et numéros est faite par la bibliothèque C, en consultant des bases de comptes dont la liste est donnée par /etc/nsswitch.conf. Sur une machine autonome, ce sont des fichiers texte dans /etc.
L'utilisateur d'UID 0 s'appelle root par convention. Ce n'est pas son nom qui lui donne ses pouvoirs, c'est son numéro : un processus d'UID 0 contourne les contrôles de permissions des fichiers (leçon 9) et peut faire à peu près tout ce que le noyau permet. Un second compte avec l'UID 0, sous un autre nom, serait un second root : c'est l'une des premières choses que vérifie un audit.
/etc/passwd
Ce fichier, lisible par tous, contient une ligne par compte, en sept champs séparés par des deux-points :
$ getent passwd root www-data nobody
root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
| Champ | Exemple | Sens |
|---|---|---|
| 1 | www-data | nom de connexion |
| 2 | x | historiquement le mot de passe haché ; x signifie « voir /etc/shadow » |
| 3 | 33 | UID |
| 4 | 33 | GID du groupe principal |
| 5 | www-data | commentaire (nom complet, souvent appelé champ GECOS) |
| 6 | /var/www | répertoire personnel |
| 7 | /usr/sbin/nologin | programme lancé à la connexion |
getent (get entries) interroge les bases de comptes comme le fait le système, en suivant /etc/nsswitch.conf, alors qu'un grep dans /etc/passwd ne voit que le fichier local. Sur une machine reliée à un annuaire, la différence est essentielle.
Le shell /usr/sbin/nologin affiche un message poli et refuse la connexion : c'est le shell des comptes qui ne doivent jamais ouvrir de session.
/etc/shadow
Les mots de passe hachés étaient autrefois dans /etc/passwd, lisible par tous, ce qui permettait à n'importe quel utilisateur de les copier pour les attaquer hors ligne. Ils ont été déplacés dans /etc/shadow, lisible seulement par root et le groupe shadow :
$ ls -l /etc/passwd /etc/shadow
-rw-r--r-- 1 root root 2875 Apr 23 15:25 /etc/passwd
-rw-r----- 1 root shadow 1340 Apr 23 15:29 /etc/shadow
Chaque ligne a neuf champs, que shadow(5) détaille : le nom, le mot de passe haché, puis des dates exprimées en jours depuis le 1er janvier 1970 (dernier changement, âge minimum et maximum, avertissement, inactivité, expiration du compte) et un champ réservé.
Le second champ dit beaucoup de choses selon sa forme :
| Valeur | Sens |
|---|---|
$y$... | mot de passe haché avec yescrypt |
$6$... | haché avec SHA-512 (méthode plus ancienne, encore répandue) |
! suivi d'un hachage | mot de passe verrouillé (passwd -l) : le hachage est conservé, mais ne peut plus correspondre |
! ou * seul | aucun mot de passe utilisable : la connexion par mot de passe est impossible (d'autres moyens, comme une clé SSH, restent possibles) |
| vide | aucun mot de passe exigé : à proscrire |
Le préfixe entre $ désigne l'algorithme, selon la convention décrite dans crypt(5). Debian et Ubuntu hachent les nouveaux mots de passe avec yescrypt depuis Debian 11 (ses notes de version l'annoncent) et Ubuntu au plus tard depuis sa version 22.04 : le module PAM de changement de mot de passe porte l'option yescrypt dans /etc/pam.d/common-password. yescrypt est volontairement lent et gourmand en mémoire, pour qu'un attaquant qui a volé /etc/shadow ne puisse essayer que peu de mots de passe par seconde.
/etc/group
$ getent group sudo www-data
sudo:x:27:camille
www-data:x:33:
Quatre champs : nom, mot de passe de groupe (inutilisé en pratique, x), GID, et liste des membres supplémentaires, séparés par des virgules. Un utilisateur appartient :
- à son groupe principal, celui dont le GID est dans
/etc/passwd; il n'est généralement pas répété dans/etc/group; - à ses groupes supplémentaires, ceux qui le listent dans
/etc/group.
Sur Debian et Ubuntu, chaque utilisateur reçoit un groupe principal à son nom (le user private group) : camille est dans le groupe camille, dont elle est seule membre. Cela permet de rendre les fichiers inscriptibles par le groupe sans les ouvrir à personne d'autre, ce que la leçon 9 exploite.
Comptes personnels et comptes système
La politique Debian, suivie par Ubuntu, découpe l'espace des UID en classes :
| Plage | Usage |
|---|---|
| 0 à 99 | comptes attribués par Debian, identiques sur toutes les machines (root 0, www-data 33) |
| 100 à 999 | comptes système créés dynamiquement par les paquets ou l'administrateur |
| 1000 à 59999 | comptes des personnes |
| 65534 | nobody, l'utilisateur sans aucun droit |
Un compte système n'est pas une personne : c'est l'identité sous laquelle tourne un service. Il n'a pas de mot de passe, a pour shell nologin, et souvent pas de répertoire personnel. Si l'application est compromise, l'attaquant obtient les droits de ce compte, et seulement ceux-là. C'est l'application directe du moindre privilège : postgres pour PostgreSQL, www-data pour le serveur web, et bientôt signalements pour notre API.
adduser ou useradd
Deux familles d'outils créent des comptes sur Debian et Ubuntu :
useradd,usermod,userdelviennent du paquetpasswdet existent sur toutes les distributions. Ce sont des outils de bas niveau : sans options,useraddcrée un compte sans répertoire personnel et avec des réglages minimaux.adduser,delusersont des scripts propres à Debian, plus haut niveau : ils appliquent la politique de la distribution (/etc/adduser.conf), créent le groupe privé et le répertoire personnel, copient/etc/skel, et posent les questions utiles. La documentation de Debian les recommande pour l'administration courante.
Ce cours utilise adduser pour créer et usermod pour modifier, ce qui est l'usage courant sur Debian et Ubuntu. Sur d'autres distributions (Red Hat, Rocky Linux), adduser n'existe pas ou n'est qu'un lien vers useradd : lisez l'aide avant de transposer.
Le modèle de sudo
sudo permet à un utilisateur autorisé d'exécuter une commande sous une autre identité, root par défaut, après s'être authentifié avec son propre mot de passe. Par rapport au partage du mot de passe de root, il apporte :
- la traçabilité : chaque commande est journalisée avec le nom de la personne ;
- la granularité : on peut autoriser une personne à exécuter certaines commandes seulement ;
- la révocation individuelle : retirer une personne ne touche pas les autres.
Les règles vivent dans /etc/sudoers et dans les fichiers du répertoire /etc/sudoers.d/. Sur Ubuntu 24.04, le fichier par défaut contient, en dehors des commentaires :
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
Defaults use_pty
root ALL=(ALL:ALL) ALL
%admin ALL=(ALL) ALL
%sudo ALL=(ALL:ALL) ALL
@includedir /etc/sudoers.dUne règle se lit « qui peut, sur quelle machine, en tant que qui, exécuter quoi » :
%sudo ALL=(ALL:ALL) ALL
│ │ │ │ └── quelles commandes
│ │ │ └────── en tant que quel groupe
│ │ └────────── en tant que quel utilisateur
│ └─────────────── sur quelles machines
└────────────────────── qui (% = un groupe)La dernière ligne de ce fichier donne donc tous les droits aux membres du groupe sudo ; c'est ainsi que le premier compte créé à l'installation d'Ubuntu devient administrateur. Les distributions de la famille Red Hat utilisent le groupe wheel pour le même rôle. Le groupe admin est un héritage des anciennes versions d'Ubuntu.
Les options Defaults ont été vues à la leçon 7 (env_reset, secure_path) ; use_pty exécute la commande dans un pseudo-terminal séparé, ce qui empêche un programme lancé avec sudo de garder la main sur votre terminal après sa fin.
Un point de syntaxe a des conséquences : d'après sudoers(5), quand plusieurs règles correspondent à une même personne, c'est la dernière qui s'applique, pas la plus précise. L'ordre des fichiers compte. Les fichiers de /etc/sudoers.d/ sont lus par ordre alphabétique, et ceux dont le nom contient un point ou se termine par ~ sont ignorés (une règle déposée dans signalements.conf ne sera jamais lue).
En pratique
Les commandes qui modifient les comptes demandent sudo ; faites-les sur votre machine d'essai. Les sorties montrées sont celles d'Ubuntu 24.04 ; celles des commandes qui exigent root sont décrites plutôt que reproduites.
Qui suis-je ?
$ id
$ id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ groups
id sans argument affiche les identifiants du processus courant (votre shell) : UID, GID principal, groupes supplémentaires. Avec un nom, il interroge la base des comptes. La différence compte : juste après avoir été ajoutée à un groupe, id camille montre le nouveau groupe, mais id dans la session déjà ouverte ne le montre pas encore (voir plus bas).
Créer un compte pour une personne
L'arrivée de Dominique dans l'équipe :
$ sudo adduser dominique
adduser choisit le premier UID libre à partir de 1000, crée le groupe dominique, le répertoire /home/dominique (en 0750 par défaut sur Ubuntu 24.04, d'après /etc/adduser.conf) avec une copie de /etc/skel, puis demande un mot de passe et le nom complet. Sur un serveur où l'on se connecte par clé SSH, le mot de passe ne sert qu'à sudo ; on peut aussi créer le compte avec --disabled-password et déposer la clé publique dans ~dominique/.ssh/authorized_keys (cours SSH).
Vérifiez :
$ getent passwd dominique
$ sudo passwd -S dominique
passwd -S affiche l'état du mot de passe : P (utilisable), L (verrouillé) ou NP (aucun), suivi des dates d'expiration.
Ajouter à un groupe, sans piège
Dominique doit lire les journaux de tous les services, sans être administratrice. La page de journalctl indique que les membres des groupes systemd-journal, adm et wheel peuvent lire tout le journal. Le plus restreint est systemd-journal :
$ sudo usermod -aG systemd-journal dominique
Le -a (append) est indispensable. L'aide de usermod dit que -G fixe la nouvelle liste des groupes supplémentaires : sans -a, usermod -G systemd-journal dominique retire Dominique de tous ses autres groupes, sudo compris s'il y était. C'est l'une des erreurs d'administration les plus fréquentes, et elle peut couper son propre accès administrateur si on l'applique à soi-même.
Le changement est écrit dans /etc/group immédiatement, mais les groupes d'un processus sont fixés à la connexion et hérités ensuite : la session déjà ouverte de Dominique ne les voit pas. Elle doit se déconnecter et se reconnecter. Pour un test immédiat, newgrp systemd-journal ouvre un nouveau shell avec ce groupe.
Pour retirer un utilisateur d'un groupe : sudo gpasswd -d dominique systemd-journal (ou sudo deluser dominique systemd-journal).
Créer le compte de service de Signalements
$ sudo adduser --system --group --home /nonexistent --no-create-home signalements
$ getent passwd signalements
$ id signalements
D'après adduser(8) :
--systemchoisit un UID dans la plage système (100 à 999 par défaut), donne le shell/usr/sbin/nologin, ne fixe pas de mot de passe et ne copie pas/etc/skel;--groupcrée un groupesignalementsdu même nom (sans cette option, un compte système est placé dans le groupenogroup) ;--home /nonexistent --no-create-home: le répertoire par défaut d'un compte système est déjà/nonexistent, un chemin que Debian garantit ne jamais exister. Les écrire explicitement documente l'intention. Si l'application a besoin d'un répertoire de travail, créez-le à part avec les bons droits (leçon 9).
getent affiche une ligne de la forme signalements:x:<UID>:<GID>::/nonexistent:/usr/sbin/nologin, avec un UID entre 100 et 999. L'option --system a une autre qualité : la commande est idempotente, la relancer sur un compte système existant ne produit pas d'erreur. Elle est faite pour les scripts d'installation.
Le service s'exécute ensuite sous ce compte grâce à la directive User=signalements de son unité (leçon 11).
Une règle sudo limitée
Dominique doit pouvoir redémarrer Signalements, et rien d'autre. On crée un fichier dédié, toujours avec visudo :
$ sudo visudo -f /etc/sudoers.d/signalements
visudo ouvre une copie du fichier dans l'éditeur (EDITOR ou VISUAL, leçon 7), vérifie la syntaxe à l'enregistrement, refuse d'installer un fichier invalide, et pose les bons droits. Un fichier sudoers mal formé, écrit avec un éditeur ordinaire, peut rendre sudo inutilisable pour tout le monde, et sur un serveur sans mot de passe root, c'est la console de secours.
Contenu :
# Équipe Signalements : redémarrer et consulter l'état du service, rien d'autre.
dominique ALL=(root) /usr/bin/systemctl restart signalements, \
/usr/bin/systemctl status signalements --no-pager- Les commandes sont écrites avec leur chemin complet, comme l'exige
sudoers(5). - Les arguments font partie de la règle :
sudo systemctl restart signalementsest autorisé,sudo systemctl restart sshne l'est pas, nisudo systemctl stop signalements. --no-pagerferme une porte dérobée, expliquée plus bas.
Vérifiez la syntaxe de l'ensemble, puis ce que Dominique a le droit de faire :
$ sudo visudo -c
$ sudo -l -U dominique
visudo -c vérifie tous les fichiers sans rien modifier. sudo -l -U dominique (exécuté par un administrateur) liste les règles qui s'appliquent à Dominique ; elle-même peut lancer sudo -l.
Lire les journaux de sudo
Chaque utilisation de sudo, réussie ou refusée, est envoyée au journal système avec l'utilisateur, le terminal, le répertoire, l'identité cible et la commande :
$ journalctl _COMM=sudo --since today
Le filtre _COMM=sudo ne garde que les messages émis par le programme sudo. Une tentative non autorisée y apparaît avec la mention command not allowed. Sur Ubuntu avec rsyslog, les mêmes lignes sont aussi écrites dans /var/log/auth.log.
Devenir root, si vraiment il le faut
$ sudo -i
sudo -i ouvre un shell de connexion de root, avec son environnement, après vous avoir authentifié par votre propre mot de passe : la session est attribuée à votre nom dans les journaux, mais ce que vous tapez ensuite ne l'est plus commande par commande. Préférez sudo commande pour chaque action.
su -, l'ancienne méthode, demande le mot de passe de root. Sur Ubuntu, le compte root n'a pas de mot de passe utilisable par défaut (sudo passwd -S root affiche L), et su - échoue donc : c'est voulu. On ne se connecte pas directement en root, ni en console, ni en SSH.
Le départ d'une personne
Dominique quitte l'équipe. Il faut que plus aucun moyen d'accès ne fonctionne, tout en gardant ses fichiers le temps de les relire :
$ sudo usermod --lock --expiredate 1 dominique
$ sudo gpasswd -d dominique sudo
$ sudo rm /etc/sudoers.d/dominique-signalements # s'il existe un fichier à son nom
$ sudo pkill -KILL -u dominique
--lockplace un!devant le hachage du mot de passe. L'aide deusermodprécise que cela ne verrouille que le mot de passe : une connexion par clé SSH reste possible. D'où :--expiredate 1fixe l'expiration du compte au 2 janvier 1970 : le compte est expiré, ce qui bloque toute ouverture de session, clé SSH comprise. La pageshadow(5)déconseille la valeur0, qui peut être interprétée comme « pas d'expiration ».- La règle
sudoà son nom et son appartenance au groupesudosont retirées, pour qu'une réactivation par erreur ne rende pas ses droits. pkill -KILL -u dominiquetermine les processus encore en cours sous son compte, sessions ouvertes comprises (leçon 10).
Plus tard, sudo deluser --remove-home dominique supprime le compte et son répertoire. Avant, cherchez les fichiers qui lui appartiennent ailleurs (sudo find / -xdev -user dominique) : supprimer le compte en laisse les fichiers orphelins, avec un UID sans nom, que le prochain compte créé avec ce même UID récupérerait.
Sous le capot
Comment sudo obtient des droits qu'il n'a pas
Un processus lancé par Dominique a son UID. Comment un programme qu'elle lance peut-il devenir root ? Par le bit setuid :
$ ls -l /usr/bin/sudo /usr/bin/passwd
-rwsr-xr-x 1 root root 64152 May 30 2024 /usr/bin/passwd
-rwsr-xr-x 1 root root 282032 Sep 21 20:37 /usr/bin/sudo
Le s à la place du x du propriétaire signifie : quand ce programme est exécuté, l'UID effectif du processus devient celui du propriétaire du fichier, ici root, tandis que l'UID réel reste celui de la personne qui l'a lancé (credentials(7)). sudo démarre donc avec les droits de root, lit /etc/sudoers (illisible pour vous), vous authentifie, vérifie la règle, journalise, puis lance la commande avec l'identité demandée. passwd utilise le même mécanisme pour écrire dans /etc/shadow. La leçon 9 revient sur ce bit et sur les risques qu'il présente.
L'authentification elle-même est déléguée à PAM (Pluggable Authentication Modules), la bibliothèque qui centralise sur Linux la vérification des mots de passe, l'ouverture des sessions et les règles d'expiration, configurée par les fichiers de /etc/pam.d/. sudo, login et sshd passent tous par elle. Après une authentification réussie, sudo retient votre réussite pendant 15 minutes par défaut (timestamp_timeout), par terminal : c'est pourquoi il ne redemande pas le mot de passe à chaque commande.
NSS : d'où viennent les noms
Quand ls -l affiche signalements au lieu de l'UID, il appelle la fonction getpwuid() de la bibliothèque C. Celle-ci lit /etc/nsswitch.conf (Name Service Switch) pour savoir quelles sources consulter, et dans quel ordre :
passwd: files systemd
group: files systemd
shadow: files systemdfiles désigne les fichiers de /etc ; systemd les comptes dynamiques que systemd peut créer pour un service (DynamicUser=). Une machine reliée à un annuaire d'entreprise ajoute sss ou ldap à ces lignes, et les comptes n'apparaissent alors plus dans /etc/passwd, mais getent les trouve. C'est la raison pour laquelle on utilise getent plutôt que grep dans les scripts.
Pièges courants
usermod -G sans -a. Vous remplacez la liste des groupes au lieu de la compléter. Si vous l'avez fait sur votre propre compte et perdu sudo, il faut un autre administrateur ou la console de secours.
« J'ai été ajoutée au groupe, mais ça ne marche pas. » Les groupes sont lus à la connexion. Déconnexion et reconnexion, ou newgrp. Vérifiez avec id (le processus) et non id <nom> (la base).
Éditer /etc/sudoers sans visudo. Une virgule de trop, et sudo refuse de fonctionner pour tout le monde (sudo: parse error in /etc/sudoers near line ...). Toujours visudo, et gardez une seconde session root ouverte quand vous modifiez la configuration de sudo sur un serveur distant.
Un fichier /etc/sudoers.d/signalements.conf sans effet. Les noms qui contiennent un point sont ignorés. Renommez-le signalements.
Une règle plus précise qui ne s'applique pas. La dernière règle correspondante gagne. Une règle restrictive placée avant un %sudo ALL=(ALL:ALL) ALL pour un membre du groupe sudo n'a aucun effet.
Des fichiers orphelins après la suppression d'un compte. ls -l affiche un numéro à la place du nom. Cherchez-les avec find / -xdev -nouser.
Un compte de service avec un shell et un mot de passe. Créé avec adduser signalements au lieu de adduser --system, le compte peut ouvrir une session. Vérifiez le septième champ de /etc/passwd et le second de /etc/shadow.
Sécurité
Une règle sudo sur une commande qui sait lancer un shell équivaut à ALL. Beaucoup de programmes permettent d'exécuter une autre commande : un éditeur (vim, :!sh), un visualiseur (less, !sh), find (-exec), tar (options de point de contrôle), awk, python... Le projet GTFOBins recense ces échappements, programme par programme ; pour less, il rappelle que la commande s'exécute avec les privilèges obtenus par sudo, qui ne sont pas abandonnés. Avant d'autoriser une commande par sudo, cherchez-la sur GTFOBins.
C'est la raison du --no-pager dans la règle de Dominique. systemctl status affiche sa sortie dans less. La documentation de systemd indique que, sous sudo, un mode sécurisé du visualiseur est activé automatiquement, qui interdit d'y lancer des commandes, et qu'il peut être désactivé par la variable SYSTEMD_PAGERSECURE ; elle conseille de supprimer purement et simplement le visualiseur avec --no-pager dans ce contexte. Ne laissez pas votre sécurité dépendre d'un réglage par défaut que l'environnement peut modifier.
Pour permettre l'édition d'un fichier précis, n'autorisez pas vim /etc/signalements/env : utilisez sudoedit. La personne édite une copie avec son propre éditeur et ses propres droits ; sudo remplace ensuite le fichier.
Le groupe docker vaut root. La documentation de Docker l'écrit en toutes lettres : ce groupe donne des privilèges équivalents à ceux de root, puisqu'il permet de lancer un conteneur qui monte la racine du système. Le cours Docker : les fondamentaux y revient. Il en va de même pour lxd, disk (accès brut aux disques) et, dans une moindre mesure, adm et systemd-journal, qui donnent accès à des journaux parfois sensibles. Auditez les groupes privilégiés comme vous auditez le groupe sudo.
Pas de compte partagé. Un compte exploit dont plusieurs personnes connaissent le mot de passe ou partagent la clé détruit la traçabilité et rend toute révocation collective. Un compte par personne, des droits par groupe.
Le moins possible de root permanent. Personne ne se connecte en root ; sudo sert à des commandes précises ; les droits larges (%sudo ALL) sont réservés à quelques administrateurs, et les autres reçoivent des règles limitées. Le cours Durcissement Linux complète ces mesures (politique de mots de passe, connexion SSH par clé uniquement, PermitRootLogin no).
En production
- Les comptes ne se créent pas à la main sur chaque machine. À partir de quelques serveurs, les comptes des personnes viennent d'un annuaire central (LDAP, FreeIPA, ou l'annuaire de l'entreprise via SSSD), ou sont déployés par un outil de gestion de configuration (cours Ansible : les fondamentaux). Le départ d'une personne devient une seule opération, au lieu d'une liste de serveurs à ne pas oublier.
- Les règles sudo sont versionnées, relues comme du code, et déployées dans
/etc/sudoers.d/avec une validationvisudo -c -favant installation. - Les comptes de service sont créés par le paquet ou par l'unité. Un paquet Debian crée son compte avec
adduser --systemdans ses scripts d'installation ; une unité systemd peut même demander un compte éphémère avecDynamicUser=yes(cours systemd en profondeur). - Les accès sont revus régulièrement : qui est dans
sudo,docker,adm; quels comptes ont un mot de passe ; quels comptes ne se sont pas connectés depuis trois mois (lastlog). - Chez Lyneko, les applications tournent dans des conteneurs sur Kubernetes, où la même logique s'applique avec d'autres outils : chaque application tourne sous un UID non privilégié fixé dans son image (cours Construire des images de conteneurs), et les droits des personnes sur le cluster passent par des rôles plutôt que par un compte administrateur partagé.
Exercices
1. Lire les comptes (niveau 100). Pour chacune des lignes suivantes de /etc/passwd, dites s'il s'agit d'une personne, d'un compte système ou d'un compte suspect, et pourquoi.
postgres:x:113:121:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
alice:x:1001:1001:Alice Martin,,,:/home/alice:/bin/bash
maint:x:0:0:maintenance:/root:/bin/bash
signalements:x:998:998::/nonexistent:/usr/sbin/nologinSolution
postgres : compte système (UID 113, dans la plage 100 à 999), créé par le paquet PostgreSQL ; son shell est /bin/bash parce que l'on s'y connecte par sudo -u postgres psql, mais il n'a normalement pas de mot de passe. alice : une personne (UID 1001). maint : suspect : son UID est 0, c'est un second root sous un autre nom ; à investiguer immédiatement (porte dérobée ou héritage dangereux). signalements : compte système de service, sans répertoire ni shell.
2. Le piège du groupe (niveau 200). Un administrateur tape sudo usermod -G docker camille pour permettre à Camille d'utiliser Docker. Camille était membre de sudo et adm. Que s'est-il passé, comment le constater, et comment réparer ? Que faut-il penser, par ailleurs, de la demande initiale ?
Solution
-G sans -a a remplacé la liste : Camille n'est plus que dans docker (et son groupe principal). getent group sudo adm ne la liste plus ; id camille le montre. Réparation, par un autre administrateur : sudo usermod -aG sudo,adm camille, puis reconnexion de Camille. Sur la demande initiale : le groupe docker donne l'équivalent de root. Pour une personne déjà administratrice, cela ne change pas grand-chose, mais il faut le savoir ; pour une autre, c'est une élévation de privilèges complète, qui doit être décidée comme telle (ou évitée avec Docker en mode rootless).
3. Une règle sudo sûre (niveau 200). L'équipe veut que les membres du groupe signalements-dev puissent : redémarrer le service, lire ses journaux, et éditer /etc/signalements/env. Écrivez le fichier /etc/sudoers.d/signalements-dev, en justifiant chaque choix, et indiquez la commande pour le valider.
Solution
%signalements-dev ALL=(root) /usr/bin/systemctl restart signalements
%signalements-dev ALL=(root) sudoedit /etc/signalements/envLe redémarrage avec chemin complet et arguments figés. Pour les journaux, pas de règle sudo du tout : ajoutez les membres au groupe systemd-journal (usermod -aG), ce qui évite d'autoriser journalctl par sudo (qui utilise less comme visualiseur). Pour l'édition, sudoedit plutôt qu'un éditeur lancé en root, qui donnerait un shell. Validation : sudo visudo -c -f /etc/sudoers.d/signalements-dev, puis sudo visudo -c pour l'ensemble, et sudo -l -U <un membre> pour vérifier le résultat. Le nom du fichier ne contient pas de point.
4. Le départ (niveau 200). Expliquez pourquoi sudo passwd -l dominique ne suffit pas à couper l'accès de Dominique, et listez dans l'ordre ce que vous faites le jour de son départ, puis un mois plus tard.
Solution
passwd -l ne verrouille que le mot de passe : si Dominique a une clé SSH autorisée, elle peut toujours se connecter, et les sessions déjà ouvertes continuent. Le jour même : usermod --lock --expiredate 1 (bloque toute ouverture de session, clé comprise), retrait des groupes privilégiés et des règles sudo à son nom, pkill -KILL -u dominique pour les sessions en cours, révocation de ses accès hors du serveur (forge, cloud, gestionnaire de secrets), et rotation des secrets qu'elle connaissait. Un mois plus tard, après avoir récupéré ce qui doit l'être : find / -xdev -user dominique pour les fichiers hors de son répertoire, puis deluser --remove-home dominique. Mieux encore : un annuaire central, où cette procédure tient en une opération.
Récapitulatif
- Pour le noyau, un utilisateur est un UID, un groupe un GID ; les noms viennent de bases consultées selon
/etc/nsswitch.conf.getentinterroge ces bases comme le système. /etc/passwd(lisible par tous) décrit les comptes,/etc/shadow(réservé àrootetshadow) contient les mots de passe hachés, en yescrypt ($y$) sur Debian et Ubuntu récents, et les dates d'expiration./etc/groupliste les membres supplémentaires.- UID 0 = root, quel que soit le nom. Comptes des personnes à partir de 1000, comptes système de 100 à 999, sans mot de passe et avec
nologin. adduser --system --groupcrée le compte d'un service ;usermod -aGajoute à un groupe (jamais-Gseul) ; les groupes sont pris en compte à la connexion suivante.sudo: une identité par personne, des règles limitées et avec arguments, écrites avecvisudodans/etc/sudoers.d/(noms sans point), la dernière règle correspondante gagne, tout est journalisé (journalctl _COMM=sudo).- Une commande qui sait lancer un shell (éditeur, visualiseur,
find...) vautALL: GTFOBins,--no-pager,sudoedit. Le groupedockervautroot. - Le départ d'une personne : verrouiller et expirer le compte, retirer les droits, terminer les sessions, puis supprimer.
Pour aller plus loin
man 5 passwd,man 5 shadowetman 7 credentials, pour le détail des champs et des identifiants d'un processus.- La section 9.2 de la politique Debian, pour la logique des plages d'UID.
- Le manuel
sudoers(5), long mais précis ; commencez par les sections User specification et Command environment. - Le site GTFOBins, à consulter avant d'autoriser toute commande par sudo.
- La leçon suivante, qui montre comment ces UID et GID décident, fichier par fichier, de qui peut lire, écrire et exécuter.
Sources
- Linux man-pages, passwd(5), shadow(5), group(5), credentials(7)
- Debian Policy Manual, 9.2 Users and groups (classes d'UID et de GID)
- Debian, adduser(8) et adduser.conf(5)
- sudo, sudoers(5) et visudo(8)
- libxcrypt, crypt(5) : formats de hachage, dont yescrypt
- Debian 11, notes de publication : 5.1.4, hachage des mots de passe avec yescrypt
- GTFOBins, binaires Unix utilisables pour contourner une restriction
- Docker, Linux post-installation steps (le groupe docker)
- systemd, systemctl(1) : SYSTEMD_PAGERSECURE
- Ubuntu Server, documentation : User management