Sécurité et isolation¶
systemd offre de nombreuses fonctionnalités de sécurité pour isoler et restreindre les services. Cette section couvre le sandboxing, les capacités Linux, les namespaces et la limitation d'accès aux ressources.
Principe de moindre privilège¶
Chaque service devrait avoir uniquement les permissions nécessaires à son fonctionnement, rien de plus.
Configuration minimale sécurisée¶
[Service]
# Utilisateur dédié
User=myapp
Group=myapp
DynamicUser=yes
# Pas de nouveaux privilèges
NoNewPrivileges=yes
# Isolation basique
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
# Chemins en lecture seule
ReadOnlyPaths=/
ReadWritePaths=/var/lib/myapp
Utilisateurs et groupes¶
Utilisateur statique¶
Utilisateur dynamique¶
Création automatique d'un utilisateur éphémère :
Avantages :
- Pas de pré-création nécessaire
- UID/GID aléatoires
- Nettoyage automatique
- Sécurité renforcée
Groupes supplémentaires¶
Isolation du système de fichiers¶
ProtectSystem¶
Contrôle l'accès en écriture au système :
[Service]
# Niveau de protection
ProtectSystem=no # Aucune protection
ProtectSystem=yes # /usr et /boot en lecture seule
ProtectSystem=full # + /etc en lecture seule
ProtectSystem=strict # Tout en lecture seule
strict est le plus sécurisé. Nécessite de définir explicitement les chemins écritables.
ProtectHome¶
Restreint l'accès aux répertoires home :
[Service]
ProtectHome=no # Accès complet
ProtectHome=yes # /home, /root, /run/user inaccessibles
ProtectHome=read-only # Accès en lecture seule
ProtectHome=tmpfs # Monté en tmpfs vide
PrivateTmp¶
Isole /tmp et /var/tmp :
Crée un namespace /tmp unique pour le service.
ReadOnlyPaths / ReadWritePaths¶
Contrôle fin des accès :
[Service]
# Tout en lecture seule
ReadOnlyPaths=/
# Sauf ces chemins
ReadWritePaths=/var/lib/myapp
ReadWritePaths=/var/log/myapp
ReadWritePaths=/run/myapp
InaccessiblePaths¶
Rend des chemins complètement inaccessibles :
TemporaryFileSystem¶
Monte un tmpfs à un emplacement :
Répertoires gérés¶
systemd peut créer et gérer automatiquement des répertoires :
[Service]
# Création automatique avec bonnes permissions
StateDirectory=myapp # /var/lib/myapp
CacheDirectory=myapp # /var/cache/myapp
LogsDirectory=myapp # /var/log/myapp
ConfigurationDirectory=myapp # /etc/myapp
RuntimeDirectory=myapp # /run/myapp
# Permissions
StateDirectoryMode=0750
CacheDirectoryMode=0750
# Nettoyage automatique
RuntimeDirectoryPreserve=no # Supprimé à l'arrêt
Isolation réseau¶
PrivateNetwork¶
Isole complètement du réseau :
Le service n'a accès qu'à l'interface loopback.
RestrictAddressFamilies¶
Limite les types de sockets :
[Service]
# Autoriser seulement IPv4 et IPv6
RestrictAddressFamilies=AF_INET AF_INET6
# Autoriser seulement Unix sockets
RestrictAddressFamilies=AF_UNIX
# Bloquer tout
RestrictAddressFamilies=none
IPAddressAllow / IPAddressDeny¶
Filterage par IP (nécessite cgroups v2) :
[Service]
# Autoriser seulement certaines IPs
IPAddressAllow=10.0.0.0/8 192.168.1.0/24
IPAddressDeny=any
# Ou bloquer certaines IPs
IPAddressDeny=192.168.1.100
Capacités Linux¶
Les capacités décomposent les privilèges root en permissions granulaires.
Supprimer toutes les capacités¶
Autoriser des capacités spécifiques¶
[Service]
# Bind sur ports < 1024
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
Capacités courantes¶
- CAP_NET_BIND_SERVICE : Bind ports < 1024
- CAP_NET_RAW : Sockets raw (ping)
- CAP_NET_ADMIN : Configuration réseau
- CAP_SYS_ADMIN : Opérations système (mount, etc.)
- CAP_SYS_TIME : Modifier l'horloge système
- CAP_DAC_OVERRIDE : Outrepasser permissions fichiers
- CAP_CHOWN : Changer propriétaire fichiers
Exemple : serveur web¶
[Service]
User=www-data
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
Permet de binder sur le port 80/443 sans être root.
Systèmes d'appel (seccomp)¶
Bloquer les syscalls dangereux avec seccomp :
Profils prédéfinis¶
[Service]
# Bloquer tous sauf liste blanche
SystemCallFilter=@system-service
# Bloquer syscalls dangereux
SystemCallFilter=~@privileged @resources @obsolete
Groupes de syscalls¶
- @system-service : Liste blanche pour services
- @privileged : Syscalls privilégiés
- @resources : Modification ressources
- @obsolete : Syscalls obsolètes
- @debug : Débogage (ptrace, etc.)
- @mount : Montage systèmes de fichiers
- @swap : Gestion swap
- @reboot : Redémarrage
- @module : Chargement modules noyau
- @raw-io : I/O brut
Exemple : service web sécurisé¶
[Service]
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources @obsolete @debug
SystemCallErrorNumber=EPERM
Bloquer des syscalls spécifiques¶
Limitations diverses¶
NoNewPrivileges¶
Empêche l'obtention de nouveaux privilèges :
Bloquer setuid, setgid, file capabilities.
ProtectKernelTunables¶
Protège /proc/sys, /sys en lecture seule :
ProtectKernelModules¶
Empêche le chargement de modules noyau :
ProtectControlGroups¶
Protège la hiérarchie cgroups :
ProtectKernelLogs¶
Bloquer l'accès aux logs noyau :
ProtectHostname¶
Empêche la modification du hostname :
ProtectClock¶
Empêche la modification de l'horloge :
ProtectProc¶
Masque les informations /proc :
[Service]
ProtectProc=invisible # Masquer les autres processus
ProtectProc=noaccess # Bloquer accès /proc
ProcSubset¶
Limiter le contenu de /proc :
PrivateDevices¶
Isole /dev :
Accès seulement à /dev/null, /dev/zero, /dev/urandom.
PrivateUsers¶
Namespace utilisateur :
Map UID/GID du service vers des IDs non-privilégiés.
PrivateIPC¶
Isole IPC (shared memory, semaphores) :
Restriction d'exécution¶
LockPersonality¶
Empêche changement de personnalité :
MemoryDenyWriteExecute¶
Bloquer W^X (write XOR execute) :
Empêche les pages mémoire à la fois écritables et exécutables.
RestrictRealtime¶
Bloquer le scheduling temps réel :
RestrictSUIDSGID¶
Bloquer création fichiers SUID/SGID :
RestrictNamespaces¶
Limiter création de namespaces :
Exemple : Service ultra-sécurisé¶
[Unit]
Description=Highly Secured Service
[Service]
# Utilisateur
DynamicUser=yes
User=myapp
# Pas de privilèges
NoNewPrivileges=yes
CapabilityBoundingSet=
AmbientCapabilities=
# Isolation système de fichiers
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadOnlyPaths=/
ReadWritePaths=/var/lib/myapp
InaccessiblePaths=/home /root
# Répertoires gérés
StateDirectory=myapp
CacheDirectory=myapp
LogsDirectory=myapp
StateDirectoryMode=0700
# Isolation réseau
PrivateNetwork=yes
RestrictAddressFamilies=AF_UNIX
# Protection noyau
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectHostname=yes
ProtectClock=yes
# Isolation proc et devices
ProtectProc=invisible
ProcSubset=pid
PrivateDevices=yes
PrivateUsers=yes
PrivateIPC=yes
# Restrictions exécution
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
RestrictNamespaces=yes
# Seccomp
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources @obsolete @debug
SystemCallErrorNumber=EPERM
# Limites ressources
MemoryMax=512M
TasksMax=100
[Install]
WantedBy=multi-user.target
Audit de sécurité¶
Analyser la sécurité d'un service¶
# Score de sécurité (systemd >= 248)
systemd-analyze security myapp.service
# Détails
systemd-analyze security --no-pager myapp.service
# Seulement les warnings
systemd-analyze security myapp.service | grep -E 'WARN|UNSAFE'
Vérifier les capacités¶
# Capacités d'un service
systemctl show myapp.service -p CapabilityBoundingSet
systemctl show myapp.service -p AmbientCapabilities
Vérifier les protections actives¶
Bonnes pratiques¶
- Toujours utiliser NoNewPrivileges
- Privilèges minimaux
- Isolation maximale
- Utilisateurs dédiés
- Bloquer syscalls dangereux
- Auditer régulièrement
- Tester après changements
La sécurité systemd permet de créer des services robustes et isolés, réduisant considérablement la surface d'attaque.