Linux - Criação de um ambiente OpenSSH-CHROOT
Mais uma vez agradeço à jipicy por sua disponibilidade e sua paciência para as correções lingüística.
Criação de um repertório para o download dos arquivos
$ 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
Parece que o patch não é disponível no endereço indicado. Olhe mais abaixo (Chap V. )
Nós estamos no /home/lami20j/prisonssh e, veja ali, o que o diretório contém :
$ 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 são os dois scripts Perl que veremos mais abaixo.
Verificação da assinatura
$ gpg --keyserver pgp.mit.edu --recv-keys 0x86FF9C48 gpg: consulta da chave 86FF9C48 do servidor hkp pgp.mit.edu gpg: clé 86FF9C48: nome de usuário duplo detectado - fusão com sucesso gpg: clé 86FF9C48: chave publica « Damien Miller (Personal Key) » importada gpg: nenhuma chave de confiança última não foi encontrada. gpg: Quantidade tratada : 1 gpg: importada: 1 $ gpg --fingerprint 86FF9C48 pub 1024D/86FF9C48 2001-02-26 Impressão da chave = 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: Assinatura feita quart feira 01 fév 2006 12:34:31 CET com a chave DSA ID 86FF9C48 gpg: Boa assinatura de « Damien Miller (Personal Key) » gpg: Atenção : Esta chave não é certificada com uma assinatura de confiança ! gpg: Nada diz que a assinatura pertence ao seu proprietário. Impressão da chave principal : 3981 992A 1523 ABA0 79DB FC66 CE8E CB03 86FF 9C48
Supressão dos pacotes instalados.
Debian :
# apt-get remove --purge ssh
Mandriva2006 et Fedora :
# for i in $(rpm -qa | grep openssh);do rpm --nodeps -e $i;done
Dependências exigidas: zlib et openssl
Leia o arquivo README para maiores detalhes. code>$ 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</code>
Com seu editor de texto preferido, criar o arquivo /etc/init.d/sshd
E escreva o seguinte script.
Depois da edição do arquivo terminado, registre e feche.
#!/bin/bash case $1 in 'start' ) /usr/local/sbin/sshd ;; 'stop' ) pkill sshd ;;
echo "usage : /etc/init.d/sshd {start|stop}" ;; esac
Estabeleça os direitos com o comando
# chmod -v 0755 /etc/init.d/sshd
Se o usuário sshd não existe, você pode cria-lo com o comando :
# useradd -c 'Privilege-separated SSH' -d /var/empty/sshd -s /sbin/nologin sshd
Lancçar o daemon
# /etc/init.d/sshd start
Para que o arranque do daemon seja levado em consideração no arranque do PC feito :
# update-rc.d sshd start 99 2 3 4 5 .
- o script prisonssh.pl
SYNOPSIS
# perl /caminho/para/script/prisonssh.pl
Na solicitação do diretório coloque o nome de sua escolha.
O diretório sera criado no /home
#! /usr/bin/perl # use strict; use warnings; use File::Basename; my (@lib,@ldd,%listreplib); # criação do diretório print "Entre o nome de diretório: "; chomp(my $chroot_rep=<STDIN>); mkdir '/home/'.$chroot_rep or die "Impossível de criar o diretório: $!"; # Os aplicativos de ambiente chroot # # Assegure--se que o caminho das aplicações mencionadas corresponde # # Por exemplo o comando id # na Debian e Fedora5 o encontramos no /usr/bin # # no Mandriva 2006 no /bin # # cabe à você adicionar ou tirar aplicações # e, é claro, modificar o script # # as aplicações (/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 ); # as aplicações (/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 ); # o sub sistema sftp my @sftp_server=qw ( /usr/local/libexec/sftp-server ); # recuperar as bibliotecas foreach (@apps0,@apps1,@sftp_server){ my $ldd='ldd $_'; my @temp=split /\n/, $ldd; push @ldd,@temp; } # recuperar o caminho de cada biblioteca foreach(@ldd){ if ( $_=~/(?:\/?.*=>\s*)?(\/.*)\b\s*\(/ ){ print "$1\n"; push @lib,$1 if $1 !~ /^\s*$/; } } # os diretórios à criar (/lib,/usr/lib,etc...) foreach(@lib){ my $replib=dirname($_); $listreplib{$replib} +=1; } # criação dos diretórios no ambiente chroot foreach (keys %listreplib){ system "mkdir","-p","/home/$chroot_rep/$_"; } # criação do diretório bin no ambiente 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/$_"; } # copiar as aplicações no diretório /bin do ambiente chroot foreach(@apps0){ system "cp","-p","$_","/home/$chroot_rep/bin"; } # copiar as aplicações nos diretórios /usr/bin do ambiente chroot foreach(@apps1){ next if /.*sftp-server.*/i; system "cp","-p","$_","/home/$chroot_rep/usr/bin"; } # copiar sftp-server system "cp","-p","/usr/local/libexec/sftp-server","/home/$chroot_rep/usr/local/libexec"; # copiar as bibliotecas foreach (@lib){ my $rep_lib=dirname($_); system "cp","-p","$_","/home/$chroot_rep/$rep_lib"; } opendir (LIBNSS,"/lib") or die "Impossível de abrir o diretório: $!"; 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"; } # Criação dos arquivos padrão { open ETCPASSWD,"> /home/$chroot_rep/etc/passwd" or die "Impossível de criar o arquivo: $!\n"; print ETCPASSWD "root:x:0:0::/:/bin/bash\n"; open ETCGROUP,"> /home/$chroot_rep/etc/group" or die "Impossível de criar o arquivo: $!\n"; print ETCGROUP "root:x:0:\n" }
-o script useradd_prisonssh.pl
SYNOPSIS
# perl /chemin/vers/script/useradd_prisonssh.pl nome_usuário diretório
Para o diretório utilize o nome do diretório que você cria com o script prisonssh.pl (sem areborescência)
#! /usr/bin/perl # use strict;use warnings; die "Uso: \n\t$0 nome_usurio 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 a senha para $user\n"; system "passwd", "$user"; print "O usuário < $user > foi criado com sucesso.\n";
O acontece afinal de contas?
O patch que se aplica para permiter à openssh criar este ambiente e que se pode chamar uma prisão.
Trata-se de uma mini arborescência Linux que se encontrará no diretório/home.
Esta arborescência contém os diretórios e os programas necessários para abertura de uma conexão que não permite sair da (/home/prison)
Então depois de estar conectado você está preso em /home/prison qui est la racine / para nosso mini ambiente graças ao patch que se utilizou.
Se você olhar o verdadeiro arquivo /etc/passwd você irá perceber que os usuários criados com o script useradd_prison.pl tem o diretório home escrito com a seguinte sintaxe: /home/prisão/./home/usuário.
Você pode testar a conexão com ssh -v usuário@localhost
Até o momento o arquivo de configuração ( /usr/local/etc/sshd_config )
Não foi modificado, então a autenticação se fera com a senha.
Se você quer uma autenticação para a chave privada/publica.
Cabe à você modificar o arquivo de modificação.
Tudo o que eu descrevi foi testado nas distribuições GNU/Linux :
Mandriva2006, Fedora5 e Debian Sarge 3.1 com Perl versão 5.8.4 e superior
--- 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 /*
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 /*
Tradução feita por Ana Spadari