Touche pas à mon root

Sur les systèmes UNIX et ses dérivés, le compte root est le super-administrateur du système. Il dispose des pleins pouvoirs sur l'ensemble du système. Cet article se concentre sur des façons employées pour sécuriser son accès.

Touche pas à mon root

Introduction

Sur les systèmes UNIX et dérivés, le compte root est historiquement le super-administrateur du système aux pleins pouvoirs sur l'ensemble du système. Son nom root vient d'ailleurs de là (racine en anglais), puisqu'il a les permissions d'altération sur la racine du système (/).

Le root est avant tout un utilisateur comme un autre qui possède généralement l'UID 0 :

# id -u
0

Mais évidemment, root a cette spécificité d'avoir en règle générale les permissions totales sur l'espace utilisateur du système, mais aussi le noyau. Par exemple, c'est seulement root qui peut (par défaut) permettre d'écouter sur des ports inférieurs à 1024.

Si le compte root venait donc à être compromis, c'est game over. En conséquence, il doit être verrouillé, protégé, et ne doit jamais être utilisé directement si possible.

Linux et la sécurité, tel un désert et un oasis ?
On entend souvent que Linux est un OS plus sécurisé que les autres. Mais qu’est-ce que ça veut dire, et est-ce vrai ? Posons-nous un court instant pour vérifier la véracité de cette association en l’an 2021...

Cet article est destiné à détailler la partie relative aux privilèges et de "l'usage dangereux de su et sudo" de l'article ci-dessus.

L'article est destiné à des personnes qui ont déjà des notions de base en matière de système UNIX et UNIX-like : UID, GID, permissions, etc.

L'élévation de privilèges : comment ça marche ?

Il existe différentes façons pour un utilisateur non-privilégié d'obtenir des privilèges normalement réservés à l'utilisateur root. Cette partie servira pour mieux comprendre comment les élévations de privilèges "classiques" fonctionnent (pour su et sudo que nous verrons par la suite).

Par exemple, la commande ping nécessite des fonctionnalités nécessitant des privilèges réservés à root. Comment un système peut-il donc permettre à un utilisateur classique d'utiliser cette commande ?

setuid / setgid

setuid est une propriété qui, si elle est attribuée à un exécutable, permet d'exécuter ce dernier avec les permissions de son utilisateur associé. Ce sont des bits de contrôle d'accès qui sont employés par exemple pour utiliser une commande nécessitant des permissions élevées, comme ping, à condition que l'exécutable soit la propriété de root et qu'il ait la propriété setuid.

setgid fonctionne d'une façon similaire mais avec la notion de groupe !

Il est possible d'attribuer soi-même setuid à n'importe quel fichier :

  • chmod u+s pour ajouter la propriété setuid
  • chmod u-s pour retirer la propriété setuid

La commande suivante permet de lister tous les fichiers du système qui ont la propriété setuid :

find / -type f \( -perm -4000 -o -perm -2000 \)

Il faut faire particulièrement attention aux exécutables avec la propriété setuid, en particulier setuid root. Ne les accordez que si besoin est, et remplacez-les autant que possible par des capabilities (cf. plus bas).

Dans un dossier, vous pouvez déjà le constater avec la commande ls -l. En effet, vous verrez dans la première partie réservée à l'utilisateur la lettre "S" :

# Après chmod u+s
-rwSr--r--    1 root     root            0 Apr 26 15:14 fichier_exemple

# Après chmod u-s
-rw-r--r--    1 root     root            0 Apr 26 15:14 fichier_exemple

Le problème de l'utilisation traditionnelle de setuid c'est que cette façon d'octroyer des privilèges manque de précision et peut être détournée à des fins malicieuses. Imaginez : vous pouvez donc lancer un exécutable en tant que root, mais si cet exécutable venait à être compromis d'une façon ou d'une autre, c'est la catastrophe.

Les capabilities (Linux)

J'écrivais plus haut que l'utilisateur root a traditionnellement les permissions totales : imaginez maintenant que nous prenions ces permissions pour les découper en plusieurs morceaux de privilèges. Vous avez donc compris le principe des capabilities, introduites dès la version 2.2 de Linux, et dont vous trouverez la liste ici (POSIX 1003.e).

