Aller au contenu

Principe de minimisation : moins c'est mieux

Mise à jour :

Un serveur avec 200 paquets installés possède 200 sources potentielles de vulnérabilités. Un serveur avec 50 paquets en a quatre fois moins. Le principe de minimisation repose sur cette évidence : ce qui n’existe pas ne peut pas être attaqué. En limitant les composants installés, les services actifs et les fonctionnalités exposées, on réduit mécaniquement les risques.

En résumé : La minimisation consiste à n’installer et n’activer que le strict nécessaire. Chaque paquet, service ou port supplémentaire augmente la surface d’attaque, la charge de maintenance et le risque d’erreur de configuration.

L’erreur de l’installation par défaut

Une erreur fréquente consiste à accepter les choix par défaut lors de l’installation d’un système ou d’une application.

Exemples de raisonnements dangereux :

  • “J’installe le groupe de paquets complet, on ne sait jamais”
  • “Ce service est désactivé, il ne gêne pas”
  • “On pourrait avoir besoin de cette fonctionnalité plus tard”
  • “L’image Docker officielle est forcément optimisée”
  • “C’est plus simple de tout installer maintenant”

Chaque composant supplémentaire représente :

  • Une vulnérabilité potentielle à surveiller et patcher
  • Des ressources consommées (mémoire, CPU, disque)
  • Une complexité accrue pour le diagnostic et la maintenance
  • Un vecteur d’attaque supplémentaire en cas de compromission

:::caution[Erreur fréquente] Penser qu’un service désactivé n’est pas un risque. Le binaire est présent, ses vulnérabilités aussi. Un attaquant qui compromet le système peut le réactiver. :::

Le principe de minimisation

La minimisation consiste à réduire chaque composant d’un système à son strict nécessaire :

  • Paquets installés : uniquement ceux requis pour la fonction du serveur
  • Services actifs : uniquement ceux utilisés en production
  • Ports ouverts : uniquement ceux nécessaires aux communications légitimes
  • Utilisateurs et comptes : uniquement ceux avec un besoin réel
  • Permissions : uniquement celles requises pour chaque tâche

La métaphore de la maison

Imaginez une maison avec 50 portes et fenêtres contre une maison avec 5 entrées. La première nécessite 50 serrures à vérifier, 50 points d’entrée potentiels pour un cambrioleur, 50 éléments à maintenir. La seconde est plus simple à sécuriser, surveiller et entretenir.

Un serveur minimaliste suit la même logique : moins de points d’entrée, moins de surface à défendre.

Les domaines d’application

Installation système

L’installation minimaliste commence dès le choix de la distribution et des paquets :

ApprocheRisqueRecommandation
Installation “complète”Centaines de paquets inutilesÉviter
Installation “serveur” standardDizaines de paquets superflusAcceptable
Installation minimale + ajouts ciblésSurface d’attaque réduiteRecommandé
Image durcie (CIS, STIG)Surface minimale, configuration vérifiéeIdéal

Privilégiez une installation minimale puis ajoutez uniquement les paquets nécessaires. Documentez chaque ajout avec sa justification.

Services au démarrage

Un serveur Linux typique démarre avec des dizaines de services. La plupart sont inutiles pour sa fonction principale.

Pratiques recommandées :

  • Auditer les services actifs : systemctl list-units --type=service
  • Désactiver les services non utilisés : systemctl disable <service>
  • Masquer les services qui ne doivent jamais démarrer : systemctl mask <service>
  • Documenter chaque service actif et sa raison d’être

Un serveur web n’a pas besoin de Bluetooth, d’un serveur d’impression ou d’un agent de messagerie. Chaque service supplémentaire est un risque inutile.

Ports réseau

Les ports ouverts sont les portes d’entrée réseau du système.

Approche minimaliste :

  • Fermer par défaut : politique de pare-feu “deny all” en entrée
  • Ouvrir explicitement : uniquement les ports nécessaires
  • Restreindre les sources : limiter les IP autorisées quand c’est possible
  • Chiffrer : utiliser TLS pour toutes les communications

Un serveur web n’a besoin que des ports 80/443 (et SSH pour l’administration, idéalement restreint à un bastion).

Images conteneur

Les images Docker héritent souvent d’une distribution complète avec des centaines de binaires inutiles.

Image de baseTaille typiqueSurface d’attaque
Ubuntu/Debian100-200 MBÉlevée
Alpine5-10 MBRéduite
Distroless2-20 MBMinimale
Scratch0 MB + binaireMinimale

Une image distroless ou basée sur Alpine réduit drastiquement le nombre de binaires exploitables en cas de compromission.

