4. Installation d'un programme un peu plus gros: sshd

Un programme un peu plus gros sera le démon sshd, qui lorsqu'il tournera, nous permettra de venir dans l'environnement chrooté non pas avec chroot, mais avec ssh. L'intérêt est grand: n'importe quel utilisateur pourra venir dans l'environnement chrooté! Pour votre information personnelle, si vous voulez juste installer un démon sshd, sachez qu'il est capable de faire appel à chroot() tout seul. Pas besoin de l'environnement chrooté. Voyez la documentation de sshd. Mais l'intérêt est ici de voir un démon qui a besoin du réseau, de la gestion des utilisateurs, et qui montre bien, une fois qu'il tourne, qu'on est bien dans un environnement chrooté. De plus, il n'est pas trop long à installer. C'est pour cela que j'ai choisi ce démon.

4.1. Installation du programme

Gardons la méthode: on copie le binaire dans la nouvelle racine, on regarde ses dépendances en terme de bibliothèques, et on les recopie.

# mkdir -p /mnt/chroot/usr/sbin
# cp /usr/sbin/sshd /mnt/chroot/usr/sbin
# ldd /usr/sbin/sshd
libpam.so.0 => /lib/libpam.so.0 (0x40020000)
libdl.so.2 => /lib/libdl.so.2 (0x40029000)
libutil.so.1 => /lib/libutil.so.1 (0x4002d000)
libz.so.1 => /lib/libz.so.1 (0x40030000)
libnsl.so.1 => /lib/libnsl.so.1 (0x4003e000)
libcrypto.so.0.9.7 => /usr/lib/libcrypto.so.0.9.7 (0x40052000)
libc.so.6 => /lib/i686/libc.so.6 (0x40140000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
# cp /lib/libpam.so* /mnt/chroot/lib
# cp /lib/libutil.so* /mnt/chroot/lib
# cp /lib/libz.so* /mnt/chroot/lib
# cp /lib/libnsl.so /mnt/chroot/lib
# mkdir -p /mnt/chroot/usr/lib
# cp /usr/lib/libcrypto.so.0.9.7 /mnt/chroot/usr/lib
# chroot /mnt/chroot /usr/sbin/sshd -p 2002
PRNG is not seeded
	

La méthode ne change pas par rapport à ce que nous avons vu avec ls. Et on lance sshd. Comme sshd tourne peut-être déjà sur le port 22 (voyez votre fichier /etc/services), nous le faisons tourner sur un autre port, ici 2002 (pris au hasard). Cela ne marche pas, et les choses sérieuses commencent ici.

4.2. Identification des problèmes et résolution

Ici, je pourrais vous dire qu'il manque /dev et son contenu, /etc et quelques fichiers ou encore /proc. Je n'ai pas envie de vous présenter cela comme si c'était un didacticiel. Nous allons choisir la méthode hacker pour résoudre les problèmes: identification, recherche d'une solution et résolution.

Pour identifier les problèmes, il y a trois méthodes assez intéressantes ici. La première que nous allons mettre en oeuvre est de regarder ce qui manque probablement, entre autres une arborescence unix minimale. La seconde qui doit toujours être mise en oeuvre, quelle que soit la situation et quel que soit le problème est d'aller voir dans les logs ou d'utiliser le mode verbeux des programmes quand il existe. D'ailleurs, revenons à la première méthode: il manque déjà le répertoire /var/log. Troisième méthode assez intéressante aussi: l'utilisation de strace. Ce programme nous indique principalement tous les accès aux fichiers.

4.3. L'aborescence Unix

Créons tout d'abord une arborescence unix/linux digne de ce nom. Il nous faut généralement les répertoires suivants:

/bin /dev /etc/ /home /lib /proc /sbin /tmp /usr /usr/bin /usr/lib /usr/sbin /var /var/log

A nouveau, si l'objectif est la sécurité, vous veillerez à supprimer ensuite tout ce qui est non utile.

4.4. /dev

Pas besoin d'être devin pour se douter que /dev doit être rempli un minimum. Sur un système sans devfs tel que debian woody, utilisez MAKEDEV:

# cd /mnt/chroot/dev
# /dev/MAKEDEV std
	

Voyez la page de manuel de MAKEDEV pour en savoir plus sur ce que l'on peut créer. Simplement std permet de créer un jeu de devices standard, la base pour fonctionner. Avec cela, vous devriez avoir ce qu'il faut pour démarrer sans avoir trop de problèmes. Je reviens à nouveau sur l'aspect sécurité: avec ceci, vous en avez largement trop et si vous gardez tout, vous facilitez la tâche aux pirates si l'objectif est d'améliorer la sécurité. Donc ici, faites le ménage une fois que cela marche si vous voulez protéger l'environnement.

Sur un système fonctionnant avec devfs, il faudrait faire tourner un démon devfsd sachant créer les devices dans /mnt/chroot/dev de la même manière qu'il le fait dans /dev. Il y a une manière plus simple de faire: monter /dev sur /mnt/chroot/dev. Avec les noyaux récents, une options de mount est apparue; elle permet de monter un répertoire sur un point de montage. Cela ressemble à la création d'un partage de répertoire pour ceux qui connaissent NFS, et ensuite à un montage de ce répertoire partagé. Mais il n'y a rien de réseau là dessous. Depuis la racine (pas l'environnement chrooté), faites:

