Seccomp Linux limite les applications aux appels système dont elles ont réellement besoin, réduisant ainsi considérablement la surface d'attaque du noyau. J'utilise ce mécanisme de manière ciblée pour isoler les conteneurs, les microservices et les services sensibles dans un Sandbox les verrouiller sans bloquer leurs fonctions essentielles.
Points centraux
Je résume ici les aspects les plus importants pour offrir un aperçu rapide et j'explique comment j'utilise Seccomp dans la pratique. Cela permet une introduction claire aux politiques, aux filtres et à la protection des charges de travail. Ces points me servent de fil conducteur pour la planification, l’exploitation et la vérification. Ils aident à hiérarchiser les risques et à choisir des paramètres par défaut adaptés. En gardant ces éléments clés à l’esprit, la Sécurité compréhensible et maîtrisable.
- Mode de filtrage: Les profils BPF à granularité fine n'autorisent que les appels système nécessaires.
- Surface d'attaque: La réduction du nombre de chemins d'accès au noyau accessible diminue le risque d'exploitation.
- Conteneur: Les profils par défaut bloquent efficacement les appels à risque.
- Kubernetes: « seccompProfile » et « seccompDefault » harmonisent la protection.
- Flux de travail: Analyser, définir le profil, renforcer, tester, déployer.
J'analyse chaque charge de travail, je définis un profil adapté et je vérifie son efficacité en conditions réelles. C'est ainsi que l'on développe une solution robuste Ligne de base- une protection qui pourra être étendue de manière ciblée ultérieurement.
Seccomp en bref : mode de calcul sécurisé
Seccomp signifie „ Secure Computing Mode “ et limite Appels système d'un processus à un ensemble clairement défini. J'applique ce filtre là où les applications interagissent avec le noyau, par exemple lors de l'ouverture de fichiers, de sockets ou lors de la création d'autres processus. L’idée est simple : autoriser ce qui est nécessaire et bloquer ce qui ne l’est pas à l’aide d’un code d’erreur ou d’une commande « kill ». Quiconque comprend l’interaction avec le noyau peut rapidement créer des profils solides ; l’article suivant constitue un bon point de départ : Comprendre les appels système. C'est ainsi que l'on obtient une Sandbox, ce qui complique les échappements et bloque les chemins d'accès indésirables au noyau.
Pourquoi Seccomp réduit la surface d'attaque sous Linux
Chaque appel système supplémentaire augmente potentiellement la Surface d'attaque. Je réduis cette surface d'attaque en n'autorisant que les appels système dont l'utilisation par l'application est avérée. De ce fait, de nombreuses chaînes d'exploitation perdent l'accès aux fonctions critiques du noyau. Même en cas d’exécution de code au sein du processus, un attaquant se heurte souvent à des portes closes. C’est ainsi que j’empêche l’accès à des sous-systèmes sensibles tels que ptrace, BPF ou certaines interfaces de débogage.
Une liste blanche plutôt qu'une liste noire : la bonne stratégie
Dans les environnements de production, je mise sur Liste blanche: L'action par défaut est „ interdire “, et seul un ensemble d'appels système soigneusement sélectionné est autorisé. Pour des raisons de compatibilité, de nombreux environnements d'exécution fournissent des profils de listes noires qui ne bloquent que les appels particulièrement risqués. Pour les services sensibles, je resserre la vis et n’autorise que ce que l’analyse d’exécution montre réellement. Cela réduit les surprises lors des modifications du noyau et fait passer le contrôle de la question „ Qu’est-ce qui est dangereux ? “ à celle de „ Qu’est-ce qui est nécessaire ? “. Pour les charges de travail génériques, une liste de blocage solide peut constituer un bon point de départ, mais pour les passerelles, les flux de paiement ou les services d’authentification, il vaut la peine de passer à une politique de liste d’autorisation avec des exceptions explicites.
Modes et logique de filtrage : de « strict » à « BPF »
Seccomp dispose d'un mode strict qui n'autorise que les commandes read, write, exit et sigreturn, ainsi que le mode hautement flexible Mode de filtrage via BPF. Dans la pratique, j'utilise presque toujours des filtres, car cela me permet d'analyser en détail les appels système et leurs arguments. Le noyau vérifie chaque appel par rapport au programme enregistré et décide s’il est autorisé, s’il renvoie une erreur ou s’il met fin au processus. Je peux ainsi bloquer certaines variantes d’un appel système, par exemple des indicateurs spécifiques de clone ou d’unshare. Cette granularité permet Politiques à la fois sobre et efficace.
Opérations de restitution et niveau de contrôle
Je gère de manière ciblée le comportement en cas d'infractions à l'aide d'actions : autoriser, erreurs définies (généralement EPERM ou EACCES) renvoyer, via TRAP déclencher un signal, avec TRACE Activer le débogage ou mettre fin de manière systématique au processus/thread. Le simple renvoi d'une erreur est souvent suffisant et améliore la tolérance aux pannes ; en revanche, pour les chemins particulièrement sensibles, j'utilise des actions de force d'arrêt. Lorsque j’ai besoin d’un diagnostic, j’utilise la journalisation du noyau ou des actions avec journalisation pour affiner progressivement le profil dans les environnements de préproduction, sans perturber inutilement le fonctionnement.
Le sandboxing et la protection par conteneurs dans la pratique
Les environnements d'exécution de conteneurs offrent des solutions éprouvées Défaut- des profils qui bloquent les appels système à risque. Je pars de là pour restreindre davantage les fonctions `mount`, `unshare`, `bpf`, `ptrace`, ainsi que `keyctl` et `perf_event_open`. Les applications qui traitent des données d’entrée non fiables en tirent un double avantage : une interface avec le noyau réduite et des cas d’erreur clairement identifiables en cas de violation. Même les navigateurs Web et les outils de sandbox s’appuient sur cette séparation entre les accès nécessaires et ceux qui présentent un danger. Ainsi, le système d’exécution reste gérable et prévisible.
Notification dans l'espace utilisateur : exceptions contrôlées
Pour les exceptions rares, mais légitimes, j'utilise le Notificateur en espace utilisateur-Approche : un processus de surveillance reçoit les demandes concernant les appels système bloqués et peut les autoriser ou les refuser de manière ciblée. Je reproduis ainsi des modèles de courtier, par exemple pour n'autoriser que certains monter- Autoriser les opérations dans des répertoires définis. Cela réduit la nécessité d'intégrer des exceptions générales dans la politique, tout en préservant la flexibilité opérationnelle. Une gouvernance claire est ici essentielle : quelles commandes sont autorisées, comment sont-elles contrôlées et comment éviter que le système de notification ne devienne lui-même un point de défaillance unique ?
Seccomp dans Kubernetes et OpenShift
Dans Kubernetes, je définis dans le manifeste du pod, via le SecurityContext, quel profil est actif. Le profil « seccompDefault » sur le nœud garantit que les charges de travail pour lesquelles aucun profil n’est spécifié se voient directement attribuer un profil approprié. Standard-profil. OpenShift et Podman intègrent également cette fonctionnalité, y compris le transfert via l'option –security-opt. Je peux déployer les profils de manière centralisée et les associer via une annotation ou un lien de champ. De cette manière, j'établis des règles claires pour l'ensemble des Espaces de nommage sur le sujet.
Conception de politiques pour les équipes et les plateformes
Je classe les profils selon Classes de charge de travail plutôt que par équipes : interfaces Web, workers, clients de base de données, pipelines de données. Chaque classe reçoit un profil testé, que je ne complète que très légèrement pour les cas particuliers. Dans Kubernetes, j'utilise une politique d'admission pour m'assurer que les pods ont au moins RuntimeDefault utiliser, tandis que les espaces de noms particulièrement sensibles nécessitent une Localhost- Imposer le profil. Pour les situations de débogage ou d'incident, il existe une procédure d'exception clairement définie, assortie d'une durée de validité limitée et d'une réduction supplémentaire des capacités réseau et des fonctionnalités, afin de permettre le diagnostic sans abaisser de manière générale le niveau de sécurité.
Création de profils : processus de l'analyse au déploiement
Je commence par une analyse des durées d'exécution et j'observe quelles Appels système que l'application utilise en fonctionnement normal. Je définis ensuite un profil initial qui autorise précisément ces appels et exclut les chemins d'accès peu fréquents. Je procède ensuite à un durcissement supplémentaire en supprimant les appels rares ou risqués, ou en les restreignant davantage. Une phase de test permet de détecter les lacunes et de déterminer si des fonctionnalités manquent ou si des codes d'erreur sont pertinents. Ce n'est qu'ensuite que je déploie la Politique en production et je gère les versions de chaque modification.
Aspects liés à l'architecture et au baccalauréat
Les appels système varient en fonction de l'architecture et de la génération du noyau. Je veille à ce que les profils Multi-Arch couvrent bien toutes les architectures (par exemple x86_64 et arm64) et que les variantes plus récentes telles que openat2 ou si les appels système time64 sont pris en compte. Dans les conteneurs utilisant des systèmes de base plus anciens, je vérifie si les chemins hérités (par exemple via socketcall ou certains appels IPC). Ceux qui libseccomp ou utilise le runtime pour la génération, bénéficie de correspondances stables entre les noms de symboles et les numéros d'appels système – je renonce délibérément à utiliser des numéros fixes afin de préserver la portabilité. Important : les filtres sont héréditaire et seulement monotone pouvant être renforcé ; ce qui est interdit une fois le reste interdit, même après execve.
Gestion des mises à niveau et de la compatibilité
Les mises à jour des bibliothèques et du noyau introduisent de nouveaux appels système ou modifient les schémas d'appel. Je prévois donc de procéder à des Tests de fumée après les mises à jour et je dispose d'un environnement de test qui, en cas de doute, peut être utilisé avec LOG-actions. Cela me permet de voir les nouvelles demandes avant de valider la mise en production. De plus, je documente délibérément les différences entre les images (par exemple, les conteneurs basés sur musl par rapport à ceux basés sur glibc), car celles-ci peuvent emprunter des chemins différents vers l'API du noyau. Pour les retours en arrière, une gestion claire des versions des profils est essentielle ; en cas d’incident, je passe temporairement à une politique moins stricte, avec une durée d’expiration courte et une surveillance étroite.
Identifier les types d'erreurs : journalisation et triage
Les appels système bloqués doivent pouvoir être identifiés, sinon on avance à l'aveuglette dans le Dans le noir. J'active la journalisation au niveau du runtime et j'analyse les métriques qui révèlent des pics et des valeurs aberrantes. Les messages contenant EPERM ou EACCES indiquent souvent que les règles sont trop restrictives. J’attribue les arrêts inattendus au composant concerné et je vérifie les indicateurs ou arguments correspondants. Ensuite, j’ajuste les Filtre Réglez-le au minimum et refaites un test.
Playbook de dépannage
- Reproduire: reproduire exactement le même flux de données et corréler les journaux.
- Identifier: enregistrer l'appel système concerné avec ses arguments (par exemple via le journal d'exécution ou les sorties d'audit).
- Évaluer: Cet appel est-il nécessaire ? Existe-t-il une alternative présentant moins de risques (par exemple, « openat » au lieu de « open », des indicateurs plus spécifiques) ?
- Personnaliser: autoriser le minimum, de préférence avec des filtres d'arguments ; laisser l'action par défaut sur « stricte ».
- Se protéger: pour les exceptions délicates, renforcer également la réduction des capacités, le système de fichiers en lecture seule ou les espaces de noms.
- Nouveau test et télémétrie: après la correction, effectuer des tests ciblés, surveiller les indicateurs et configurer des alertes.
Comparaison avec SELinux, AppArmor et les capacités
Seccomp intervient au niveau de l'interface entre l'application et le noyau, tandis que SELinux et AppArmor régulent principalement les accès aux objets. Les capacités contrôlent les opérations privilégiées, que je réduis par ailleurs considérablement. En combinaison avec Espaces de noms et Cgroups On obtient ainsi une stratégie de protection à plusieurs niveaux. Je sépare les ressources, je supprime les privilèges inutiles et je limite les chemins d'accès au noyau via Seccomp. Cette combinaison permet de maintenir les charges de travail bien encadrées et faciles à contrôler.
Performances et surcharge
Un profil Seccomp bien conçu n'entraîne qu'une faible Overhead: Le noyau vérifie un petit programme BPF pour chaque appel système. Dans la pratique, cela n'a pratiquement aucun impact mesurable sur les charges de travail Web et de services courantes. Les chemins à haute fréquence et à forte intensité d'appels système (par exemple, le traitement des paquets, les processus IPC très actifs) peuvent toutefois devenir critiques. Je veille donc à limiter le nombre de règles, j’utilise des filtres d’arguments plutôt que de longues listes et je teste les chemins critiques à l’aide de benchmarks. Si un profil entraîne un ralentissement mesurable, je vérifie d’abord s’il y a des doublons, des correspondances imprécises et si certains appels rares peuvent être déportés vers un processus distinct.
Bonnes pratiques pour des paramètres par défaut sécurisés
Je commence par le profil par défaut du Runtime, puis je l'affine en fonction de Charge de travail. Les services hautement sensibles, tels que les passerelles ou les services d'authentification, sont soumis à des règles particulièrement strictes. J'intègre les modifications apportées aux profils dans le processus CI/CD et je les teste automatiquement. Je recommande en outre une forte réduction des capacités, des systèmes de fichiers en lecture seule et l’application de la politique « NoNewPrivs ». Vous trouverez un guide sur les mécanismes globaux de protection des hôtes à l’adresse suivante : Renforcement du noyau, qui se combine bien avec Seccomp.
Durcissement avancé : ce que je vérifie en plus
Outre les habituels suspects (monter, ne plus partager, bpf, ptrace, keyctl, perf_event_open) j'examine les requêtes suivantes et, selon le contexte, je les limite considérablement ou je les bloque complètement :
- setns: empêche le passage vers d'autres espaces de noms.
- process_vm_readv/process_vm_writev: empêche l'accès direct à la mémoire d'autres processus.
- kexec_load et redémarrage: protègent contre les tentatives de redémarrage ou de remplacement du noyau.
- swapon/swapoff et init_module/finit_module: limitent les mécanismes de chargement du système et des modules.
- clone3 avec des indicateurs à risque (par exemple, les espaces de noms) : limiter de manière granulaire via des arguments.
- io_uring_setup: à autoriser ou à limiter strictement en fonction de la charge de travail, car il s'agit d'une interface puissante.
La règle d'or est la suivante : autant que nécessaire, aussi peu que possible – et mieux vaut une petite exception documentée qu'une règle standard trop large.
Intégration dans CI/CD et Teams
Je traite les profils Seccomp comme Code: gestion des versions, révision, tests. Les tâches du pipeline vérifient si les profils correspondent à l’image et s’il y a des blocages. Les tests de fumée avec des données de test détectent plus rapidement les changements de comportement que les clics manuels. Les développeurs reçoivent un petit guide expliquant comment fonctionne la journalisation et où ils peuvent adapter les signatures. C’est ainsi que la Sécurité directement intégré au processus de développement et reste à jour.
En bref
Seccomp limite la Appels système en limitant l'application au strict nécessaire, ce qui élimine ainsi de nombreuses voies d'attaque. Je commence par une configuration par défaut robuste, j'évalue le comportement réel, puis je restreins progressivement l'accès. Les plateformes de conteneurs telles que Kubernetes ou OpenShift me déchargent d'une grande partie du travail de base lorsque je définis « seccompDefault » et que je déploie les profils de manière centralisée. Combinée aux capacités (capabilities), à SELinux/AppArmor ainsi qu’aux espaces de noms (namespaces) et aux groupes de contrôle (cgroups), cette approche offre une protection multiple efficace. En suivant cette approche de manière cohérente, on réduit le risque d’exploits du noyau tout en assurant une bonne protection des charges de travail. contrôlable.