Pardonnez l'anglicisme, en français rigoureux on devrait employer le terme de capacité POSIX. Je préfère parler de capabilities car vous trouverez davantage de ressources avec ce terme !

L'idée n'est donc pas d'attribuer les pleins privilèges, mais d'attribuer les privilèges nécessaires uniquement au bon fonctionnement du programme. C'est une façon de faire bien plus robuste et moderne, et qui respecte le principe du moindre privilège.

Parmi les capabilities, nous trouvons par exemple :

  • CAP_NET_BIND_SERVICE : donne le privilège à un exécutable d'écouter sur des ports inférieurs à 1024.
  • CAP_NET_RAW : permet d'ouvrir un socket de type SOCKET_RAW, ce qui permet entre autres à ping de fonctionner (sans setuid root).

Vous pouvez vous amuser avec les capabilities avec le paquet libcap qui fournira les commandes setcap et getcap, dont leur utilité est assez explicite je pense.

# Attribuer une capability
setcap $CAPABILITY+ep /path/to/executable

# Retirer toutes les capabilities
setcap -r /path/to/executable

Le mystérieux suffixe +ep correspond à des sets (à ce jour, il y en a 5) dont (e)ffective, (p)ermitted, et (i)nherited par exemple.

Les capabilities offrent donc un contrôle dit granulaire, et doivent être préférés autant que possible à setuid root. Ils doivent tout de même être utilisés avec parcimonie et dans la mesure du strict nécessaire.

Les user namespaces (Linux)

Nous avons parlé plus généralement das namespaces dans un précédent article, cette fonctionnalité de Linux qui permet de partitionner ses ressources telles que les systèmes de fichier, les UID (user IDs), PID (process IDs) et les processus d'intercommunication.

Parmi ces namespaces il y a donc les user namespaces, introduits dès Linux 3.8 et aujourd'hui arrivés à un stade de maturation jugé suffisant (par Docker par exemple). Cette fonctionnalité permet sur le papier une meilleure isolation des privilèges : un compte root dans une sandbox ne sera ainsi pas le compte root effectif sur l'hôte. C'est une technologie très intéressante dans le cadre des conteneurs où un attaquant aura théoriquement une portée limitée s'il s'échappe d'un conteneur.

