Hello ! Dans cet article nous allons voir comment créer une jail « hybrid » SSH/SFTP (avec accès au répertoire web public_html) pour resserrer un peu plus encore la sécurité d’un système Linux. Pour la démonstration, je vais utiliser Ubuntu 22.04. D’autres méthodes de cloisonnement existent et sont plus simple à mettre en œuvre (comme rbash), mais ne sont pas aussi efficaces, car les risques d’échappement sont plus élevés. La méthode que je présente ci-dessous est adoptée par bon nombre d’hébergeur dans le cadre d’offre d’hébergement mutualisé.

L’article présente une approche  » à l’ancienne  » mais qui, d’après mes pairs, a su faire ses preuves à travers les années. Préparez votre meilleur thé/café, vos lunettes ?, l’article va être un tant soit peu long.

Pour faciliter la compréhension du sujet, j’utilise à de multiples reprises des analogies (comme à mon habitude), avec mes deux utilisateurs principaux tintin et haddock.

Environnement

  • Ubuntu 22.04 avec OpenSSH de préinstallé. Installez le logiciel client filezilla, si vous souhaitez avoir une vue graphique lors de vos connexion SFTP. (apt install filezila)

Etape 1 – Fondation de notre prison virtuelle

Afin de gagner du temps, et d’éviter d’écrire à chaque fois le chemin racine de notre jail, je vais définir le répertoire /home/jails/ au sein d’une variable local. Ce dossier sera les « murs » de notre futur prison.

D=/home/jails
mkdir -p $D

Listez les éléments du dossier /dev à l’aide de la commande suivante (Nous en allons avoir besoin pour la suite) :

ls -l /dev/{null,zero,stdin,stdout,stderr,random,tty}

Pour que notre prison prenne forme, il faut reproduire un minimum de dossier racine contenant certains fichiers élémentaires d’un système Unix. Recréez le dossier « dev » à la racine de notre prison :

mkdir -p $D/dev/

Notre « jail » virtuelle a donc besoin de « fonction primaire » pour pouvoir fonctionner correctement. Copiez les fichiers suivants en exécutant les commandes ci-après lignes par lignes. N’utilisez pas cp mais la commande mknod (copie de fichiers sous un certain format : généralement au format : block)

mknod -m 666 $D/dev/null c 1 3
mknod -m 666 $D/dev/tty c 5 0
mknod -m 666 $D/dev/zero c 1 5
mknod -m 666 $D/dev/random c 1 8

Ensuite, nous devons définir le propriétaire du répertoire $D. Saisissez la commande suivante afin que le répertoire $D appartienne exclusivement à l’utilisateur root et ne soit accessible en écriture par aucun utilisateur : 

chown root:root $D
chmod 0755 $D

Vérifiez, en exécutant  :

ls -ld $D
Récapitulatif des actions précédentes

Pour continuer, nous allons avoir besoin de créer un dossier « racine » (cellule pour chaque utilisateur prisonnier) dans le chemin $D (/home/jails)/bin/. Saisissez :

mkdir -p $D/bin

Copiez ensuite le shell /bin/bash dans le répertoire $D/bin/ :

cp -v /bin/bash $D/bin

Nos prisonniers auront donc l’accès à un shell bash très restreint.

On pourrait comparer cet environnement aux droits civique français. Ils pourront parler, écrire, lire, manger… (echo,touch/mkdir,cat,… ^^) mais ne pourront pas interagir avec l’extérieur pour des raisons de sécurité collective.

Copiez les bibliothèques partagées requises (pour le fonctionnement « natif » de bash) dans le répertoire $D. La commande suivante permet de savoir ce dont bash a besoin :

ldd /bin/bash

Attention, vous n’aurez probablement pas la même sortie de commande que moi si vous utilisez une autre version qu’Ubuntu 22.04. Prenez garde au nom des fichiers, c’est la partie la plus délicate de cet article.

Créez les dossiers suivants, puis copiez les fichiers comme suit à l’aide de la commande cp.

mkdir -p $D/lib/
mkdir -p $D/lib64/
mkdir -p $D/lib/x86_64-linux-gnu/
cp -v /lib/x86_64-linux-gnu/{libtinfo.so.6,libc.so.6,ld-linux-x86-64.so.2} $D/lib/
Récapitulatif des actions précédentes

Cette étape est bloquante

Ensuite, copiez /lib64/ld-linux-x86-64.so.2 dans le répertoire $D/lib64/ :

cp -v /lib64/ld-linux-x86-64.so.2 $D/lib64/

Puis, copiez tous les fichiers étant préfixés de cette manière /lib/x86_64-linux-gnu/libnss_files* :

cp -va /lib/x86_64-linux-gnu/libnss_files* $D/lib/x86_64-linux-gnu/

