Aller au contenu
Sécurité medium

Principe de moindre privilège : juste ce qu'il faut

9 min de lecture

Un compte administrateur compromis donne accès à tout le système. Un compte applicatif avec les droits minimaux ne donne accès qu’à son périmètre. Le principe de moindre privilège exige que chaque utilisateur, processus ou service ne dispose que des permissions strictement nécessaires à sa fonction, et pas une de plus.

En résumé : Chaque entité (utilisateur, service, application) ne doit avoir que les droits indispensables à sa tâche. Les privilèges excessifs amplifient l’impact de toute compromission.

Accorder des droits élevés “pour que ça marche” est une pratique courante et dangereuse.

Exemples de raisonnements dangereux :

  • “Je mets 777 pour éviter les problèmes de permissions”
  • “On donne sudo sans restriction, c’est plus simple”
  • “L’application tourne en root, comme ça elle a accès à tout”
  • “Tous les développeurs sont admins sur les serveurs de dev”
  • “Ce compte de service a les droits DBA, au cas où”

Chaque privilège excessif représente :

  • Un périmètre d’impact élargi en cas de compromission
  • Une possibilité d’erreur humaine aux conséquences amplifiées
  • Une violation de conformité (PCI-DSS, ISO 27001, SOC2)
  • Un obstacle au forensic (qui a fait quoi ?)

Le moindre privilège s’applique à tous les niveaux d’un système :

NiveauApplication
UtilisateursComptes nominatifs avec rôles restreints
ApplicationsExécution sous compte dédié non privilégié
Services systèmeDroits limités au strict nécessaire (systemd, capabilities)
ConteneursNon-root, capabilities restreintes, seccomp
Base de donnéesUtilisateurs applicatifs avec droits sur leurs tables uniquement
Cloud (IAM)Politiques avec permissions minimales, pas de *:*

Dans une entreprise sécurisée, chaque employé a un badge qui ouvre uniquement les portes nécessaires à son travail. Le comptable accède à la comptabilité, pas au datacenter. L’agent d’entretien accède aux locaux techniques, pas aux bureaux de direction.

Un système informatique suit la même logique : chaque identité (humaine ou machine) ne doit pouvoir accéder qu’aux ressources requises pour sa mission.

Les systèmes Unix/Linux offrent plusieurs mécanismes pour appliquer le moindre privilège.

Utilisateurs et groupes :

  • Un compte par personne (jamais de comptes partagés)
  • Groupes fonctionnels pour les accès partagés
  • Pas de connexion directe en root (utiliser sudo)

Gestion de sudo :

Fenêtre de terminal
# Mauvais : accès total
user ALL=(ALL) ALL
# Mieux : commandes spécifiques
user ALL=(ALL) /usr/bin/systemctl restart nginx
user ALL=(ALL) /usr/bin/journalctl -u nginx
# Encore mieux : avec justification et timeout
Defaults timestamp_timeout=5
Defaults log_input, log_output

Un service ne devrait jamais tourner en root sauf nécessité absolue.

Avec systemd :

[Service]
User=appuser
Group=appgroup
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

Ces directives :

  • Exécutent le service sous un utilisateur dédié
  • Empêchent l’acquisition de nouveaux privilèges
  • Isolent le système de fichiers
  • Limitent les capabilities Linux au strict nécessaire

Les conteneurs par défaut héritent souvent de trop de privilèges.

Bonnes pratiques :

  • Exécuter en non-root (USER 1000 dans le Dockerfile)
  • Supprimer toutes les capabilities (--cap-drop=all)
  • Ajouter uniquement celles nécessaires (--cap-add=NET_BIND_SERVICE)
  • Utiliser les profils seccomp et AppArmor/SELinux
  • Éviter --privileged sauf cas exceptionnels documentés

Chaque application devrait avoir son propre utilisateur base de données avec des droits limités à ses tables.

Anti-patternBonne pratique
Application connectée en rootUtilisateur dédié par application
Droits GRANT ALLDroits SELECT, INSERT, UPDATE sur tables spécifiques
Un seul compte pour dev/prodComptes séparés par environnement
Mots de passe dans le codeSecrets managés (Vault, Secret Manager)

Les politiques IAM cloud sont souvent trop permissives par défaut.

