Aller au contenu
Sécurité medium

Durcir et journaliser sudo (sudoers)

10 min de lecture

sudo est la porte d'élévation de privilèges de vos serveurs : c'est à la fois un point de contrôle et une cible. Mal configuré, il accorde trop, journalise trop peu, et laisse passer des contournements. Ce guide montre comment journaliser sudo de façon exploitable (avec enregistrement de session rejouable), durcir les Defaults sans casser l'automatisation, et limiter les privilèges proprement. L'approche suit la section sudo des CIS Benchmarks (5.2/5.3 selon la version) et les recommandations R38 à R44 d'ANSSI-BP-028 v2.0.

  • Journaliser sudo dans un fichier dédié et enregistrer les sessions
  • Éditer sudoers en sécurité avec visudo
  • Durcir les Defaults (use_pty, !visiblepw, délais) sans footgun
  • Limiter les privilèges : groupe dédié, négations bannies, arguments précisés
  • Rejouer une session sudo avec sudoreplay pour l'investigation

Chaque règle sudoers est une délégation de pouvoir. Deux risques :

  • Trop de privilèges : un ALL=(ALL) ALL ou des commandes mal cadrées permettent une élévation complète, parfois par contournement (un éditeur autorisé qui lance un shell, une négation ! contournable).
  • Pas de traçabilité : par défaut, sudo ne consigne que dans syslog. Sans journal dédié ni enregistrement, vous ne savez pas qui a fait quoi lors d'un incident.

Durcir sudo, c'est donc réduire ce qui est accordé et rendre tout traçable.

  • Un serveur Linux (Debian, Ubuntu, RHEL, AlmaLinux, Rocky)
  • Un accès root (ou un sudo fonctionnel) et un second accès de secours
  • De préférence une VM de test : une erreur sudoers peut couper l'accès admin

Regardez les Defaults déjà en place :

