Isolation d'environnements (chroot)

Magazine
Marque
Linux Pratique
Numéro
87
|
Mois de parution
janvier 2015
|
Domaines


Résumé
Cet article propose deux techniques de base permettant de cloisonner une machine Ubuntu/Debian (transposables sur d'autres distributions). À titre d'exemple, nous utiliserons ces techniques pour créer un hébergement cloisonné de sites web. Ceux-ci pourront être mis à jour par des utilisateurs distants en accès console (SSH). D'autres techniques d'isolation d'environnement existent, telles que l'utilisation de container LXC, mais ne seront pas abordées dans cet article.

Body

1. Principe de base de l'isolation d'environnements « chrootés »

Dans les systèmes d'exploitation UNIX, chroot est une commande servant à changer le répertoire racine d'un processus de la machine hôte. La commande permet alors d'isoler l'exécution d'un programme dans un environnement limité, sans accès au système complet. Par analogie, on peut voir chroot comme un coffre-fort à l'intérieur d'une banque ; quelqu'un enfermé dans ce coffre-fort ne peut accéder au reste de la banque (sauf s'il s'appelle Harry Houdini, mais nous nous égarons...).

2. Utilisation du chroot pré-intégré à OpenSSH

Depuis sa version 4.9, OpenSSH offre directement un chroot sur SFTP (SSH File Transfert Protocol). Cette version d'OpenSSH est disponible dans les dépôts depuis Ubuntu 9.10 et Debian 5. Les différentes commandes décrites ci-après sont saisies côté serveur distant.

Étape 1 : Préparation de l'environnement

1) Installation d'OpenSSH

Commençons par installer OpenSSH (si ce n'est déjà fait).

% sudo apt-get update ; sudo apt-get install openssh

Nous pouvons vérifier la version d'OpenSSH par la commande suivante :

% ssh -V

OpenSSH_6.0p1 Debian-4+deb7u1, OpenSSL 1.0.1e 11 Feb 2013

2) Choix et préparation de l'environnement utilisateur

Nous devons définir un dossier de base qui accueillera les homes (environnements isolés) de chaque utilisateur. Pour des raisons de facilité, nous placerons les différents environnements dans /home. Rien ne vous empêche de définir un autre dossier de base, que vous pouvez créer n'importe où :

% sudo mkdir -p /VOTRE_CHEMIN

Nous allons également créer un groupe qui rassemblera les utilisateurs SFTP et que nous appellerons (par exemple) sftpusers :

% sudo groupadd sftpusers

Étape 2 : Configuration

Les étapes préliminaires terminées, nous pouvons attaquer la configuration.

1) Configuration d'OpenSSH

La configuration du serveur OpenSSH se fait par le biais du fichier de configuration /etc/ssh/sshd_config. Nous allons commencer par remplacer le mode de gestion SFTP par défaut par le mode interne à SSH :

# Subsystem sftp /usr/lib/openssh/sftp-server

Subsystem       sftp    internal-sftp

Juste après cette section, nous allons définir les utilisateurs pour lesquels va s'appliquer ce mode de gestion :

Match Group sftpusers

      ChrootDirectory /home/%u

      ForceCommand  internal-sftp

      AllowTCPForwarding no

      X11Forwarding no

Vous pourriez de la même façon définir un pattern par utilisateur plutôt que par groupe, avec la syntaxe Match User NOM_DU_USER. Bien entendu, il faudra remplacer /home par tout autre dossier de base que vous auriez choisi au point précédent.

2) Création de compte utilisateur

Il ne reste plus qu'à créer des utilisateurs :

% sudo useradd -m -g sftpusers NOM_UTILISATEUR

% sudo passwd NOM_UTILISATEUR

Entrez le nouveau mot de passe UNIX : MDP_UILISATEUR

NOM_UTILISATEUR et MDP_UTILISATEUR doivent évidemment être remplacés par le nom et mot de passe de votre utilisateur. À noter qu'il faut ajouter l'argument -d /VOTRE_CHEMIN si vous n'utilisez pas /home comme dossier de base.

3) Validation de fonctionnement et configurations spécifiques

À ce niveau, vous pouvez déjà essayer depuis un poste client :

% sftp NOM_UTILISATEUR@SERVEUR_DISTANT

NOM_UTILISATEUR@SERVEUR_DISTANT's password:

Connection closed

Vous aurez alors un message d'erreur du type : « Connection closed, Error code 255, ... ». Il s'agit d'une sécurité incluse dans OpenSSH. En faisant un petit tour dans la manpage de sshd_config, nous noterons la description suivante :

ChrootDirectory

