Sections du handbook

Durcir sudo

Revu le

sudo est le pont contrôlé d'un compte utilisateur vers root. Durcissez la politique pour qu'une session volée ne devienne pas un root silencieux, sans authentification ni traçabilité, et journalisez chaque élévation.

La menace : une politique sudoers laxiste, c'est un root sans mot de passe

sudo est le moyen par lequel un compte ordinaire devient root le temps d'une commande, ce qui fait de sa politique une cible permanente. Le danger vient rarement de sudo lui-même : il vient d'une politique sudoers laxiste. Une règle globale NOPASSWD: ALL transforme toute session détournée, ou simplement déverrouillée, en root instantané, sans ré-authentification et sans aucune preuve de qui se trouve réellement au clavier. Même lorsqu'un mot de passe est exigé, la façon d'élever les droits peut fuiter du privilège : une commande lancée via sudo peut être amenée à ouvrir un sous-shell (vi, less, find -exec, le catalogue GTFOBins), à injecter des frappes dans le terminal de contrôle via l'ioctl TIOCSTI, à hériter de variables d'environnement hostiles comme LD_PRELOAD ou PATH, ou à exécuter un binaire malveillant trouvé dans le répertoire courant. Une élévation non journalisée est un rêve d'attaquant : des actions root sans trace d'authentification.

Pourquoi le durcir

sudo se trouve exactement à la frontière entre un utilisateur et toute la machine. Une politique mal réglée revient à distribuer un root sans mot de passe, le pire dénouement possible en matière d'élévation de privilèges. Le durcissement garde ce pont étroit, authentifié et observable : chaque passage est défié, imputable à une personne, enregistré, et débarrassé des canaux auxiliaires (sous-shells, injection dans le terminal, héritage d'environnement) qui permettraient à un simple pied dans la place de se muer en contrôle total. Deux axes comptent : réduire ce qui est accordé, et tout rendre traçable.

Ce que Pavois audite : la politique effective, fusionnée

Pavois audite la politique sudoers effective, et non un seul fichier. Comme sudo fusionne /etc/sudoers avec chaque drop-in sous /etc/sudoers.d/, Pavois parcourt l'arborescence entière : une exemption cachée dans n'importe quel drop-in est ainsi détectée, exactement comme sudo l'appliquerait. Parmi ses règles Sudo, il vérifie : aucune directive !authenticate non commentée ni NOPASSWD global (sudo-require-authentication, sudo-remove-no-authenticate), Defaults use_pty et l'exigence d'un tty réel (sudo-use-pty), noexec pour que les commandes élevées ne puissent pas ouvrir de sous-shell (sudo-noexec), env_reset (sudo-env-reset), ignore_dot (sudo-ignore-dot), et un umask sudo restrictif. Chaque contrôle Defaults recherche la directive non commentée dans l'arborescence sudoers active, reflétant la politique fusionnée et appliquée plutôt qu'un seul fichier.

Comment vérifier et opérer sudo ?

  • Éditez toujours avec visudo (visudo -cf /etc/sudoers.d/10-hardening pour un drop-in) : il valide la syntaxe avant d'écrire, donc une faute de frappe ne peut pas vous verrouiller hors de sudo. Gardez une seconde session root ouverte pendant que vous changez la politique.
  • Voyez les règles effectives d'un utilisateur avec sudo -lU alice : il liste exactement ce que la politique fusionnée lui accorde ; visudo -c valide toute l'arborescence.
  • Faites une baseline des Defaults : grep -hE '^Defaults' /etc/sudoers /etc/sudoers.d/*. À noter : use_pty n'est le défaut upstream que depuis sudo 1.9.14 ; Debian et Ubuntu le rétroportent, mais une RHEL/Rocky plus ancienne peut ne pas l'avoir, donc vérifiez sudo --version.

Limiter les privilèges (ANSSI BP-028 R38 à R44)

Les Defaults réduisent les abus, mais ce sont les règles qui accordent le pouvoir. N'accordez que le strict minimum :

Pratique Règle
Accorder via un groupe dédié (R38) %sudo (Debian) ou %wheel (RHEL), jamais un utilisateur en direct
Cibler un compte non-root (R40) alice ALL=(www-data) ... vaut mieux qu'un (root) réflexe
Lister l'autorisé, jamais nier (R42) ALL, !/bin/su est contournable (chemins alternatifs, copies)
Préciser les arguments (R43) systemctl restart nginx, pas systemctl tout court (qui permet edit puis un shell root). Un * dans un chemin est presque toujours une faille : cat /var/log/messages* peut lire /etc/shadow via ../
Bloquer les évasions vers un shell (R41) NOEXEC: sur les commandes qui peuvent ouvrir un shell (less, vi, find, awk)
Éditer un fichier sans shell root (R44) sudoedit (sudo -e) édite sous l'identité de l'utilisateur puis réinstalle ; l'éditeur ne tourne jamais en root

Journaliser chaque élévation

Par défaut, sudo ne consigne que dans syslog. Rendez chaque usage rejouable : Defaults logfile, Defaults log_input, log_output, Defaults iolog_dir. sudoreplay -l liste les sessions par leur TSID de six caractères, et sudoreplay <TSID> rejoue les frappes et la sortie, décisif pour l'investigation après incident. Attention : log_input capture tout ce qui est tapé, y compris les mots de passe, donc ajoutez Defaults !log_passwords et verrouillez /var/log/sudo-io en 0700 root:root. Déportez les journaux hors de la machine (un attaquant qui obtient root efface les logs locaux) et surveillez les changements de sudoers avec auditd (clé scope).

Pièges

  • N'utilisez pas requiretty. Souvent présenté comme un durcissement, il casse tout sudo non interactif (cron, scripts de déploiement, runuser -u app -- sudo ...). L'équivalent moderne et sûr est use_pty, déjà le défaut sur les distributions récentes.
  • Un * dans un chemin de commande est un piège : la traversée de chemin peut atteindre /etc/shadow. Précisez les arguments exacts à la place.
  • Les règles de négation (!commande) sont contournables : listez l'autorisé, jamais l'interdit.
  • log_input enregistre les secrets sauf si !log_passwords est posé et les journaux d'E/S verrouillés.

Patcher sudo aussi

Aucun Defaults ne protège d'une faille dans sudo lui-même. Deux rappels : CVE-2021-3156 (Baron Samedit) permettait à n'importe quel utilisateur local de devenir root sans même figurer dans sudoers (corrigée en 1.9.5p2) ; CVE-2023-22809 contournait sudoedit via un -- injecté dans $EDITOR pour éditer des fichiers hors périmètre comme /etc/shadow (corrigée en 1.9.12p2). Réduire les privilèges et appliquer les correctifs sont complémentaires, jamais l'un sans l'autre.

FAQ

Pourquoi Pavois scanne-t-il tout /etc/sudoers.d/ ? Parce que sudo applique la politique fusionnée ; une exemption NOPASSWD cachée dans n'importe quel drop-in est active, et Pavois audite ce que sudo applique réellement.

requiretty ou use_pty ? use_pty. requiretty casse le sudo non interactif ; use_pty offre la même protection contre l'injection dans le terminal sans ce coût.

Comment laisser quelqu'un éditer une config sans shell root ? sudoedit (R44) : il édite le fichier sous l'identité de l'utilisateur et le réinstalle, donc l'éditeur ne tourne jamais en root.