# mount -o bind /dev /mnt/chroot/dev
	

4.5. /proc

En ce qui concerne /proc, il est généralement inutile. En l'occurence, avec sshd, il est inutile. Pourtant, dans certains cas, il peut s'avérer nécessaire. Il faudra alors le monter. Mais dans ce cas, sachez qu'un pirate vous sera particulièrement reconnaissant de lui donner accès à /proc, encore une fois si l'objectif est la sécurité.

Ici, nous allons tout simplement le monter de la manière la plus classique qu'il soit, depuis l'environnement chrooté. Pour que ce soit encore plus facile, remarquez qu'il manque le fichier /etc/fstab que nous allons en profiter pour éditer:

# chroot /mnt/chroot /bin/bash
# cat /etc/fstab
bash, cat, command not found

# cat /etc/fstab
none /dev/pts devpts mode=0620 0 0
none /proc proc defaults 0 0
# mount /proc
bash, mount, command not found

# mount /proc
	

Eh oui, il manquait cat et mount que j'ai recopiés, dans une autre fenêtre, au bons endroits, et c'est pour cela que ca marche du second coup. J'ai aussi installé umount pour démonter /proc avant de quitter l'environnement chrooté. Dans /etc/fstab, mettez tout ce qui peut vous arranger pour de futurs montages à l'intérieur de l'environnement chrooté.