Sans aller dans les détails (cela sera le sujet d'un article dédié), vous pouvez tester la fonctionnalité très simplement avec Docker en l'activant dans les paramètres du daemon :

{
    "userns-remap": "default"
}
/etc/docker/daemon.json

Le mode default indique à Docker de préparer pour nous un utilisateur dockremap pour le remapping. Un autre utilisateur peut très bien être configuré par le biais des fichiers /etc/subuid et /etc/subgid.

Dans le conteneur, nous sommes bien root (c'est le cas par défaut avec Docker, mais bien sûr, même sans user namespaces, vous devriez toujours utiliser des utilisateurs non-root dans vos conteneurs) :

container:# whoami
root
container:# sleep 60

Mais sur l'hôte, le processus du conteneur n'est pas root pour autant :

host:# ps -fC sleep
UID 231072 ...

Les user namespaces constituent donc un moyen d'avoir des utilisateurs privilégiés dans un conteneur sans qu'ils ne le soient en dehors du conteneur. Cette technique a des limitations et n'est pas parfaite cependant (je lui préfère l'usage de vraies sandbox comme gVisor ou une VM légère).

Il est également à noter que les user namespaces permettent de facto à des utilisateurs non-privilégiés d'interagir avec du code normalement réservé à root : on peut y voir une surface d'attaque supplémentaire si bien que Debian restreint cette fonctionnalité par précaution.

Les outils user-facing pour l'élévation de privilèges

Nous avons terminé le tour d'une partie relativement théorique mais qui n'en demeure pas moins intéressante à comprendre. Maintenant, il est temps d'aborder par exemple ces questions récurrentes :

Est-ce que je dois utiliser su ou sudo ?
Est-ce que sudo est sûr ?
Comment verrouiller l'accès à root ?

su (substitute user)

La commande su est bien connue de tout utilisateur de système UNIX-like : elle permet d'exécuter une commande ou simplement d'ouvrir un shell en tant qu'un autre utilisateur, le plus souvent (mais pas exclusivement) root. Si vous avez bien lu la partie précédente, vous comprendrez que su nécessite setuid root pour fonctionner.

xkcd.com

L'usage classique de su est donc d'ouvrir un shell avec l'utilisateur root pour mener à bien des opérations en profondeur du système. Ne préciser aucun utilisateur revient à dire que l'on veut se connecter au compte root :

$ su -
Password: _

# echo "I can do whatever the fuck I want"

J'insiste directement sur un point particulier qui concerne le - :

  • su seul ouvre un shell root sans changer l'environnement
  • su - ouvre un shell root avec changement d'environnement

La différence est critique : ce changement permet notamment de rafraîchir la variable d'environnement $PATH qui contient les chemins d'accès vers les exécutables. Outre de ne pas avoir accès à toutes les commandes, vous mettez votre compte root en danger par une contamination possible à partir d'un compte utilisateur dont le $PATH aurait été malicieusement altéré.

Quand bien même vous y feriez très attention, l'usage d'un shell root est fortement déconseillé et va à l'encontre du principe du moindre privilège. Vous n'êtes pas à l'abris d'une faute de frappe qui peut compromettre l'intégrité et/ou la sécurité de votre système, d'une erreur humaine ou autre.

Mais les sysadmins savent ce qu'ils font, laisse-les tranquille.

Ce sont des humains comme tout le monde (à moins que ?) ; à noter que cet article ne leur est pas principalement destiné de toute manière.

sudo (substitute user & do)

La commande sudo est également une façon extrêmement répandue d'éléver ses privilèges. Elle repose aussi sur setuid pour son fonctionnement.

xkcd.com

Par rapport à su, sudo permet un contrôle bien plus précis de "qui peut exécuter telle commande avec tels privilèges", et nous permettra de verrouiller davantage l'accès au compte root. Par défaut, beaucoup de distributions préconfigurent sudo. Une distribution installée de façon minimale ne l'a pas forcément, auquel cas il suffira d'installer le paquet correspondant puis de configurer manuellement.

Il est fortement conseillé d'utiliser visudo pour modifier /etc/sudoers car il vérifiera que le fichier a une syntaxe correcte avant de remplacer la configuration présente. Un utilisateur de confiance pour les tâches d'administration sera ainsi souvent ajouté à un groupe sudo, lequel permet une élévation de privilèges pour n'importe quelle commande (dont l'ouverture d'un shell root) quand il est configuré ainsi dans sudoers :

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL
Le mot de passe de l'utilisateur sera bien sûr exigé par défaut

Il est préférable de définir un groupe sudo et de l'attribuer au cas par cas dans une optique de réduction de la surface d'attaque :

usermod -aG sudo user_de_confiance

Pour vérifier qui sont les membres actuels du groupe sudo :

getent group sudo

Mais ce n'est qu'un exemple minime de la puissance de configuration que propose sudo. Vous pouvez définir certaines commandes seulement que seuls certains utilisateurs/groupes pourront exécuter avec les privilèges élevés, ce qui est une excellente pratique. Je vous réfère à la documentation pour apprendre à configurer précisément sudo.

L'objectif est d'appliquer le principe du moindre privilège !

Un autre avantage de sudo est que toutes ses interactions sont enregistrées dans un historique consultable : c'est un processus auditable et transparent. Il est aussi important à noter que sudo protège par défaut des attaques via $PATH et $LD_PRELOAD, entre autres.

# Debian-based
sudo grep sudo /var/log/auth.log

# RedHat-based
sudo grep sudo /var/log/secure

La commande ci-dessus vous permettra de vérifier les authentifications et les opérations qui ont été menées via sudo (auditd reste une mesure intéressante à mettre en place). D'ailleurs, sudo demande par défaut le mot de passe de l'utilisateur : cela peut être changé (pour rootpw ou targetpw), mais c'est mieux ainsi, car il vaut mieux ne jamais distribuer le mot de passe root de façon centralisée.

Mais sudo c'est pas parfait ! Au fond pourquoi s'embêter avec ?

En effet, quelques articles critiquent (à juste titre d'ailleurs) l'utilisation abusive de sudo. Certains arguments sont justes, mais les alternatives sont assez douteuses. Il faut simplement retenir que sudo :

  • N'est pas une solution magique
  • Doit être configuré selon vos besoins
  • Ne suffit pas à lui seul

Dans un environment sécurisé, une politique de contrôle d'accès restrictive (type SELinux) et auditd seront probablement considérés. La réalité est que sudo est, en dépit des critiques, un des meilleurs moyens de contrôler facilement ce processus d'élévation des privilèges.

Les outils moins connus

doas (do as, littéralement)

doas est un outil conçu par et pour OpenBSD, qui fonctionne dans la même veine que sudo mais qui se veut être bien plus simple et moins compliqué à configurer.

The core of the problem was really that some people like to use sudo to build elaborate sysadmin infrastructures with highly refined sets of permissions and checks and balances. Some people (me) like to use sudo to get a root shell without remembering two passwords. And so there was considerable tension trying to ship a default config that would mostly work with the second group, but not be too permissive for the first group.

- doas - dedicated openbsd application subexecutor (tedunangst.com)

De ce que je comprends, il est de facto moins puissant dans ses possibilités de gérer finement les permissions (il est estimé cela dit que 95% des fonctionnalités sont reproduites). Mais sa simplicité est tout à son honneur, et à l'image d'OpenBSD qui apprécie la réduction de surface d'attaque et de code complexe difficile à maintenir.

gosu / su-exec

gosu et su-exec sont deux outils que vous trouverez de temps en temps, par exemple dans les conteneurs qui ont besoin d'exécuter un code en root à leur démarrage puis de drop ces privileges car ils n'en ont plus besoin par la suite. Ils fonctionnent entre autres également grâce au couple setuid/segid.

Ils sont surtout utilisés pour leur aspect minimal, dans des scripts d'automatisation, entre autres.

Ce sont des implémentations du même concept, seulement gosu est écrit en Go, et su-exec est écrit en C.

chroot

On peut voir chroot (= change root) comme une façon de changer ses privilèges. L'appel système responsable n'est réservé qu'à root de toute façon (par défaut chroot est lancé avec l'utilisateur qui lance la commande, mais un utilisateur peut être précisé avec --userspec).

Recommandations

Maintenant que nous avons vu les différents outils ainsi que leur fonctionnement (à peu près, hein), je propose quelques bonnes pratiques à mettre en place. Le but sera de verrouiller l'accès à root et de manière générale aux pleins privilèges, et de privilégier des accès auditables et granulaires.

Restreindre l'utilisation de su

Nous allons faire en sorte que seuls les utilisateurs du groupe wheel puissent utiliser la commande su. C'est à ma connaissance une pratique commune sur les systèmes BSD, mais certaines distributions Linux n'ont même pas de groupe wheel par défaut, ce qui n'est pas un problème puisque nous pouvons le créer :

groupadd --system wheel
En réalité, le nom est arbitraire, mais c'est une convention

Enfin, ajoutez les utilisateurs de confiance qui pourront accéder à su :

usermod -aG wheel user_de_confiance

Par la suite, deux fichiers seront à modifier :

  • /etc/pam.d/su
  • /etc/pam.d/su-l

Avec l'ajout suivant :

auth required pam_wheel.so use_uid
/etc/pam.d/su et /etc/pam.d/su-l

La surface d'attaque de su est ainsi réduite.

Configurer et utiliser sudo

Je vous réfère à la partie concernant sudo ci-dessus, mais également à l'excellente documentation d'ArchLinux. En résumé :

  • Utilisez sudo au lieu d'ouvrir un shell root avec su
  • Octroyez de façon granulaire les permissions nécessaires
  • ... à des utilisateurs de confiance
  • Dès que possible, contrôlez chaque commande (whitelisting) !
  • Attention au password sniffing (en savoir plus)

C'est d'autant plus important quand vous partagez une machine à plusieurs. Ne négligez pas les situations de catastrophe par facilité.

xkcd.com

N'oubliez pas que sudo peut lire les fichiers dans /etc/sudoers.d, lesquels sont éditables avec visudo -f. Par exemple, voici une entrée pour un utilisateur qui n'aura que le droit d'utiliser apt et reboot :

user ALL=/usr/bin/apt,/usr/sbin/reboot
/etc/sudoers.d/user

Encore une fois, c'est un maigre exemple de ce que vous pouvez faire.

D'ailleurs, vous pouvez exiger systématiquement le mot de passe (par défaut, il y a un timeout de quelques secondes voire minutes après une première entrée correcte) en ajoutant ceci dans /etc/sudoers :

Defaults        timestamp_timeout=0
/etc/sudoers

Libre à vous d'incrémenter ce temps de quelques secondes/minutes si cela est trop inconvénient pour vous : remplacez 0 par un nombre en minutes (avec décimaux pour les secondes) que vous estimez confortable et suffisant. Le but est in fine :

  • D'éviter de finir par lancer un root shell par flemmardise
  • De comprendre qu'une commande privilégiée n'est pas anodine

Pause détente avec ces quelques options esthétiques :

Defaults        insults
Defaults        passprompt="[sudo] Hey %p, type your password: "
/etc/sudoers

Ce qui est assez drôle dans l'histoire, c'est que ces options peuvent vous empêcher d'être victime d'une tentative de password sniffing très basique (les fake sudo écrits en quelques lignes). Bon, reprenons notre sérieux.

Verrouiller l'accès à root (facultatif)

Avertissement : prévoyez un moyen de secours comme par exemple, monter le système de fichiers depuis un autre système en live et chroot dedans. Je ne conseille cette partie qu'à des utilisateurs avertis.

Notes :

  • Certaines distributions (desktop notamment) désactivent déjà le compte root par défaut et préconfigurent votre compte utilisateur de la même façon que ci-dessous avec sudo.
  • Je ne conseille pas particulièrement cette manipulation pour des serveurs à distance. Les mesures précédentes "suffisent".

Une fois sudo configuré pour votre usage, vous pouvez choisir de verrouiller totalement l'accès à root. C'est une mesure radicale qui n'a pas forcément un grand intérêt en réalité (d'autant plus une fois que su et sudo ont été bien configurés), mais elle peut être à considérer.