Principes à appliquer :

  • Jamais de "Action": "*" ou "Resource": "*"
  • Utiliser les managed policies les plus restrictives
  • Préférer les rôles assumables aux credentials long-terme
  • Activer les Service Control Policies (SCP) pour les guardrails
  • Auditer régulièrement avec des outils comme AWS IAM Access Analyzer

Une application web est déployée avec un compte de service ayant tous les droits sur le serveur.

Configuration initiale :

  • Application exécutée en root
  • Accès sudo sans restriction
  • Connexion base de données en DBA
  • Clé SSH avec accès à tous les serveurs

Attaque :

  1. L’attaquant exploite une vulnérabilité applicative (injection)
  2. Il obtient une exécution de code sous le compte root
  3. Il accède à toutes les bases de données (droits DBA)
  4. Il pivote vers tous les serveurs (clé SSH partagée)
  5. Compromission totale de l’infrastructure

Avec moindre privilège :

  • Application sous compte dédié appweb
  • Aucun sudo, capabilities minimales
  • Base de données : droits SELECT/INSERT sur 3 tables
  • Pas de clé SSH (déploiement via CI/CD)

Même attaque :

  1. L’attaquant exploite la même vulnérabilité
  2. Il obtient un accès limité au compte appweb
  3. Il ne peut lire que les données de l’application
  4. Il ne peut pas pivoter (pas de credentials)
  5. Impact contenu à une seule application

Tous les développeurs ont des accès administrateur sur les environnements de développement “pour aller plus vite”.

Situation initiale :

  • 15 développeurs avec sudo complet
  • Accès direct aux serveurs par clé SSH personnelle
  • Pas de traçabilité des actions

Incident :

  1. Un développeur supprime accidentellement un répertoire critique
  2. Impossible de savoir qui a fait l’action
  3. Les backups datent de 24h, perte de données
  4. Aucune procédure de restauration testée

Avec moindre privilège :

  • Développeurs avec accès limité aux logs et redémarrage services
  • Actions privilégiées via pipeline CI/CD avec validation
  • Toutes les actions sudo journalisées

Même erreur :

  1. Le développeur tente de supprimer le répertoire
  2. Permission refusée (pas les droits)
  3. S’il avait les droits (via procédure), l’action est tracée
  4. Restauration possible, responsabilité identifiable

Commencez par cartographier l’existant :

  • Qui a accès à quoi ? Liste des utilisateurs et leurs droits
  • Quels services tournent avec quels droits ? Audit systemd/supervisor
  • Quelles credentials existent ? Clés SSH, tokens, mots de passe
  • Qui utilise vraiment ces accès ? Logs d’authentification

Créez une matrice de rôles basée sur les fonctions réelles :

RôleServeursActionsDonnées
DéveloppeurDev uniquementLogs, restartDonnées test
OpsTousMonitoring, restartMétadonnées
DBABases de donnéesBackup, maintenanceDonnées prod
AdminTousToutesToutes

Les droits doivent être régulièrement révisés :

  • Révocation automatique des accès des personnes qui quittent l’équipe
  • Revue trimestrielle des droits accordés
  • Expiration automatique des accès temporaires
  • Rotation des secrets (mots de passe, clés, tokens)

Définir des politiques strictes mais accorder des exceptions permanentes “en attendant”. Ces exceptions deviennent la norme.

Au fil des projets, un utilisateur accumule des droits sans jamais en perdre. En 3 ans, il a accès à tout sans en avoir besoin.

Appliquer le moindre privilège sur les comptes mais laisser traîner des credentials partagées dans des wikis ou des scripts.

Se concentrer sur les utilisateurs humains et oublier que les applications et services ont aussi besoin d’être restreints.

  1. Juste ce qu’il faut, pas plus — chaque droit excessif amplifie l’impact d’une compromission.

  2. Aucun compte ne devrait être permanent sans justification — les accès doivent être régulièrement révisés.

  3. Les services ne doivent jamais tourner en root — sauf nécessité absolue et documentée.

  4. Tracer toutes les actions privilégiées — pour la conformité et le forensic.

  5. Séparer les environnements — dev, test et production doivent avoir des credentials distincts.

  6. Automatiser la révocation — les accès temporaires doivent expirer automatiquement.