Specifies the pathname of a directory to chroot(2) to after authentication. All components of the pathname must be root-owned directories that are not writable by any other user or group. After the chroot, sshd(8) changes the working directory to the user's home directory.

La solution consiste à changer le propriétaire et les droits du dossier utilisateur :

% sudo chown root:root /home/NOM_UTILISATEUR

% sudo chmod o-w /home/NOM_UTILISATEUR

Réessayons de nous connecter depuis le client :

% sftp NOM_UTILISATEUR@SERVEUR_DISTANT

NOM_UTILISATEUR@SERVEUR_DISTANT's password:

Connected to SERVEUR_DISTANT.

sftp>

Parfait, ça fonctionne. Mais est-ce suffisant ? Essayons de vérifier que nous disposons bien d'un accès en écriture à l'environnement :

sftp> mkdir test

Couldn't create directory: Permission denied  

Comme indiqué précédemment, le premier niveau du dossier « chrooté » doit appartenir à root et ne doit pas être accessible en écriture aux autres utilisateurs. Donc, au niveau du principe de fonctionnement, il faut ajouter un sous-dossier qui, cette fois, appartiendra à l'utilisateur. Pour notre exemple, soit un dossier www :

% sudo mkdir /home/NOM_UTILISATEUR/www

% sudo chown NOM_UTILISATEUR /home/NOM_UTILISATEUR/www

Il ne nous reste plus qu'à valider que tout fonctionne correctement. Depuis le poste client :

% sftp NOM_UTILISATEUR@SERVEUR_DISTANT

NOM_UTILISATEUR@SERVEUR_DISTANT's password:

Connected to SERVEUR_DISTANT.

sftp> cd www

sftp> mkdir test

sftp> ls

test

sftp>

Maintenant, qu'en est-il de la connexion SSH normale ? Tentons de nous connecter en SSH simple :

% ssh NOM_UTILISATEUR@SERVEUR_DISTANT

NOM_UTILISATEUR@SERVEUR_DISTANT's password:

This service allows sftp connections only.

Connection to SERVEUR_DISTANT closed.

Nous venons donc de mettre en place un environnement isolé pour un utilisateur ! Vous pouvez répéter cette procédure pour chaque nouvel utilisateur.

3. Utilisation d'un chroot externe à OpenSSH

La simplicité de la solution précédente peut être intéressante s'il ne s'agit que de transferts de fichiers et d'opérations simples (renommage, déplacement…), mais nous pouvons être rapidement limités par les commandes disponibles. La solution alors, est de ne pas utiliser la commande chroot intégrée à OpenSSH, mais d'utiliser le chroot système.

Nous supposons que les différentes commandes décrites ci-après se font côté serveur distant. Par ailleurs, cette solution est indépendante de la solution précédente.

Étape 1 : Préparation de l'environnement

On commence par installer OpenSSH, comme dans la première partie. De même, on définit le répertoire qui accueillera les environnements isolés, puis un groupe d'utilisateurs (chrootusers ici).

Étape 2 : Configuration

1) Configuration de OpenSSH

Dans le fichier /etc/ssh/sshd_config, on ajoute une section pour définir les utilisateurs auxquels va s'appliquer ce mode de gestion :

Match Group chrootusers

      ChrootDirectory /home/%u

      AllowTCPForwarding no

      X11Forwarding no

À nouveau, il est possible de définir un pattern par utilisateur avec Match User NOM_DU_USER.

2) Création de compte utilisateur

% sudo useradd -m -g chrootusers NOM_UTILISATEUR

% sudo passwd NOM_UTILISATEUR

Entrez le nouveau mot de passe UNIX : MDP_UILISATEUR

Ici encore, n'oubliez pas d'ajouter l'argument -d /VOTRE_CHEMIN si vous n'utilisez pas /home comme dossier de base.

3) Génération de l'environnement restreint

Durant cette étape, nous allons générer une cage (jail) pour l'utilisateur. Cette dernière inclura les programmes et commandes que notre utilisateur aura le droit d'utiliser. Afin de simplifier les différentes opérations nécessaires à la génération de l'environnement restreint, nous allons commencer par créer un script de génération, que nous appellerons genJail.bash. Devant la complexité de ce script, nous allons le détailler partie par partie.

Pour commencer, déclarons nos variables d'environnement :

mag01

Dans APPS, nous déclarerons le chemin complet vers toutes les commandes que nous souhaitons accorder à l'utilisateur, séparées par un espace.

Nous allons à présent créer la structure de base du dossier utilisateur :

mag02