Pour ce faire, utilisez cette commande pour verrouiller (lock) root :

passwd -l root
Soyez SÛR de l'implication de cette commande

Le fichier /etc/securetty contient toutes les instances de terminal possibles où le login en tant que root est possible. Videz-le pour empêcher ces login directs, mais le même avertissement que ci-dessus est de rigueur :

mv /etc/securetty /etc/securetty.bak
touch /etc/securetty
chmod 600 /etc/securetty
Pareil, soyez sûr que c'est ce que vous voulez

Vous pouvez par exemple réserver les commandes privilégiées à un utilisateur admin, que vous allez créer avec un mot de passe fort :

useradd admin && passwd admin

Puis configurer sudo de cette façon dans un fichier dans /etc/sudoers.d avec bien évidemment visudo -f /etc/sudoers.d/admin-account pour éditer le fichier :

admin ALL=(ALL) ALL
/etc/sudoers.d/admin-account

Utilisez ensuite ce compte avec su - admin ou très préférablement un accès direct en tty avec Secure Attention Key pour y réaliser vos opérations privilégiées avec sudo puis quittez avec exit quand vous n'en avez plus besoin. Vérifiez que seul ce compte ait un accès sudo.

Vous pouvez réutiliser ce concept pour avoir plusieurs utilisateurs privilégiés avec la configuration de votre choix. C'est un exemple, à vous de faire comme bon vous semble.