Etape 2 – Ajouter un ou plusieurs utilisateurs prisonnier dans notre prison virtuelle

Utilisez la commande suivante pour créer vos utilisateurs.

adduser --no-create-home tintin
adduser --no-create-home haddock

Ajoutez les à un groupe

groupadd moulinsart
usermod -G moulinsart tintin
usermod -G moulinsart haddock

Pour vérifier :

id tintin
id haddock

Tintin et Haddock font donc partie du groupe Unix Moulinsart.

Enfin, créez et copiez les fichiers /etc/{passwd,group} dans le répertoire $D/etc/ :

mkdir -p $D/etc/
cp -vf /etc/{passwd,group} $D/etc/

Avertissement : si vous ajoutez, supprimez ou apportez des modifications à un ou x utilisateurs recopiez à nouveau les fichiers /etc/{passwd,group} en exécutant les deux commandes suivantes :
D=/home/jails
cp -vf /etc/{passwd,group} $D/etc/

Etape 3 – Configurer sshd

Editez /etc/ssh/sshd_config, en entrant les directives suivantes à la fin du fichier :

nano /etc/ssh/sshd_config
Commentez la ligne surlignée en vert

Enregistrez le fichier, puis redémarrez le service SSH :

systemctl restart ssh.service

Si vous n’avez pas d’erreur, cela veut dire que votre configuration ssh est intègre et syntaxiquement correcte. Vous pouvez donc essayer de vous connecter en sftp et en ssh, afin de vérifier que votre jail fonctionne bien pour ces deux protocoles « siamois ».

Maintenant, tentez de vous connecter à l’aide d’un des comptes faisant partie du groupe Moulinsart. Dans le contexte présenté, je vais utiliser tintin exclusivement pour tous mes tests ci-après.

sftp tintin@localhost
Connexion via SFTP
Connexion via SSH

Top ! Nos prisonniers ont bien été affectés dans notre prison, et il est possible de se connecter à la fois en SSH et par son protocole jumeaux SFTP. Toutefois, actuellement ils n’ont pas de cellule qui leur est affectée, par défaut, ils ne peuvent presque rien faire car ils sont affectés dans /home/jails, qui est le répertoire dont root est le propriétaire.

Etape 4 – Tests du cloisonnement de notre prison (Quelles sont les droits des prisonniers ?)

Comme vous pouvez le constater, je peux me connecter avec le compte tintin. Par contre très peu de commandes sont disponible… C’est normal, car nous avons copié uniquement les cmds « Core » Unix. Par mesure de sécurité, le moins de commande l’utilisateur final aura, plus dur il sera pour lui de s’échapper de sa cellule et de sa prison (escalade de privilège). Toutefois, il doit quand même disposer de commandes tels que ls, cat, echo, rm, vi, date, mkdir, touch, etc, (pour pouvoir communiquer et ne pas trop se morfondre ^^) afin qu’il puisse à minima interagir avec le système. C’est ce que nous allons voir dans la section suivante :

Par défaut, les commandes telles que ls, cd, touch, date… ne sont pas disponible. De plus, vous êtes situé à la racine de la prison et donc vous n’avez aucun droits ! (le hall central d’accueil des prisonniers, dans l’attente d’être affecté dans une cellule.) Dans la section suivante, nous verrons comment remédier à ce problème.

Afin d’ajouter d’autres commandes à notre jail, nous allons utiliser le script suivant que j’ai trouvé sur le site LinuxConfig.org où j’ai pris la liberté de la modifier légèrement afin de l’optimiser :

#!/bin/bash
# This script can be used to create simple chroot environment
# Written by LinuxConfig.org 
# (c) 2020 LinuxConfig under GNU GPL v3.0+
#!/bin/bash
CHROOT='/home/jails'
for i in $( ldd $* | grep -v dynamic | cut -d " " -f 3 | sed 's/://' | sort | uniq )
  do
    cp --parents $i $CHROOT
  done
# ARCH amd64
if [ -f /lib64/ld-linux-x86-64.so.2 ]; then
   cp --parents /lib64/ld-linux-x86-64.so.2 /$CHROOT
fi
# ARCH i386
if [ -f  /lib/ld-linux.so.2 ]; then
   cp --parents /lib/ld-linux.so.2 /$CHROOT
fi
echo "Chroot jail is ready. To access it execute: chroot $CHROOT"

Exécutez le script, en précisant les commandes que vous souhaitez affecter à vos prisonniers :

chmod u+x addCommandToJail.sh
./addCommandToJail.sh /bin/{ls,cat,echo,rm,vi,date,mkdir,touch}
On constate que notre prisonnier tintin, peux maintenant exécuter la commande ls

