Renforcer la sécurité des services systemd (hardening)
(roguesecurity.dev)- systemd fournit de puissantes fonctions de gestion des services, mais sa configuration par défaut est optimisée pour l’utilisabilité plutôt que pour la sécurité, d’où la nécessité d’appliquer des options de hardening dédiées
- La commande
systemd-analyze securitypermet d’analyser les indicateurs d’exposition en matière de sécurité pour l’ensemble des services ou pour un service précis, et d’établir des priorités - Il existe de nombreuses options de sécurité applicables au niveau de l’unité de service, modifiables individuellement via
/etc/systemd/system/ServiceName.service.d/override.confet autres fichiers similaires - Parmi les principales options figurent
ProtectSystem,PrivateTmp,NoNewPrivileges,SystemCallFilter,MemoryDenyWriteExecute, qui limitent les privilèges des processus et l’accès aux ressources - Plutôt que de viser une sécurité parfaite, il est possible de réduire les risques en durcissant en priorité les services exposés vers l’extérieur, avec un effet également très bénéfique dans les environnements self-hosting
Vue d’ensemble de systemd
- systemd propose une approche très aboutie et robuste pour la gestion des services
- Toutefois, ses paramètres par défaut privilégient l’usage immédiat plutôt que la sécurité, et restent donc relativement permissifs
- Ce document présente plusieurs options de renforcement de la sécurité applicables aux unités de service systemd et à podman quadlet, afin de réduire les possibilités de compromission et de limiter l’ampleur des dégâts en cas d’incident
- Il ne s’agit pas d’un guide à appliquer uniformément à tous les services : chaque service exige des tests, une vérification des logs et des ajustements en fonction de ses caractéristiques et de ses besoins
- La responsabilité de la sécurité de l’infrastructure incombe entièrement à l’exploitant ; ce document n’est qu’un outil de référence
Analyse de sécurité de systemd
- La commande
systemd-analyze securitypermet de vérifier l’état de sécurité global des services ou d’analyser la configuration détaillée d’un service donné (par ex.sshd.service)- La sortie inclut l’état des contrôles, le nom de la fonctionnalité, sa description et un score d’exposition ; plus l’Exposure est élevé, plus le risque est important
- Les options de sécurité peuvent être ajoutées dans la section
[Service](systemd) ou[Container](podman quadlet) - Il est recommandé de créer un fichier d’override via
systemctl edit ServiceName.service; en cas d’échec, il faut vérifier puis ajuster les autorisations nécessaires
Options de sécurité des services
- systemd fournit divers mots-clés d’options de sécurité, consultables notamment via
man systemd.exec 5,man capabilities 7, etc. - Options de sécurité représentatives
ProtectSystem→ option qui limite le système de fichiers en lecture seuleProtectHome→ option qui bloque l’accès à/home,/root,/run/userPrivateDevices→ option qui bloque l’accès aux périphériques physiques et n’autorise que les périphériques virtuels comme/dev/nullProtectKernelTunables,ProtectKernelModules,ProtectKernelLogs→ options qui bloquent l’accès aux ressources du noyauNoNewPrivileges→ option qui empêche l’obtention de nouveaux privilèges via setuid/setgid, etc.MemoryDenyWriteExecute→ option qui empêche l’usage simultané de mémoire inscriptible et exécutable ; cela peut poser problème à certains langages avec JITSystemCallFilter→ option qui limite les appels système autorisés ; en cas de violation, le processus peut être terminé ou recevoir un retourEPERM
Description de chaque option
- ProtectSystem : avec le réglage
strict, l’ensemble du système de fichiers est monté en lecture seule ;/dev,/proc,/sysnécessitent des options de protection distinctes - ReadWritePaths : permet de réautoriser l’écriture uniquement sur certains chemins
- ProtectHome : bloque l’accès à
/home,/root,/run/user - PrivateDevices : désactive l’accès aux périphériques physiques et n’autorise que des pseudo-périphériques comme
/dev/null - ProtectKernelTunables : passe
/procet/sysen lecture seule - ProtectControlGroups : n’autorise qu’un accès en lecture seule aux cgroups
- ProtectKernelModules : interdit le chargement explicite de modules du noyau
- ProtectKernelLogs : restreint l’accès au tampon des logs du noyau
- ProtectProc : avec
invisible, masque dans/proc/les processus appartenant à d’autres utilisateurs - ProcSubset : bloque dans
/procle contenu autre que certains éléments liés au PID - NoNewPrivileges : bloque toute nouvelle élévation de privilèges via setuid, setgid ou les capabilities du système de fichiers
- ProtectClock : bloque l’écriture sur l’horloge système/matérielle
- SystemCallArchitectures : avec
native, n’autorise que les syscalls natifs comme x86-64 - RestrictNamespaces : limite les namespaces spécifiques aux conteneurs
- RestrictSUIDSGID : empêche le positionnement des bits setuid et setgid sur les fichiers
- LockPersonality : empêche le changement de domaine d’exécution (utile seulement pour certaines anciennes applications)
- RestrictRealtime : limite l’ordonnancement temps réel (nécessaire uniquement pour certains services spécialisés)
- RestrictAddressFamilies : limite les familles d’adresses socket autorisées (par ex.
AF_INET,AF_INET6,AF_UNIX, etc.) - MemoryDenyWriteExecute : bloque la création de nouvelles zones mémoire à la fois inscriptibles et exécutables (prudence pour les services utilisant du JIT)
- ProtectHostname : interdit l’usage des syscalls
sethostname,setdomainname - SystemCallFilter : permet de définir, service par service, les syscalls autorisés/interdits, avec un filtrage fin
- Les groupes, syscalls individuels et modes autorisation/interdiction peuvent être ajustés
- En cas de violation, il est aussi possible de renvoyer un code d’erreur comme
EPERMau lieu de terminer le processus - La liste complète est disponible via
systemd-analyze syscall-filterouman systemd.exec(5) - Le préfixe
~permet de négativer l’ensemble d’une liste (ex.CapabilityBoundingSet=~CAP_SETUIDetc.)
Processus d’ajustement des restrictions SystemCallFilter
- Avec
auditd, il est possible de consulter les logs pour voir quel syscall a été bloqué lorsqu’un service échoue- Exécuter
sudo ausearch -i -m SECCOMP -ts recent, puis vérifier la valeur du syscall - Il est ensuite possible d’ajouter ce syscall ou le groupe concerné à
SystemCallFilterafin de résoudre le problème progressivement
- Exécuter
Priorités d’application du hardening et conseils d’exploitation
- Il n’est pas nécessaire de tout appliquer à tous les services
- Le modèle de menace et la gestion du risque sont essentiels ; en particulier, les services exposés vers l’extérieur (
httpd,nginx,ssh, etc.) doivent être considérés en priorité - Il est aussi efficace d’appliquer ces mesures de façon préventive aux commandes personnalisées, aux unités timer (remplaçantes de cron), etc.
- Plus un service est simple, plus il est généralement possible d’effectuer des ajustements fins
Checklist : combinaison d’options de sécurité recommandée (priorité d’application initiale)
ProtectSystem=strictPrivateTmp=yesProtectHome=yesouProtectHome=tmpfsProtectClock=yes,ProtectKernelLogs=yes,ProtectKernelModules=yesRestrictSUIDGUID=yesUMask=0077LockPersonality=yesRestrictRealtime=yesMemoryDenyWriteExecute=yesDynamicUser=yesou définirUsersur un utilisateur spécifique autre que root
- Les éléments ci-dessus constituent en général une combinaison utilisable sans presque aucun impact sur le service
- L’ajout d’un filtrage des syscalls (
SystemCallFilter) nécessite en revanche des tests détaillés
Exemple de configuration Traefik
- Il s’agit d’un exemple d’exécution d’un service Traefik conteneurisé avec systemd quadlet, en appliquant de nombreuses options de sécurité
ProtectSystem=full,ProtectHome=yes,SystemCallFilter=@system-service @mount @privileged, etc.CapabilityBoundingSet=~CAP_SETUID CAP_SETPCAPretire certains privilèges spécifiquesRestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK, etc., applique des limitations d’accès réseau
Conclusion
- Les options de hardening de systemd constituent un moyen pratique à garder dans la boîte à outils de tout administrateur système Unix
- Il ne faut pas les considérer comme une solution de sécurité parfaite, mais comme un outil de réduction du risque ; il n’est pas nécessaire d’appliquer indistinctement des réglages de sécurité à tous les services
- Elles peuvent être particulièrement utiles aux administrateurs d’environnements self-hosting pour améliorer nettement leur niveau de sécurité
- En privilégiant la « praticité plutôt que la perfection », il est recommandé de les appliquer au moins partiellement, dans la mesure adaptée au travail et à l’environnement
1 commentaires
Avis Hacker News
Je trouve intéressant qu’on puisse mettre en place un durcissement automatisé des services systemd via du profilage
stracehttps://github.com/desbma/shh
J’ai trouvé une bonne méthode :
ProtectSystem=n’est pas utilisé dans l’exemple, mais avecTemporaryFileSystem=/:ro, BindReadOnly=/usr/bin/binary /lib /lib64 /usr/lib usr/lib64on peut n’inclure que le binaire voulu et les chemins qu’on souhaite laisser en lecture
ProtectSystem=n’est actuellement pas compatible avec ce comportementVoir plus de détails ici
Je pense que cette approche peut poser problème pour les services qui ont besoin d’actions supplémentaires en cas d’erreur, comme l’envoi d’un e-mail
Par rapport à l’article d’hier sur le durcissement de systemd, celui-ci est bien plus réaliste et rempli de bons conseils applicables immédiatement
J’avais essayé de donner des exemples plus concrets dans les commentaires de l’article d’hier, mais l’article d’aujourd’hui organise tout cela de façon bien plus claire et explique comment renforcer rapidement et facilement l’isolation et la sécurité avec systemd
Je trouve que c’est un excellent article
Je laisse aussi celui d’hier en référence
https://us.jlcarveth.dev/post/hardening-systemd.md
https://news.ycombinator.com/item?id=44928504
Sur certains navigateurs, l’accès est tout simplement impossible à cause de l’erreur de certificat
Merci pour le partage
On peut vérifier la sécurité des unités utilisateur systemd en utilisant
systemd-analyzeavec l’option--user(systemd-analyze --user security)J’utilise davantage systemd depuis que j’ai migré des conteneurs vers Podman, et cet outil sera très utile pour améliorer la sécurité des unités systemd et des services de conteneurs
Les anciens scripts init étaient tous différents, donc ce genre de durcissement cohérent était impossible
Je suis arrivé assez tard dans l’écosystème Linux, donc j’ai du mal à imaginer un système sans systemd, et les systèmes sans systemd me paraissaient très peu pratiques à administrer
J’ai récemment découvert l’outil
unshare, qui permet de faire des expériences comme remonter tout/nixen RW sans affecter les autres processusL’ergonomie de systemd est un peu rugueuse, mais honnêtement, pour moi, la seule alternative serait Windows
Je me demande pourquoi les distributions Linux n’activent pas davantage de ces options de sécurité par défaut
Je me demande s’il y a des inconvénients à un durcissement conservateur
Pour beaucoup d’utilisateurs, il y a peut-être simplement trop de réglages et trop de complexité
Si on modifie les réglages de façon trop agressive, on risque de casser des configurations existantes sans le vouloir
Par exemple, si on durcit NetworkManager, il faut vérifier un par un que les connexions IPv4 et IPv6 fonctionnent toujours, que les modes
dns=systemd-resolvedetdns=defaultmarchent correctement, ainsi que l’intégration avec ModemManager et le cellulaire, les plugins openvpn ou cisco anyconnect, les hooks NetworkManager-dispatcher, etc.Il y a aussi la question de savoir combien de mainteneurs de distributions peuvent être certains jusqu’où ils peuvent changer les options d’un paquet sans casser plus de 0,01 % des environnements utilisateurs
Si ces flags sont gérés par la distribution, chaque release upstream apporte en prime des problèmes de compatibilité ; et si c’est upstream qui les définit, la rétrocompatibilité oblige à être encore plus prudent
Cette question ressemble à « pourquoi les distributions n’activent-elles pas par défaut des politiques MAC (comme SELinux) plus strictes ? »
Il serait sans doute préférable de restreindre davantage quelque chose comme
sshd, maisfont que c’est une lourde charge pour les distributions majeures
C’est pareil pour SELinux et AppArmor : beaucoup de mainteneurs jugent que le retour sur investissement est faible
Une autre raison importante est l’absence de moyens ou de ressources pour faire des tests d’intégration, paramètre par paramètre, sur le bon fonctionnement des services système critiques
Discussion connexe
https://news.ycombinator.com/item?id=29995566
Les résultats de
systemd-analyze securitydiffèrent selon les distributionsdesbma/shhgénère automatiquement, à partir de ce qui est collecté parstrace, des règles par unité commeSyscallFilter, un peu à la manière deaudit2allowpour SELinuxMais installer
straceen production peut faire débathttps://github.com/desbma/shh
Je ne sais pas trop non plus, mais certains réglages sont récents, donc beaucoup d’utilisateurs ne les connaissent peut-être pas encore
Il n’y a pas que des experts systemd, et activer certains paramètres peut aussi risquer de ne pas fonctionner correctement sur d’anciennes versions de systemd
Il existe diverses fonctions comme SELinux ou AppArmor, mais beaucoup de distributions, de développeurs et d’utilisateurs ne ressentent tout simplement pas le besoin de les rendre automatiques
Il y a tellement d’options de durcissement que je trouverais utile d’avoir un dépôt regroupant des exemples génériques de durcissement par type de service
Les utilisateurs réutilisent souvent des scripts de durcissement communs, mais on se rend parfois compte qu’il faut au contraire élargir un peu les permissions pour éviter les cas particuliers
nixpkgs,le plus utile est de regarder comment les distributions grand public empaquettent et durcissent les logiciels
Ces méthodes de durcissement sont souvent déjà bien testées ; donc si vous cherchez des exemples, par exemple pour
postgresql, le mieux est de partir des paquets Debian, Ubuntu ou RHELL’une des excellentes fonctions de sécurité offertes par systemd est la gestion des credentials
Cela permet de transmettre des secrets à une application de manière plus sûre qu’en les stockant dans des variables d’environnement ou dans le système de fichiers
Dans des environnements sans Vault, par exemple pour des projets personnels, je préfère toujours cette méthode
J’ai même créé moi-même un package Go qui s’intègre à cette fonctionnalité
credentials dans systemd
package credential-go
J’ai l’impression que c’est un peu la culture nodejs ou npm où même deux lignes de code deviennent un package
En pratique, c’est juste
ce n’est même pas plus compliqué que
left-padIl me semblait qu’au sein de la communauté Go, on valorisait plutôt la réduction des dépendances et l’évitement des abstractions inutiles (comme les appels de fonction)
Ce genre de logique simple, tout le monde l’écrivait normalement directement sur le moment
Je me demande comment ce mode de transmission des credentials empêche l’héritage des secrets par les processus enfants forkés
Article vraiment utile
J’aime aussi la liste des différentes options systemd et les conseils du style « consultez le man et bonne chance »
systemd est vraiment excellent et j’ai envie de le déployer activement sur mes serveurs
Petit détail, mais la graphie correcte est bien
systemddans le titreCe n’est ni
SystemD, nisystem D, nisystem d, mais biensystemdLa raison est que cela vient de « system daemon », conformément à la tradition Unix/Linux qui utilise un
dminuscule en fin de nomJ’ai souvent vu
systemD, et je me demande pourquoi cette forme s’est autant répandueL’astuce pour déboguer les problèmes de syscalls dans systemd est vraiment utile