Les bonnes pratiques

Des mots de passe forts

Grâce à passwd, vous pouvez changer de mot de passe. Privilégiez comme pour tout le reste d'ailleurs des mots de passe à haute entropie pour tous vos utilisateurs (dont root).

Renforcement du hashage

Vous pouvez aller plus loin et forcer l'usage d'un algorithme très robuste comme SHA-512 pour le hashage des mots de passe avec un nombre d'itérations suffisamment grand (65536). Par défaut, ce nombre est à 5000 pour SHA-512 sur les systèmes utilisant glibc.

Pour ce faire, modifiez le fichier /etc/pam.d/passwd et ajoutez cette ligne :

password required pam_unix.so sha512 shadow nullok rounds=65536
/etc/pam.d/passwd

Cette modification ne suffit pas à elle-même proprement dite, il faudra regénérer vos mots de passe avec passwd. Pour vérifier que le changement a été pris en compte, vous pouvez consulter /etc/shadow :

root:$6$rounds=65536$...
/etc/shadow

On constate que :

  • $6 signifie que le hash utilise SHA-512 ($5 = SHA-256).
  • $rounds a été mis à jour et reflète notre changement.

Vous pouvez augmenter ce nombre comme bon vous semble au prix d'un coût en performances au login.

sudoedit