Fenêtre de terminal
sudo grep -hE '^Defaults' /etc/sudoers /etc/sudoers.d/* 2>/dev/null

Sur une Debian 12, vous trouverez en général :

Defaults env_reset
Defaults mail_badpass
Defaults secure_path="..."
Defaults use_pty

Sur Debian 12 (sudo 1.9.13p3), use_pty, mail_badpass (alerte mail en cas d'échec d'authentification) et secure_path (PATH fixe, anti détournement de binaire lancé via sudo) sont déjà posés. Attention toutefois : use_pty n'est le défaut upstream qu'à partir de sudo 1.9.14 ; Debian et Ubuntu l'activent via un correctif distributeur, mais une RHEL/Rocky plus ancienne peut ne pas l'avoir (vérifiez avec sudo --version). Mauvaise nouvelle commune : aucun journal dédié n'est configuré, sudo ne consigne que dans syslog.

C'est le cœur du durcissement : rendre chaque usage de sudo exploitable. Créez /etc/sudoers.d/10-hardening :

  1. Définir un journal dédié et l'enregistrement de session

    Defaults logfile="/var/log/sudo.log"
    Defaults log_input, log_output
    Defaults iolog_dir="/var/log/sudo-io"
  2. Valider puis poser les bons droits

    Fenêtre de terminal
    sudo visudo -cf /etc/sudoers.d/10-hardening
    sudo chmod 0440 /etc/sudoers.d/10-hardening
  3. Vérifier que tout est capturé

    Après une commande sudo id lancée par un utilisateur, le journal dédié contient l'essentiel :

    Jun 25 07:34:44 : alice : PWD=/home/alice ; USER=root ; TSID=000001 ;
    COMMAND=/usr/bin/id

    Et la session complète est enregistrée :

    Fenêtre de terminal
    sudo ls /var/log/sudo-io/
    sudo sudoreplay -l # lister les sessions et leurs TSID
    sudo sudoreplay 000001 # rejouer la session par son TSID

    Le TSID est un identifiant de 6 caractères (ici 000001) ; sudoreplay -l vous le donne pour chaque session.

sudoreplay rejoue la session à l'identique (frappes et sortie), un atout majeur pour l'investigation après incident.

Ajoutez au même fichier les options qui réduisent les abus :

Defaults use_pty
Defaults !visiblepw
Defaults passwd_tries=3
Defaults passwd_timeout=1
Defaults timestamp_timeout=5
OptionEffet
use_ptyExécute la commande dans un pseudo-terminal : empêche une tâche lancée via sudo de détourner le terminal réel
!visiblepwRefuse sudo si la saisie du mot de passe serait visible (terminal sans masquage)
passwd_triesNombre d'essais de mot de passe autorisés (défaut 3) avant échec
passwd_timeoutDélai (minutes) pour saisir le mot de passe
timestamp_timeoutDurée (minutes) avant de redemander le mot de passe. Défaut 15 ; 5 est plus strict, 0 redemande à chaque sudo

Au-delà des Defaults (que l'ANSSI regroupe sous R39), ce sont les règles qui comptent. Le découpage R40 à R44 vise à n'accorder que le strict nécessaire.

  • Un groupe dédié (ANSSI R38) : accordez sudo via un groupe (%sudo sur Debian, %wheel sur RHEL), jamais à des utilisateurs en direct.

    %sudo ALL=(ALL:ALL) ALL
  • Cibler un compte non privilégié (R40) : quand une commande n'exige pas root, imposez l'utilisateur cible. alice ALL=(www-data) /usr/bin/... vaut mieux qu'un (root) réflexe qui rouvre la porte de l'élévation complète.

  • Bannir les négations (R42) : une règle du type ALL, !/bin/su est contournable (chemins alternatifs, copies du binaire). Listez ce qui est autorisé, pas ce qui est interdit.

  • Préciser les arguments (R43) : alice ALL=(root) /usr/bin/systemctl restart nginx est bien plus sûr que /usr/bin/systemctl tout court, qui permettrait systemctl edit et donc un shell root. Méfiez-vous des jokers : une règle comme cat /var/log/messages* laisse lire /etc/shadow via un chemin remontant (../../etc/shadow). Un * dans un chemin est presque toujours une faille.

  • Éviter les commandes qui ouvrent un shell (R41) : vi, less, find, awk autorisés sans restriction permettent de sortir vers un shell root (la référence des évasions est GTFOBins). Forcez la directive NOEXEC, qui empêche la commande de lancer un sous-processus :

    %ops ALL=(root) NOEXEC: /usr/bin/less
  • Éditer un fichier sans shell root (R44) : pour laisser modifier une configuration, utilisez sudoedit (alias sudo -e) plutôt qu'un éditeur lancé en root. sudoedit copie le fichier, l'édite sous l'identité de l'utilisateur, puis le réinstalle : l'éditeur ne tourne jamais avec les privilèges root.

    alice ALL=(root) sudoedit /etc/nginx/nginx.conf

Patcher sudo : durcir ne dispense pas de mettre à jour

Section intitulée « Patcher sudo : durcir ne dispense pas de mettre à jour »

Aucun Defaults ne protège d'une faille dans sudo lui-même. Deux vulnérabilités majeures le rappellent :

  • CVE-2021-3156 « Baron Samedit » (CVSS 7.8) : un débordement de tas exploitable par n'importe quel utilisateur local pour devenir root, sans même figurer dans sudoers. Versions touchées : sudo 1.8.2 à 1.8.31p2 et 1.9.0 à 1.9.5p1, corrigé en 1.9.5p2.
  • CVE-2023-22809 (CVSS 7.8) : un contournement de sudoedit via un séparateur -- injecté dans $EDITOR/$SUDO_EDITOR permettait d'éditer un fichier hors périmètre (jusqu'à /etc/shadow). Corrigé en 1.9.12p2.

Vérifiez votre version et tenez-la à jour :

Fenêtre de terminal
sudo --version | head -1

La leçon est constante en durcissement : réduire les privilèges et appliquer les correctifs sont deux chantiers complémentaires, jamais l'un sans l'autre.

Quelques contrôles rapides :

Fenêtre de terminal
# La configuration globale est-elle valide ?
sudo visudo -c
# Quelles règles s'appliquent à un utilisateur ?
sudo -lU alice
# Le journal dédié grossit-il à chaque sudo ?
sudo tail -f /var/log/sudo.log
  • Garder un accès de secours : avant de durcir, gardez une session root ou une console ouverte. Une erreur sudoers se corrige depuis cet accès.
  • Protéger les journaux : /var/log/sudo.log et /var/log/sudo-io doivent être en accès root uniquement, et idéalement déportés vers un collecteur (un attaquant qui obtient root effacerait les logs locaux).
  • Tracer les changements de sudoers : couplez avec auditd, qui surveille /etc/sudoers et /etc/sudoers.d/ (clé scope).
  • Revoir régulièrement : sudo -lU <user> pour auditer les droits réels, pas seulement la théorie des fichiers.
SymptômeCause probableSolution
Plus aucun sudo ne fonctionneErreur de syntaxe écrite sans visudoCorriger depuis l'accès root de secours, valider avec visudo -c
Le cron ou un script sudo échouerequiretty poséRetirer requiretty, garder use_pty
Rien dans /var/log/sudo.loglogfile absent ou fichier non rechargéVérifier /etc/sudoers.d/, droits 0440, relancer une commande
sudoreplay ne trouve rienlog_output non activéAjouter log_input, log_output et iolog_dir
Une règle « tout sauf X » est contournéeUsage de négations !Lister les commandes autorisées explicitement
  • Toujours visudo : jamais d'édition directe de sudoers
  • Journal dédié (logfile) + enregistrement de session (log_input/log_output) rejouable avec sudoreplay
  • use_pty (souvent déjà par défaut) et !visiblepw ; jamais requiretty (casse le non-interactif)
  • Groupe dédié (R38), compte cible non privilégié (R40), pas de négations (R42), arguments précisés (R43), NOEXEC (R41), sudoedit (R44)
  • Mettre à jour sudo : durcir ne remplace pas le patch (Baron Samedit, contournement sudoedit)
  • Protéger les journaux sudo (root only, déportés) car ils contiennent des traces sensibles
  • Référentiels : section sudo des CIS Benchmarks (5.2/5.3 selon version) et ANSSI-BP-028 R38 à R44

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn