Linux - Création environnement OpenSSH-CHROOT

Décembre 2016


OpenSSH-CHROOT






Pour encore une fois un grand merci à jipicy pour sa disponibilité et sa patience pour les corrections linguistiques.

I. Installation de openssh-chroot


A. Téléchargement et vérification de la signature


Création d'un répertoire pour le téléchargement des fichiers
$ mkdir /home/lami20j/prisonssh
$ cd /home/lami20j/prisonssh
$ wget ftp://ftp.club-internet.fr/pub/OpenBSD/OpenSSH/portable/openssh-4.3p1.tar.gz*
$ wget http://chrootssh.sourceforge.net/download/osshChroot-4.3p1.diff
 
Il semble que le patch n'est plus disponible à l'adresse indiquée. Regardez plus bas (Chap V. )

Nous sommes dans /home/lami20j/prisonssh et voilà ce que le répertoire contient :
$ ls -1
openssh-4.3p1.tar.gz
openssh-4.3p1.tar.gz.asc
osshChroot-4.3p1.diff
prisonssh.pl
useradd_prisonssh.pl 
prisonssh.pl et useradd_prisonssh.pl sont les 2 scripts Perl que l'on verra plus bas.

Vérification de la signature
$ gpg --keyserver pgp.mit.edu --recv-keys 0x86FF9C48
gpg: requête de la clé 86FF9C48 du serveur hkp pgp.mit.edu
gpg: clé 86FF9C48: nom d'utilisateur en double détecté - fusion accomplie
gpg: clé 86FF9C48: clé publique « Damien Miller (Personal Key) » importée
gpg: aucune clé de confiance ultime n'a été trouvée
gpg: Quantité totale traitée: 1
gpg: importée: 1

$ gpg --fingerprint 86FF9C48
pub 1024D/86FF9C48 2001-02-26
Empreinte de la clé = 3981 992A 1523 ABA0 79DB FC66 CE8E CB03 86FF 9C48
uid Damien Miller (Personal Key) 
sub 2048g/AA2B1C41 2001-02-26

$ gpg --verify openssh-4.3p1.tar.gz.asc openssh-4.3p1.tar.gz
gpg: Signature faite le mer 01 fév 2006 12:34:31 CET avec la clé DSA ID 86FF9C48
gpg: Bonne signature de « Damien Miller (Personal Key) »
gpg: ATTENTION: Cette clé n'est pas certifiée avec une signature de confiance !
gpg: Rien ne dit que la signature appartient à son propriétaire.
Empreinte de clé principale: 3981 992A 1523 ABA0 79DB FC66 CE8E CB03 86FF 9C48 

B. Installation


Suppression des paquetages installés.

Debian :
# apt-get remove --purge ssh 
Mandriva2006 et Fedora :
# for i in $(rpm -qa | grep openssh);do rpm --nodeps -e $i;done 
Dépendances requises : zlib et openssl
Lisez le fichier README pour plus de détails.
$ su
Password:
# cd /usr/local
# tar xzvf /home/lami20j/prisonssh/openssh-4.3p1.tar.gz
# cd openssh-4.3p1/
# patch < /home/lami20j/prisonssh/osshChroot-4.3p1.diff
patching file session.c
# ./configure
# make
# make install

C. Ecriture du script de démarrage pour sshd


Avec votre éditeur de texte préféré, créer le fichier /etc/init.d/sshd
et écrivez le script suivant.
Une fois l'édition du fichier terminé, enregistrez et quittez.
#!/bin/bash

case $1 in
'start' )
        /usr/local/sbin/sshd
        ;;
'stop'  )
        pkill sshd
        ;;

* )
        echo "usage : /etc/init.d/sshd {start|stop}"
        ;;
esac 
 
Etablissez les droits d'accès avec la commande
# chmod -v 0755 /etc/init.d/sshd 
Si l'utilisateur sshd n'existe pas, vous pouvez le créer avec la commande :
# useradd -c 'Privilege-separated SSH' -d /var/empty/sshd -s /sbin/nologin sshd  
Lancer le daemon
# /etc/init.d/sshd start 
Pour que le démarrage du daemon soit pris en compte au démarrage du PC faites :
# update-rc.d sshd start 99 2 3 4 5 . 

