sh vs bash

J’écris cet article car j’ai constaté à deux reprises un comportement que je ne comprenais pas. L’appel système

execve("/bin/sh", NULL, NULL)

me lançait un terminal bash au lieu de sh. Comme j’étais en phase d’exploitation avec une élévation de privilèges, et comme bash drop les droits par défault, je me retrouvais avec un shell qui n’avait plus les droits du binaire.

Voici alors un petit post qui me servira plus de rappel à moi-même qu’autre chose. Les deux ressources citées en fin d’article vous permettront d’aller voir un peu plus loin.

sh est un langage de programmation décrit par le standard POSIX. Il possède plusieurs implémentations telles que dash, ksh etc. Ainsi, dans la plupart des systèmes d’exploitation, sh n’étant pas une implémentation, /bin/sh est un lien symbolique vers une implémentation, souvent /bin/bash.

Dans mon système d’exploitation actuel, je peux le voir

/bin/sh -> bash*

bash est donc une implémentation de sh, cependant beaucoup de modules/extensions y ont été ajoutés. Lorsqu’on fait un appel à /bin/bash, nous avons l’implémentation de sh avec tout un tas d’extensions.

Cependant, le binaire /bin/bash a implémenté une vérification sur argv[0] (contenant la ligne de commande qui a appelé le binaire). Si le binaire a été appelé via /bin/sh, alors /bin/bash va essayer d’imiter le comportement des versions historiques de sh. Les extensions de démarrage de bash ne seront pas chargées, notamment celle qui fait perdre l’élévation des droits suite à une exécution d’un binaire possédant le bit SUID.

Voici quelques exemples

# Appel via sh
$ /bin/sh
sh-3.4 $ 

# Appel via bash
$ /bin/bash
bash-4.3 $ 

# Appel système execve("/bin/sh", NULL, NULL)
bash-4.3 $ 

# Appel système execve("/bin/sh", ["/bin/sh"], NULL)
sh-3.4 $ 

Vous voyez bien avec ces différents exemples que lorsque le binaire bash est exécuté, si jamais argv[0] contient le chemin vers sh alors nous avons une imitation du comportement historique de sh qui est exécutée. Dans le cas contraire, c’est bien le binaire bash et toutes ses extensions qui est exécuté.

Voilà pourquoi je perdais les droits pendant mes exploitations. Il me suffit alors de faire en sorte que le deuxième argument de execve pointe vers un tableau contenant une chaîne de caractères : "/bin/sh".

Références