Ici, nous avons créé l'arborescence de base et généré les pseudo devices null et zero, utilisables directement par l'utilisateur dans sa cage et utilisés par nombre de commandes Linux. De nombreuses commandes ne fonctionnent pas (ou mal) si elles n'arrivent pas à récupérer les informations utilisateur (par exemple, la commande scp). Pour contourner ce problème, il faut générer un fichier etc/passwd contenant au minimum les informations sur l'utilisateur et sur root. Nous allons donc ajouter ceci dans notre script :

mag03

Ensuite, il faut copier dans la cage les dépendances des applications déclarées au début du script :

mag04

Malheureusement, ça ne suffit toujours pas. Comme expliqué précédemment, certaines applications nécessitent de récupérer les informations utilisateur. Juste créer un fichier passwd n'est pas suffisant, car en l'état, l'environnement de la cage ignore qu'il doit utiliser le fichier passwd. Pour ce faire, d'autres bibliothèques et fichiers de configuration sont nécessaires, mais n'ont pas été remontés par la commande ldd.

Sans rentrer dans les détails sur la méthode d'identification de ces fichiers, il faut comparer la liste des dépendances générée dans $TMPFILE3 avec les logs générés par la commande strace, en surveillance des applications demandant les UID et GID.

Au final, nous pouvons terminer notre script avec la récupération des fichiers manquants (certains à un emplacement fixe, d'autres à un emplacement variable en fonction de la distribution) les plus couramment utilisés (à noter qu'une identification basée sur autre chose que le fichier passwd local demandera sans doute d'autres librairies et fichiers de configuration) :

mag05

4) Ajout d'applications à l'environnement restreint : makejail

Nous avons un environnement restreint sur SSH fonctionnel. Après coup, nous pourrions avoir besoin d'autoriser l'une ou l'autre application supplémentaire. Comme nous avons pu le constater, la mécanique à mettre en œuvre n'est pas des plus simples. Pour faciliter l'ajout de nouvelles applications, nous allons cette fois utiliser un programme disponible dans les dépôts : makejail. Pour l'installer, nous utiliserons la commande suivante :

% sudo apt-get update 

% sudo apt-get install makejail

Ce programme fonctionne sur la base de scripts Python. Il rassemble à la fois la recherche de dépendances dynamiques (ldd) et de dépendances indirectes (strace).

Soit un fichier de configuration addCommand.pydans lequel nous allons définir les paramètres d'exécution demakejail :

mag06

Il suffit alors de lancer makejail avec notre fichier de configuration pour ajouter la(les) commande(s) à l'environnement restreint de l'utilisateur :

% sudo makejail addCommand.py

Le programme makejail lance des itérations successives de strace pour identifier tous les fichiers de dépendances indirectes. C'est à la fois sa force et sa faiblesse. Pour un grand nombre de commandes à ajouter à l'environnement restreint, son temps d'exécution devient vraiment énorme (principale raison pour laquelle il n'a pas été retenu pour la génération de l'environnement restreint initial).

Nous privilégierons donc son utilisation pour des environnements légers, ou pour des commandes ayant un grand nombre de dépendances (par exemple : Ruby, Python, …). Enfin, nous n'avons qu'effleuré l'utilisation du paquet makejail. Pour plus d'informations, je vous invite à visiter le site de son auteur sur http://www.floc.net/makejail/.

Nous avons vu que l'environnement restreint devait garder une trace des UID et GUID de l'utilisateur courant et de root pour certaines commandes (ex : scp). Si vous utilisez makejailplutôt que le scriptgenJail.bashdétaillé ci-avant, les informations de UID/GUID devront être ajoutées manuellementdans les fichiers /etc/passwd et /etc/group de l'environnement restreint.

Conclusion

Avec chacune de ces méthodes, nous arrivons au résultat final souhaité qui était d'avoir un dossier web accessible avec une session restreinte. La première méthode, plus simple à mettre en place, est plus limitée que la seconde. Nous avons également vu comment ajouter simplement des commandes à un environnement restreint existant, à l'aide du paquet makejail. Enfin, vous pourriez obtenir des solutions comparables par l'utilisation de conteneurs (LXC, …).

Il ne reste plus qu'à configurer votre serveur web pour utiliser ces dossiers pour le rendu de vos pages web. Si votre serveur web s'exécute avec un utilisateur particulier (par ex : www-data), ajoutez à votre procédure la création d'un groupe contenant votre utilisateur ET l'utilisateur du serveur web. Ensuite, définissez ce groupe comme groupe de base du dossier www de votre utilisateur.


Sur le même sujet

Comment bien choisir son prestataire d’hébergement ?

Magazine
Marque
Linux Pratique
Numéro
119
|
Mois de parution
mai 2020
|
Domaines
Résumé