II. Création d'un environnement chroot openssh


- le script prisonssh.pl

SYNOPSIS
# perl /chemin/vers/script/prisonssh.pl 
A la demande du répertoire mettez le nom de votre choix.
Le répertoire sera créé dans /home
#! /usr/bin/perl
#
use strict; use warnings;

use File::Basename;
my (@lib,@ldd,%listreplib);
# création de répertoire
print "Entrez le nom de repertoire : ";
chomp(my $chroot_rep=<STDIN>);
mkdir '/home/'.$chroot_rep
or die "Impossible de créer le répertoire : $!";
# Les applications d'environement chroot
#
# Assurez vous que le chemin des applications mentionnées correspond 
#
# Par exemple la commande id
# sous Debian et Fedora5 on la trouve dans /usr/bin
#
# sous Mandriva 2006 dans /bin
#
# à vous d'ajouter ou enlever des applications
# et bien sûr de modifier le script
#
# les applications (/bin) 
my @apps0=qw ( 
              /bin/bash
              /bin/ls
              /bin/mkdir
              /bin/mv 
              /bin/pwd 
              /bin/rm
              /bin/sh 
              /bin/echo 
              /bin/cp 
              /bin/cat 
              /bin/ln 
              /bin/chown
              /bin/chmod 
              /bin/grep 
              /bin/more 
              /bin/tar
              /bin/gzip 
              /bin/true 
              /bin/false
              /bin/ping 
              /bin/egrep
              /bin/hostname
);

# les applications (/usr/bin, etc...)

my @apps1=qw ( 
              /usr/local/bin/scp 
              /usr/bin/env 
              /usr/bin/clear 
              /usr/bin/wc 
              /usr/bin/perl 
              /usr/bin/id 
              /usr/local/bin/ssh
              /usr/bin/du
              /usr/bin/less
              /usr/bin/bzip2
              /usr/bin/tset
);

# le subsystem sftp
my @sftp_server=qw ( /usr/local/libexec/sftp-server );

# récupérer les bibliothéques
foreach (@apps0,@apps1,@sftp_server){
    my $ldd=`ldd $_`;
    my @temp=split /\n/, $ldd;
    push @ldd,@temp;
}