Scénario 1 : Le serveur “au cas où”

Un administrateur installe un serveur Linux pour héberger une application web. Par précaution, il installe une distribution complète avec tous les outils “qui pourraient servir”.

Configuration initiale :

  • 847 paquets installés
  • 45 services actifs au démarrage
  • Serveur SSH, FTP, mail, base de données, serveur web tous présents
  • Ports 21, 22, 25, 80, 443, 3306, 5432 ouverts

6 mois plus tard :

  • Une vulnérabilité critique dans le serveur FTP (jamais utilisé)
  • L’attaquant l’exploite et obtient un accès initial
  • Il trouve les credentials MySQL dans un fichier de configuration
  • Il exfiltre la base de données clients

Avec minimisation :

  • 127 paquets installés (uniquement web + dépendances)
  • 8 services actifs (nginx, application, monitoring)
  • Ports 80, 443 ouverts (SSH via bastion uniquement)
  • Pas de serveur FTP, pas de vulnérabilité FTP

Scénario 2 : L’image conteneur vulnérable

Une équipe déploie une application Python dans un conteneur basé sur python:3.11.

Image initiale (python:3.11) :

  • Taille : 1.2 GB
  • Contient : bash, curl, wget, apt, gcc, make, et des centaines d’utilitaires
  • Vulnérabilités connues : 47 (dont 3 critiques)

Un attaquant exploite une faille applicative :

  1. Il obtient une exécution de code dans le conteneur
  2. Il utilise curl pour télécharger un reverse shell
  3. Il utilise bash pour l’exécuter
  4. Il utilise les outils présents pour pivoter

Avec image minimale (python:3.11-slim + multi-stage) :

  • Taille : 150 MB
  • Contient : uniquement Python et les dépendances de l’application
  • Vulnérabilités connues : 5 (aucune critique)
  • Pas de shell, pas de curl, pas de wget

L’attaquant qui exploite la même faille ne peut pas télécharger d’outils ni obtenir de shell interactif. L’impact de la compromission est contenu.

Comment appliquer la minimisation

Audit de l’existant

Avant de réduire, il faut connaître l’état actuel :

  • Paquets installés : dpkg -l ou rpm -qa
  • Services actifs : systemctl list-units --type=service --state=running
  • Ports ouverts : ss -tlnp ou netstat -tlnp
  • Processus en cours : ps aux
  • Utilisateurs : cat /etc/passwd

Documentez ce qui est installé et pourquoi. Si personne ne sait pourquoi un service tourne, c’est probablement qu’il n’est pas nécessaire.

Suppression progressive

Ne supprimez pas tout d’un coup. Procédez par étapes :

  1. Identifier les composants candidats à la suppression
  2. Vérifier qu’ils ne sont pas utilisés (logs, monitoring)
  3. Désactiver d’abord, observer pendant quelques jours
  4. Supprimer si aucun impact n’est constaté
  5. Documenter la suppression et sa raison

Automatisation

La minimisation doit être reproductible et vérifiable :

  • Scripts d’installation qui n’installent que le nécessaire
  • Images de base durcies et validées
  • Vérifications automatiques de la conformité (paquets, services, ports)
  • Alertes si un nouveau composant apparaît

Pièges courants

Le minimalisme excessif

Supprimer des composants nécessaires au fonctionnement ou au diagnostic. Un serveur sans outils de debug devient impossible à dépanner. Trouvez l’équilibre entre sécurité et opérabilité.

La dette de documentation

Supprimer des composants sans documenter pourquoi. Six mois plus tard, quelqu’un les réinstalle “parce qu’ils manquaient”.

L’image minimale non maintenue

Créer une image conteneur minimale puis ne jamais la reconstruire. Les vulnérabilités s’accumulent dans les dépendances restantes.

Le faux sentiment de sécurité

Penser que la minimisation suffit. C’est un principe parmi d’autres. Un système minimal mal configuré reste vulnérable.

À retenir

  1. Ce qui n’existe pas ne peut pas être attaqué — chaque composant supplémentaire augmente la surface d’attaque.

  2. Installer uniquement le nécessaire — partir d’une base minimale et ajouter ce dont on a besoin, pas l’inverse.

  3. Désactiver n’est pas supprimer — un binaire présent peut être exploité même si son service est arrêté.

  4. Les images conteneur héritent des problèmes — privilégier Alpine, Distroless ou des builds multi-stage.

  5. Documenter chaque composant — si personne ne sait pourquoi c’est là, c’est probablement inutile.

  6. Automatiser la vérification — la conformité doit être testée, pas supposée.

Liens utiles