J'ai besoin d'exécuter un script bash en tant que root (Sudo sans mot de passe ou su non viable) et, comme vous ne pouvez pas définir de script sous Linux, j'ai pensé l'appeler à partir d'un exécutable et de créer it setuid:
$ cat wrapper.c
int main(void)
{
system("/bin/bash ./should_run_as_root.sh");
}
$ gcc -o wrapper wrapper.c
$ Sudo chown root wrapper
$ Sudo chmod ug+s wrapper
$ ll wrapper
-rwsr-sr-x 1 root users 6667 2009-02-17 11:11 wrapper
$
Cela fonctionne - comme dans exécute le script correctement - mais le script s'exécute en tant qu'utilisateur qui exécute "./wrapper".
Pourquoi? Et comment mettre en œuvre correctement cela?
Merci!
Etant donné que le bit suid
sur les exécutables ne modifie que l'UID effectif (EUID), l'exécutable s'exécutera sous le nom, et non le véritable UID (RUID) que getuid()
renvoie, et en plus de la restriction sur les scripts interprétés suid
(tout exécutable commençant par "#!
" ), certains shells tels que bash
comme mesure de sécurité supplémentaire ramèneront le EUID au RUID. Dans ce cas, vous devrez utiliser l'appel setuid(0)
dans le code C avant d'exécuter le script.
Consultez les pages man
des setuid
, seteuid
, getuid
et geteuid
pour connaître la sémantique exacte des UID réels et effectifs.
(WARNING) Bien sûr, c’est un point approprié pour mentionner que la restriction sur les scripts suid
dans de nombreux systèmes Unix, interpréteurs de commandes et interpréteurs, existe pour une raison: si le script n’est pas très prudent à propos de la désinfection de son entrée et de l'état de l'environnement lors de son exécution, ils sont dangereux et peuvent être exploités pour une escalade de sécurité. Alors soyez très prudent lorsque vous faites cela. Définissez l'accès à votre script et à votre wrapper aussi strict que possible, n'autorisez que l'exécution de ce script très spécifique et effacez l'environnement au sein de votre programme C avant de démarrer le script, en définissant des variables d'environnement telles que PATH
est nécessaire dans le bon ordre et pas de répertoires accessibles en écriture aux autres.
Une autre chose à noter ici est que la limitation ici provient de bash et non du système * nix lui-même. En réalité, Bash vérifie les scripts SUID pour les exécuter uniquement avec la racine EUID. Si vous prenez des coquillages plus vieux, vous obtiendrez souvent ce que vous vouliez sortir de la boîte. Par exemple, sh ne fait pas ce genre de vérifications:
$ cat wrapper.c
int main(void)
{
system("/bin/sh -c whoami");
}
$ ls -l wrapper
-rwsr-sr-x 1 root users 8887 Feb 17 14:15 wrapper
$ ./wrapper
root
Avec bash:
$ cat wrapper.c
int main(void)
{
system("/bin/bash -c whoami");
}
$ ls -l wrapper
-rwsr-sr-x 1 root users 8887 Feb 17 14:18 wrapper
$ ./wrapper
skinp
Néanmoins, la réponse de Tom est généralement la voie à suivre pour créer un wrapper pour les programmes racine SUID
Ajoutez le setuid (0) dans le script et compilez-le. Cela devrait fonctionner après cela.
$ cat wrapper.c
int main(void)
{
setuid(0);
system("/bin/bash ./should_run_as_root.sh");
}
$ gcc -o wrapper wrapper.c
$ Sudo chown root wrapper
$ Sudo chmod ug+s wrapper
$ ll wrapper
-rwsr-sr-x 1 root users 6667 2009-02-17 11:11 wrapper
$
Les exemples sont terriblement peu sûrs et permettent à toute personne disposant de deux connaissances d’exécuter le programme de son choix en tant qu’utilisateur setuid.
Ne passez jamais par un shell sans avoir au préalable assaini l'environnement. La plupart des exemples ci-dessous sont vulnérables à la configuration de IFS et de PATH avant de l'exécuter.
Pourquoi Sudo n'est-il pas viable? Cela évite les failles de sécurité telles que:
bash-3.2$ cat test
#!/bin/bash
echo ima Shell script durp durp
bash-3.2$ chmod +x test
bash-3.2$ ./test
heh heh
bash-3.2$
En raison de l’environnement mal assaini, par exemple dans ce cas:
export echo='() { builtin echo heh heh; }'
Sudo désinfecte ce cas, et peut-être d'autres cas Edge et autres pièges qu'il serait bon de ne pas écrire dans un wrapper suid personnalisé.