Avoir son propre serveur, sa propre production, ses propres baies… Bien souvent, cela est juste nécessaire pour la continuité de service et c’est un des métiers clés de l’informatique contemporaine. Sauf que voilà, posséder sa baie à la maison ou dans l’entreprise n’est plus depuis longtemps la meilleure façon de faire. Et la mode des clouds (du « nuagique » en français) nous a même expliqué que tout cela était dépassé, has been, remisé aux poubelles de l’Histoire. Mais alors, quand on a besoin de ses propres serveurs (et pas de services clés en main) et de continuité de services, comment fait-on ? Allons voir ensemble ce que recouvre la notion d’hébergement.

9P, le protocole parfait pour l’IoT

Magazine
Marque
MISC
Numéro
109
|
Mois de parution
mai 2020
|
Domaines
Résumé

Plutôt que de faire passer du JSON sur la couche HTTP, faisons un saut dans le passé pour voir à quoi le futur pourrait ressembler. Développé à partir de la fin des années 80 à Bell Labs, le système d’exploitation Plan 9 utilise le protocole 9P pour rendre le réseau cohérent, sûr et transparent, trois caractéristiques qui manquent à l’IoT...

Attaques par fabrication de liens dans le SDN

Magazine
Marque
MISC
Numéro
109
|
Mois de parution
mai 2020
|
Domaines
Résumé

Imaginez suivre un itinéraire indiqué par votre GPS en qui vous avez toute confiance, et vous retrouver sur un chemin de terre, seul et vulnérable à une attaque par des personnes malintentionnées… Et cela à cause d’un petit malin qui a réussi à faire croire à l’algorithme de votre GPS que cette route était le moyen le plus rapide de rejoindre votre destination ! C’est le sort que nous réserve cet article, avec dans le rôle du GPS un contrôleur SDN (ONOS) et un ensemble de switchs OpenFlow ; et dans le rôle du méchant deux machines disposant de la librairie SCAPY dans leur boite à outils.

« Certifier » son serveur mail

Magazine
Marque
Linux Pratique
Numéro
118
|
Mois de parution
mars 2020
|
Domaines
Résumé

Avoir son propre serveur de mails bien à soi est le rêve de beaucoup d’utilisateurs GNU/Linux. Cependant, depuis quelque temps, les principaux acteurs du net exigent que nous montrions patte blanche avant de transférer ou d'accepter nos courriels. Voyons donc comment faire.

Maîtriser la sécurité de son accès Internet avec OpenWRT

Magazine
Marque
Linux Pratique
Numéro
117
|
Mois de parution
janvier 2020
|
Domaines
Résumé

Nous allons voir dans cet article comment installer le système GNU/Linux embarqué de type OpenWRT. OpenWRT est un système GNU/Linux pour les matériels embarqués et pour les matériels de types routeurs et box. Il constitue donc la part essentielle pour se libérer des GAFA. C’est un système léger, rapide et performant pour administrer et contrôler son accès Internet. Ce système est optimisé pour la gestion des ressources et supporte de nombreux routeurs.

WireGuard, le VPN simple et efficace

Magazine
Marque
Linux Pratique
Numéro
116
|
Mois de parution
novembre 2019
|
Domaines
Résumé

Les logiciels de sécurité peuvent être complexes à comprendre et lourds à mettre en œuvre. Cela peut nous freiner dans l’usage et le déploiement d'architectures sécurisées. Mais le logiciel WireGuard veut nous réconcilier avec les solutions de sécurité. Il a pour but de créer un accès VPN performant entre deux machines et ne propose que peu de choix de configuration. En effet, son développeur, Jason A. Donenfeld a pris le parti de n'implémenter qu'un jeu restreint de protocoles cryptographiques, tous à l'état de l'art, et de ne fournir à l'utilisateur qu'une simple interface réseau. Ces choix permettent de masquer beaucoup de la complexité sous-jacente du VPN derrière cette abstraction. Et en plus de cette simplicité de configuration, WireGuard affirme aussi apporter un haut niveau de performance. Je vous propose de vérifier ensemble si cette promesse est bien tenue !

Par le même auteur

Isolation d'environnements (chroot)

Magazine
Marque
Linux Pratique
Numéro
87
|
Mois de parution
janvier 2015
|
Domaines
Résumé
Cet article propose deux techniques de base permettant de cloisonner une machine Ubuntu/Debian (transposables sur d'autres distributions). À titre d'exemple, nous utiliserons ces techniques pour créer un hébergement cloisonné de sites web. Ceux-ci pourront être mis à jour par des utilisateurs distants en accès console (SSH). D'autres techniques d'isolation d'environnement existent, telles que l'utilisation de container LXC, mais ne seront pas abordées dans cet article.