Pour éditer vos fichiers, n'utilisez pas sudo editeur mais sudoedit à la place. Quand vous utilisez sudo editeur vous lancez le programme d'éditeur lui-même en tant que root, et vi par exemple permet d'ouvrir un shell avec :sh, donc ce sera un shell root et l'équivalent d'un su.

sudoedit /etc/iptables.conf

Vous pouvez définir l'éditeur de votre choix avec la variable d'environnement $SUDO_EDITOR.

Dans l'exemple ci-dessus, sudoedit va copier /etc/iptables.conf dans un fichier temporaire que vous allez éditer proprement dit avec vos permissions actuelles. Puis, au moment de sauvegarder, sudoedit utilise les privilèges octroyés pour remplacer le fichier original par le fichier temporaire non-privilégié que vous avez édité.

OpenSSH

Pour les serveurs, une modification est à apporter dans la configuration du daemon OpenSSH pour prohiber le login direct en root :

PermitRootLogin no
/etc/ssh/sshd_config

Dans le cas où vous avez besoin de root pour des tâches particulières (les raisons vous regardent), vous devriez a minima n'autoriser qu'une authentification par clés (sans mot de passe) :

PermitRootLogin prohibit-password
/etc/ssh/sshd_config (OpenSSH 7.0 et ultérieur)

Ce type d'authentification est plus robuste et permet de ne pas distribuer le mot de passe root, ce à quoi sudo était la première réponse.

Xorg (GUI)

Vérifiez dans /etc/X11/Xwrapper.config que Xorg n'utilise pas root :

needs_root_rights = no
/etc/X11/Xwrapper.config

Sinon, une meilleure solution est de laisser Xorg mourir en paix et de passer, je ne sais pas, sur Wayland.

Daemon Docker

Potentiel sujet pour un autre article, je ne dis ici que quelques choses.

Le daemon Docker utilise root. Certains ont la fausse bonne idée de créer un groupe docker et de modifier les permissions du socket Docker pour permettre à ce qu'un utilisateur du groupe docker puisse communiquer avec le socket sans avoir besoin de privilèges.

En faisant ceci, cela revient tout simplement à donner les pleins privilèges à votre utilisateur. Ce dernier pourra lancer un conteneur avec toutes les capabilities qu'il souhaite, voire en mode --privileged, et même monter / dans le conteneur s'il le souhaite.

La bonne pratique est d'éviter cela et d'avoir conscience que quiconque a les droits sur le socket Docker a un accès root sur la machine. Docker n'a jamais été idéal pour partager une machine de travail à plusieurs : son mode rootless ou Podman sont plus adaptés pour cela.

Les conteneurs

J'ai distillé quelques informations à ce sujet ici :

gVisor & Kata : des sandbox pour renforcer l’isolation des conteneurs
Les conteneurs apportent sur le papier un environnement réplicable et léger avec un espace utilisateur isolé, loin de la lourdeur des machines virtuelles. En réalité, l’isolation est une problématique qui doit être considérée de plus près : nous verrons ici des solutions proposées...