# récupérer le chemin de chaque bibliothèque
foreach(@ldd){
    if ( $_=~/(?:\/?.*=>\s*)?(\/.*)\b\s*\(/ ){
        print "$1\n";
        push @lib,$1 if $1 !~ /^\s*$/;
    }
}

# les répertoires à créer (/lib,/usr/lib,etc...)
foreach(@lib){
    my $replib=dirname($_);
    $listreplib{$replib} +=1;
}

# création des répertoires dans l'environement chroot
foreach (keys %listreplib){
    system "mkdir","-p","/home/$chroot_rep/$_";
}

# création du répertoire bin dans l'environement chroot
mkdir "/home/$chroot_rep/bin";

my @rep=qw { 
            home usr/bin
            usr/lib/locale
            usr/share/locale
            tmp
            dev/pts
            etc/pam.d
            usr/local/libexec
};

foreach (@rep) {
    system "mkdir", "-p", "/home/$chroot_rep/$_";
}

# copier les applications dans le répertoire /bin d'environnement chroot
foreach(@apps0){
    system "cp","-p","$_","/home/$chroot_rep/bin";
}

# copier les applications dans répertoire /usr/bin d'environnement chroot
foreach(@apps1){
    next if /.*sftp-server.*/i;
    system "cp","-p","$_","/home/$chroot_rep/usr/bin";
}

# copier sftp-server
system "cp","-p","/usr/local/libexec/sftp-server","/home/$chroot_rep/usr/local/libexec";

# copier les bibliothèques
foreach (@lib){
    my $rep_lib=dirname($_);
    system "cp","-p","$_","/home/$chroot_rep/$rep_lib";
}

opendir (LIBNSS,"/lib")
        or die "Impossible d'ouvrir le répertoire : $!";
while (defined (my $libnss = readdir(LIBNSS))) {
    next unless $libnss=~/libnss.*/;
    system "cp","-p","/lib/$libnss","/home/$chroot_rep/lib";
} 

#
system "cp","-RPp","/usr/share/terminfo","/home/$chroot_rep/usr/share";

#
system "mknod","-m","0666","/home/$chroot_rep/dev/null","c","1","3";
system "mknod","-m","0666","/home/$chroot_rep/dev/zero","c","1","5";
system "mknod","-m","0444","/home/$chroot_rep/dev/urandom","c","1","9";
system "mknod","-m","0666","/home/$chroot_rep/dev/tty","c","5","0";
system "mknod","-m","0666","/home/$chroot_rep/dev/ptmx","c","5","2";

#
my @etc_conf=qw(
                nsswitch.conf host.conf resolv.conf bashrc termcap 
                hosts localtime login.defs profile tsocks.conf
);

foreach (@etc_conf){
    system "cp","/etc/$_","/home/$chroot_rep/etc";
}

#
system "cp","-R","/usr/lib/perl5","/home/$chroot_rep/usr/lib";

#
my @pamd=qw(
            other
);

foreach (@pamd){
    system "cp","/etc/pam.d/$_","/home/$chroot_rep/etc/pam.d";
}

# Création des fichiers par défaut
{
open ETCPASSWD,"> /home/$chroot_rep/etc/passwd"
        or die "Impossible de créer le fichier : $!\n";

print ETCPASSWD "root:x:0:0::/:/bin/bash\n";

open ETCGROUP,"> /home/$chroot_rep/etc/group"
        or die "Impossible de créer le fichier : $!\n";

print ETCGROUP "root:x:0:\n"
}

III. Création d'utilisateurs


-le script useradd_prisonssh.pl

SYNOPSIS
# perl /chemin/vers/script/useradd_prisonssh.pl nom_utilisateur répertoire 
Pour le répertoire utilisez le nom du répertoire que vous avez créé avec le script prisonssh.pl (sans arborescence)
#! /usr/bin/perl 
#
use strict;use warnings;

die "Usage: \n\t$0 nom_utilisateur chroot-dir\n" unless @ARGV == 2;

my $user = $ARGV[0];
my $chroot = "/home/$ARGV[1]";

system "groupadd", "$user";
system "useradd", "-d", "$chroot/./home/$user", "-g", "$user", "-m", "-s", "/bin/bash", "$user";

open PASSWD,">>$chroot/etc/passwd"
        or die "E/S : $!\n";

#
my ($u) = grep { /$user/ } `cat /etc/passwd`;
$u =~ s/[^:]*\.//;

print PASSWD $u;

#
open GROUP,">>$chroot/etc/group"
         or die "E/S : $!\n";

print GROUP grep { /$user/ } `cat /etc/group`;

#
chmod 0700, "$chroot/home/$user";
system "chown", "-R", "$user:$user", "$chroot/home/$user";

#
print "Entre le mot de passe pour $user\n";

system "passwd", "$user";

print "L'utilisateur < $user > à été créé avec succés.\n";
 

IV. Les mains dans les cambouis ou un coup d'oeil sous le capot


Que ce passe-t-il en fait ?

Le patch qu'on applique à openssh permet de créer cet environnement qu'on peut appeler une prison.

Il s'agit en fait d'une mini arborescence linux qui se trouvera dans le répertoire /home.
Cette arborescence contient les répertoires et les programmes nécessaires pour l'ouverture d'une connexion ne permettant pas de sortir de la prison (/home/prison)

Donc une fois connecté vous êtes emprisonné dans /home/prison qui est la racine / pour notre mini environnement grâce au patch qu'on a utilisé.

Si vous regardez le vrai fichier /etc/passwd vous allez remarquer que les utilisateurs créés avec le script useradd_prison.pl ont le répertoire home écrit avec la syntaxe suivante : /home/prison/./home/utilisateur.

Vous pouvez tester la connexion avec ssh -v utilisateur@localhost

Pour l'instant le fichier de configuration ( /usr/local/etc/sshd_config )
n'est pas modifié donc l'authentification se fera avec le mot de passe.

Si vous voulez une authentification par clé privée/publique
à vous de modifier le fichier de configuration.

Tout ce que j'ai décrit a été testé sous les distributions GNU/Linux :
Mandriva2006, Fedora5 et Debian Sarge 3.1 avec Perl version 5.8.4 et supérieure
 

V. Le patch osshChroot-4.3p1.diff


--- openssh-4.3p1/session.c	2005-12-24 04:59:12.000000000 +0100
+++ openssh-4.3p1-chroot/session.c	2006-02-02 13:39:03.000000000 +0100
@@ -59,6 +59,8 @@
 #include "kex.h"
 #include "monitor_wrap.h"
 
+#define CHROOT
+
 #if defined(KRB5) && defined(USE_AFS)
 #include <kafs.h>
 #endif
@@ -1251,6 +1253,11 @@
 void
 do_setusercontext(struct passwd *pw)
 {
+#ifdef CHROOT
+       char *user_dir;
+       char *new_root;
+#endif /* CHROOT */
+
 #ifndef HAVE_CYGWIN
 	if (getuid() == 0 || geteuid() == 0)
 #endif /* HAVE_CYGWIN */
@@ -1308,6 +1315,27 @@
 			restore_uid();
 		}
 #endif
+
+#ifdef CHROOT
+       user_dir = xstrdup(pw->pw_dir);
+       new_root = user_dir + 1;
+
+       while((new_root = strchr(new_root, '.')) != NULL) {
+               new_root--;
+               if(strncmp(new_root, "/./", 3) == 0) {
+                       *new_root = '\0';
+                       new_root += 2;
+
+                       if(chroot(user_dir) != 0)
+                               fatal("Couldn't chroot to user's directory %s", user_dir);
+                       pw->pw_dir = new_root;
+                       break;
+               }
+
+               new_root += 2;
+       }
+#endif /* CHROOT */
+
 # ifdef USE_PAM
 		/*

 		 * PAM credentials may take the form of supplementary groups.

VI. Le patch osshChroot-4.5p1.diff


Original patch by Ricardo Cerqueira <rmcc@clix.pt>

Updated by Pierre Schiesser <pierre.schiesser@gmail.com> for OpenSSH-4.5p1

A patch to cause sshd to chroot when it encounters the magic token
'/./' in a users home directory. The directory portion before the
token is the directory to chroot() to, the portion after the
token is the user's home directory relative to the new root.

Patch source using: patch -p0 < /path/to/patch

Systems with a bad diff (doesn't understand -u or -N) should use gnu diff.
Solaris may store this as gdiff under /opt/sfw/bin. I can't say much about
other systems (unless you email me your experiences!).

================================================================================
--- openssh-4.5p1/session.c	2006-10-23 19:01:56.000000000 +0200
+++ openssh-4.5p1-chroot/session.c	2006-11-07 21:33:12.000000000 +0100
@@ -88,6 +88,8 @@
 #include "kex.h"
 #include "monitor_wrap.h"
 
+#define CHROOT
+
 #if defined(KRB5) && defined(USE_AFS)
 #include <kafs.h>
 #endif
@@ -1287,6 +1289,11 @@
 void
 do_setusercontext(struct passwd *pw)
 {
+#ifdef CHROOT
+       char *user_dir;
+       char *new_root;
+#endif /* CHROOT */
+
 #ifndef HAVE_CYGWIN
 	if (getuid() == 0 || geteuid() == 0)
 #endif /* HAVE_CYGWIN */
@@ -1344,6 +1351,27 @@
 			restore_uid();
 		}
 #endif
+
+#ifdef CHROOT
+       user_dir = xstrdup(pw->pw_dir);
+       new_root = user_dir + 1;
+
+       while((new_root = strchr(new_root, '.')) != NULL) {
+               new_root--;
+               if(strncmp(new_root, "/./", 3) == 0) {
+                       *new_root = '\0';
+                       new_root += 2;
+
+                       if(chroot(user_dir) != 0)
+                               fatal("Couldn't chroot to user's directory %s", user_dir);
+                       pw->pw_dir = new_root;
+                       break;
+               }
+
+               new_root += 2;
+       }
+#endif /* CHROOT */
+
 # ifdef USE_PAM
 		/*

 		 * PAM credentials may take the form of supplementary groups.


A voir également :

Ce document intitulé «  Linux - Création environnement OpenSSH-CHROOT  » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.