Si vous obtenez une erreur de ce type : cp: cannot create regular file ‘//home/jails/lib64/ld-linux-x86-64.so.2’: Text file busy, c’est que vous êtes toujours connecté en ssh au serveur avec votre utilisateur. Déconnectez-vous. Je tiens à préciser que cette erreur est un peu aléatoire parfois, je l’ai eu juste une fois. ^^

Etape 5 – Création des dossiers utilisateurs (Attributions des cellules aux prisonniers)

Continuons. Nous devons créer le dossier « home » de tintin et le nommer propriétaire du dossier.

Vous avez l’obligation de créer le répertoire « home » de vos utilisateurs. Sans cela, vous serez relégué à la racine de la jail (/home/jails/) qui appartient à l’utilisateur root. Autant vous dire qu’ici, vous n’avez aucun droits. ^^

mkdir -p /home/jails/home/tintin
chown -R tintin:tintin /home/jails/home/tintin/
chmod 700 -R /home/jails/home/tintin/

Faite pareil pour haddock :

mkdir -p /home/jails/home/haddock
chown -R haddock:haddock /home/jails/home/haddock/
chmod 700 -R /home/jails/home/haddock/

Les étapes ci-dessus peuvent être scriptées très facilement 🙂 | Hop Hop Pas de fainéantise les sysadmins ^^

Réessayez de vous connecter en SFTP/SSH, dans l’intention de vérifier votre chemin courant, afin de vérifier si vous êtes bien affecté automatiquement dans votre dossier (cellule).

SSH

Vous êtes bien dans votre /home/$USER. Vous disposez donc des droits nécessaire pour interagir avec le système.

Déconnectez vous de votre client SFTP, puis connectez vous de nouveau, si vous souhaitez tester que l’affectation fonctionne aussi via SFTP.

SFTP via filezilla

Bonus – Répertoire web public_html pour vos utilisateurs « chrooté » (Seul contact de vos prisonniers avec l’extérieur de leurs cellules)

Exécutez les commandes ci-dessous « as root », afin d’installer votre serveur web apache et de créer un répertoire public_html (dossier personnalisé), pour chaque utilisateurs de votre jail :

Note : Vous ne pouvez pas utiliser la méthode traditionnelle site.com/~user pour apache lorsque vous êtes un user chrooté. Trop compliqué à détailler, je ne rentrerai pas dans les détails, car je ne serais même pas sûr de savoir l’expliquer ^^. Je vous laisse suivre les étapes ci-dessous en mode « Copy and Paste » <3

apt update
apt install apache2 
cd /home/jails/home/tintin && mkdir public_html
chown -R tintin:tintin /home/jails/home/tintin/public_html
cd /var/www/html && mkdir tintin && cd tintin

Créez un simple fichier, afin de vérifier que notre répertoire est bien pris en compte par notre service web apache.

touch hello

Vu qu’il n’est pas possible d’utiliser la fonctionnalité mod_userdir d’apache dans ce contexte, il vous faut utiliser la commande mount afin de créer un lien entre votre dossier public_html de votre prison, et le dossier du service web.

mount /var/www/html/tintin /home/jails/home/tintin/public_html/ -o bind
cd /home/jails/home/tintin/public_html
touch hello_from_jail.txt

Actualisez la page depuis le navigateur, et vous verrez que votre fichier hello_from_jail.txt aura été synchronisé instantanément avec le dossier « mirroir » /var/www/html/tintin

Afin de persister ce point de montage et donc l’accès au dossier web personnalisé, ajouter cette commande à /etc/fstab, puis redémarrez pour tester

echo "/var/www/html/tintin/ /home/jails/home/tintin/public_html none bind" >> /etc/fstab
reboot

Affichez de nouveau le dossier web de l’utilisateur tintin dans votre navigateur pour vérifier que le point de montage a bien été remonté automatiquement suite au redémarrage.

« tin tin » ça fonctionne !

J’espère que ce tutoriel vous aura plus, il fut sans aucun doute l’un des plus complexes pour moi à tester et à rédiger (très peu de ressources à jour sur le web). Je vous invite à scripter tout ça afin de ne pas prendre 15m, pour ajouter un nouvel utilisateurs par exemple. Peut-être que j’en ferai un à l’occasion. J’ai bien dis peut être.

++

Geoffrey


Geoffrey Sauvageot-Berland

Ingénieur diplômé par l’état en Informatique et Cybersécurité. Généraliste, à l'origine administrateur systèmes et réseaux, j’occupe actuellement un poste d’auditeur en sécurité offensive. J’apprécie également la programmation/automatisation. Fondateur du blog : "Le Guide du SecOps", anciennement "Le Guide du SysOps"