En résumé, il y a plein de façons d'éviter l'usage de root dans un conteneur. Parfois, vous avez besoin des privilèges : dans ce cas pensez aux capabilities que vous pouvez utiliser avec Docker : au lieu d'utiliser --privileged, ajoutez les capabilities nécessaires avec --cap-add (et ses équivalents docker-compose).

Linux : lockdown mode

J'en ai parlé ici :

Quelques bricoles pour renforcer Linux : ASLR, lockdown, PTI (Spectre/Meltdown)...
Linux a lui aussi droit à son confinement ! Nous allons voir quelques paramètres non-exhaustifs pour renforcer sa sécurité.

Le mode lockdown restreint les pleins pouvoirs du compte root sur le noyau lui-même. Détails dans l'article !

The kernel can effectively be thought of as the largest, most vulnerable setuid root binary on the system.
- grsecurity - Huawei HKSP Introduces Trivially Exploitable Vulnerability

Linux : no_new_privs

Linux est doté depuis 2012 du mécanisme de sécurité no_new_privs qui, comme son nom le suggère, prévient des élévations de privilèges en agissant sur l'appel système execve() responsable (utilisé par setuid par exemple).

Il peut être utilisé conjointement avec seccomp (filtrage d'appels système), et avec Docker comme avec le flag --security-opt=no-new-privileges que je conseille de systématiquement ajouter à ses conteneurs (non-privilégiés de surcroît), ou directement au niveau du daemon.

Les mises à jour

Il va de soi… non sérieusement, rien que cette année on a eu ça :

CVE-2021-3156: Heap-Based Buffer Overflow in Sudo (Baron Samedit) | Qualys Security Blog
Update Feb 3, 2021: It has been reported that macOS, AIX, and Solaris are also vulnerable to CVE-2021-3156, and that others may also still be vulnerable. Qualys has not independently verified the…

Ce qui ne fait pas de sudo un outil à fuir pour autant :

  • Ces vulnérabilités critiques pendent malheureusement au nez de tout programme écrit dans un langage memory-unsafe (ici en C). Ce n'est qu'une question de temps avant que la prochaine arrive.
  • C'est pour cette raison que vous devez restreindre l'utilisation de sudo à des utilisateurs/groupes de confiance (réduction de surface d'attaque, exposez le moins de programmes sensibles).

Donc restez à jour, c'est important, c'est la première ligne de défense. Si vous voulez des mitigations proactives, il serait intéressant de voir jusqu'à quelle mesure un allocateur renforcé comme hardened_malloc peut protéger des heap overflow comme celle-ci.

Bilan

Merci d'avoir lu jusqu'au bout ! J'espère que cela vous aura été utile pour mieux comprendre et configurer votre système UNIX-like. Bien entendu, les pistes énoncées sont non-exhaustives et sont à compléter avec des documentations bien plus précises et rigoureuses que ce présent article.

Nous avons vu comment restreindre son système, mais ce n'est pas bulletproof ni suffisant. Plus que ça, il faudra adopter de bonnes pratiques, et le but de la première partie de cet article était de faire comprendre plutôt que de taper sur les doigts directement.

Gardez le modèle Zero Trust à l'esprit.

Réflexion

Cet article s'est concentré sur le paradigme classique des distributions GNU/Linux, mais il est par exemple important de constater qu'Android restreint en permanence ses privilèges y compris dans ses phases d'initilisation au démarrage par divers mécanismes. Il n'y a pas donc pas de moyen d'obtenir les pleins privilèges à proprement parler sur Android, sauf modification et utilisation d'un OS modifié qui altère son modèle de sécurité.

Ce paradigme "UNIXien" historique se traduit par la volonté d'avoir le libre accès à tout le fonctionnement de son système. Je pense qu'il est en contradiction avec les notions modernes de sécurité informatique et que la majorité des utilisateurs doit être limitée à ce dont elle a besoin, tout en laissant des possibilités pour d'éventuels power-users.

Les autres systèmes desktop (Windows, macOS qui a une base UNIX d'ailleurs) ont déjà commencé ce travail de longue date, et ces changements qui s'inspirent du modèle de sécurité mobile continuent en profondeur.

N'hésitez pas à me faire part de votre avis sur cette question qui rejoint des interrogations déjà énoncées ici et .