Pourquoi ai-je besoin de setuid (0) dans un programme C setuid-root qui appelle un programme administratif avec system ()?
-
20-08-2019 - |
Question
J'ai dû faire un bidouillage Linux sale à quelqu'un afin qu'il puisse démarrer une imprimante avec la commande shell cupsenable printername
tout en étant un utilisateur non root. Je ne voulais pas qu'ils puissent utiliser l'intégralité de la syntaxe cupsenable
en tant que racine. Je viens donc d'écrire un wrapper en C qui nettoie l'entrée dans argv[1]
et appelle system("cupsenable sanitizedprintername")
.
J'ai créé le programme setuid root, mais malgré cela, setuid(0)
a échoué avec & l'autorisation refusée & ";". Ensuite, j’ai inséré un system()
appel avant chmod u+s
et voilà, cela a fonctionné.
Ne tenez pas compte du fait qu’il existe un meilleur moyen de donner aux utilisateurs le contrôle de l’imprimante. Il y a probablement une meilleure façon. Ce qui m'intéresse, ce sont les subtilités de <=> vs. <=> vs. <=>. Pourquoi s'est-il comporté de cette façon?
La solution
De man system
:
N'utilisez pas
system()
à partir d'un programme disposant des privilèges set-user-id ou set-group-ID, car des valeurs étranges pour certaines variables d'environnement peuvent être utilisées pour nuire à l'intégrité du système. Utilisez plutôt la familleexec(3)
de fonctions, mais pasexeclp(3)
niexecvp(3)
. En fait,/bin/sh
ne fonctionnera pas correctement avec des programmes dotés des privilèges set-user-id ou set-group-ID sur les systèmes sur lesquelsman bash
est bash version 2, car bash 2 supprime les privilèges au démarrage.
Et de -p
:
Si le shell est démarré avec l'ID utilisateur effectif (groupe) différent de l'ID utilisateur réel (groupe) et que l'option
SHELLOPTS
n'est pas fournie, aucun fichier de démarrage n'est lu, les fonctions du shell ne sont pas héritées du environnement, lasetuid(0)
variable, si elle apparaît dans l'environnement, est ignorée et l'ID utilisateur effectif est défini sur l'ID utilisateur réel.
Il apparaît que votre <=> appel a contourné cette protection.