4.6. /etc/ssh/*

Recommençons à lancer sshd comme nous l'avons fait. S'il n'est toujours pas content et continue à parler de PRNG not seeded, nous irons voir ce que cela veut dire dans la documentation de sshd, les FAQ ou nous utiliserons d'autres moyens de nous documenter.

# chroot /mnt/chroot /bin/bash
# mount /proc
# /usr/sbin/sshd -p 2002
/etc/ssh/sshd_config: No such file or directory
	

Le message d'erreur à changé, donc pas besoin de se casser la tête à comprendre d'où venait le problème de PRNG. Petite digression en ce qui concerne le précédent message. PRNG is not seeded est un message de sshd pour indiquer qu'il n'a pas de moyen de générer des nombres aléatoires digne de ce nom. Sur GNU/Linux, /dev/random suffit amplement et c'est pour cela que nous n'avons plus le problème. Sur Solaris, il faut installer un générateur de nombres aléatoires en plus. Fin de la digression.

Le message d'erreur actuel est que sshd ne trouve pas ses fichiers de configuration. Cela est simple: je vous laisse recopier les fichiers nécessaires de /etc/ssh vers /mnt/chroot/etc/ssh.

4.7. Utilisation de strace

Recommencez. Le message est maintenant:

# /usr/sbin/sshd -p 2002
Privilege separation user sshd does not exist
	

Si cela ne vous dit pas grand chose, au moins, cela doit vous faire penser que nous n'avons pas de /etc/passwd, /etc/group ni /etc/shadow. Ici encore, il suffit de les recopier. Pour améliorer la sécurité, ne gardez que les utilisateurs dont vous avez besoin, à savoir root, sshd et un utilisateur si besoin.Evitez par contre de modifier les uid/gid si vous n'avez pas de bonne raison de le faire. En effet, c'est plus facile hors du chroot de savoir à qui appartiennent les fichiers créés à l'interieur de l'environnement chrooté. Et hop, on recommence. Et hop, on retrouve le même message d'erreur.

Passons à la vitesse supérieure: lançons sshd en mode debug

# /usr/sbin/sshd -d -d -d -p 2002
debug2: read_server_config: filename /etc/ssh/sshd_config
debug1: sshd version OpenSSH_3.6.1p2
debug1: private host key: #0 type 0 RSA1
debug3: Not a RSA1 key file /etc/ssh/ssh_host_rsa_key.
debug1: read PEM private key done: type RSA
debug1: private host key: #1 type 1 RSA
debug3: Not a RSA1 key file /etc/ssh/ssh_host_dsa_key.
debug1: read PEM private key done: type DSA
debug1: private host key: #2 type 2 DSA
Privilege separation user sshd does not exist
	

Pas moyen d'en savoir beaucoup à partir de cela, et pas moyen non plus d'en savoir plus avec la log: il n'y en a tout simplement pas. Nous devons passer à une vitesse encore supérieure et utiliser strace. Installez-le comme vous avez installé les autres binaires (vérifiez les bibliothèques avec ldd).

# strace /usr/sbin/sshd -d -p 2002
[...]
open("/etc/nsswitch.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
[...]
	

Je n'ai pas fait une lecture attentive de la sortie, mais quelques lignes avant la fin, on repère sans trop de difficultés qu'il manque ce fichier /etc/nsswitch.conf. Il suffit de le rajouter comme d'autres déjà.

Je vais faire une nouvelle digression sur les bibliothèques partagées et le chargeur dynamique. Apres le message concernant /etc/nsswitch.conf, voici ce qui apparaît chez moi:

open("/lib/libnss_compat.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libnss_compat.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
	

Ce genre de message se trouve souvent, et vous pouvez le trouver dès le début ou plus loin. Exemple (extraits):

open("/lib/libcrypto.so.0.9.7", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/i686/libcrypto.so.0.9.7", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libcrypto.so.0.9.7", O_RDONLY) = 3
	

Quand cela marche, le chargeur cherche dans plusieurs répertoires (ceux qui sont dans /etc/ld.so.conf; d'ailleurs, il est manquant, mais certains chemins comme /lib et /usr/lib sont déjà pris par défaut). Et lorsqu'il a trouvé le fichier contenant la bibliothèque partagée, il s'arrête et on passe à d'autres messages. Quand cela ne marche pas, vous avez un exemple avec libnss_files.so et libnss_compat.so qui sont manquantes aussi. Encore deux fichier manquants: veuillez les installer!

Essayons à nouveau... Cela marche! Il ne reste plus qu'à se connecter depuis ailleurs. Et là, déception: le serveur sshd s'arrête après refus de connexion.

4.8. localtime

Vous avez maintenant compris la méthode: lorsque les messages d'erreurs ne suffisent pas à dire ce qu'il manque, on utilise strace. On recommence avec strace ici comme ci-dessus. Puis on se logue depuis ailleurs, ce qui nous rajoute quelques messages du côté de strace avant l'arrêt/plantage de sshd. A la fin, nous avons un message indiquant qu'il manque /etc/localtime:

open("/etc/localtime", O_RDONLY) = -1 ENOENT (No such file or directory)
	

Vous pouvez copier le fichier comme on a fait déjà, mais ce serait intéressant de savoir ce qu'est ce fichier qui est plutôt binaire. Ce fichier n'est rien d'autre qu'un lien ou une copie d'un fichier que l'on peut trouver dans /usr/share/zoneinfo. C'est le fichier qui décrit le fuseau horaire où l'on se trouve. Ainsi, si vous habitez la Bretagne, le fuseau horaire est celui de Paris puisqu'on trouve aussi des bretons dans le quartier Edgar Quinet à Montparnasse entre autres (je ne suis pas très sur pour mon explication sur les fuseaux horaires), et il vous suffit donc de copier /usr/share/zoneinfo/Europe/Paris dans /mnt/chroot/etc.

4.9. PAM

Pourtant, cela ne change pas grand chose à notre problème qui se situe ailleurs. Voici deux des messages vers la fin:

stat64("/etc/pam.d", 0xbfffeea0) = -1 ENOENT (No such file or directory)
open("/etc/pam.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
	

Voyons ce que l'on trouve dans /etc/pam.d quand on n'y connaît rien à PAM. On y trouve des fichiers texte, qui contiennent des règles d'authentification. Effectivement, PAM signifie bien Pluggable Authentification Modules. Donc c'est tout simple, c'est comme pour le reste: il suffit de copier les fichiers. Et si vous vous amusez à essayer à nouveau, vous devriez avoir du nouveau: on va vous demander votre mot de passe. Mais même si vous fournissez le bon mot de passe, il vous sera impossible de vous loguer. Pour continuer, il faut en savoir plus sur les Modules d'Authentification à brancher. La page de manuel est bien faite sur Linux: outre les explications, on nous indique à la fin que nous avons oublié de copier les fichiers /usr/lib/libpam.so.X et /usr/lib/security/*.so. Sshd étant lié à libpam, nous l'avons déjà recopié. Reste /usr/lib/security/*.so. Attention, la page de manuel n'est pas forcément conforme à la réalité. En outre, Debian et Mandrake placent ces bibliothèques dans /lib/security et pas dans /usr/lib/security. Vous savez ce qu'il vous reste à faire...

4.10. DNS et réseau

...et cela ne marche toujours pas. Il faut remonter un peu plus haut dans les messages d'erreur:

open("/etc/hosts.allow", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/hosts.deny", O_RDONLY) = -1 ENOENT (No such file or directory)
[... beaucoup de lignes ici ...]
open("/etc/protocols", O_RDONLY) = -1 ENOENT (No such file or directory)
[...]
connect(3, {sa_family=AF_UNIX, path="/var/run/.nscd_socket"}, 110) = -1 ENOENT (No such file or directory)
open("/etc/protocols", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/resolv.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
[...]
open("/etc/host.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/hosts", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libnss_nisplus.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libnss_nisplus.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libnss_nis.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libnss_nis.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libnss_dns.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libnss_dns.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
	

Bref, il nous manque pas mal de choses au niveau réseau. Mais rien de neuf ici: il suffit encore de copier les fichiers manquants. Attention, les fichiers /var/run/* sont un peu spéciaux. Ce sont des fichiers créés par les programmes ou les scripts qui les lancent pour indiquer qu'ils tournent, et qui servent généralement à contenir leur numéro de processus (PID). Ici, nous n'avons dont pas à créer le fichier /var/run/.nscd_socket, mais juste à nous assurer que /var/run existe et est un répertoire. Dans le même style, créez un répertoire /var/lock car certains démons ou scripts créent un fichier dans ce répertoire pour éviter qu'on le lance une seconde fois.

Par ailleurs, il est un fichier que sshd ne semble pas nécessiter, mais que d'autres programmes utilisent. C'est le fichier /etc/services, que vous pouvez aussi copier. Attention aussi à un autre fichier absent: le fichier nologin. Ce fichier doit lui, au contraire des autres, être effectivement absent. Ce fichier, lorsqu'il est présent, empêche les connexions à distance: exactement le contraire de ce que nous voulons!

4.11. Les dernières bibliothèques

Cela ne marche pas encore, toujours pas, mais ne nous decourageons pas: on est proche du bout. Sauf que... impossible de trouver ce qu'il manque maintenant. Si vous avez l'oeil, vous avez déjà repéré qu'il manque libcrypt.so et libcrack (éventuellement aussi libglib qui me semble inutile). Sinon, vous aurez peut-être fait comme moi, à savoir copié grep et la bibliothèque libpcre.so pour pouvoir les utiliser:

# strace /usr/sbin/sshd -d -p 2002 2>&1 |grep ENOENT
open("/lib/libcrypt.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libcrypt.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libcrack.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
	

Et voilà, si vous les copiez, vous devriez pouvoir vous loguer après avoir relancé sshd.

4.12. /var/*

Relancez sshd avec strace pour la dernière fois, par acquis de conscience. Vous devrez noter que /var/run/utmp, /var/run/utmpx, /var/log/xtmp, /var/log/wtmpx et /var/log/lastlog manquent. Ce sont des fichiers que vous devriez créer s'ils existent déjà sur votre distribution:

# touch /mnt/chroot/var/run/utmp
# touch /mnt/chroot/var/log/wtmp
# touch /mnt/chroot/var/log/lastlog
	
création est mise à disposition sous un contrat Creative Commons