Linux ignore le bit setuid¹ sur tous les exécutables interprétés (c'est-à-dire les exécutables commençant par une #!
ligne). La FAQ comp.unix.questions explique les problèmes de sécurité liés aux scripts du shell setuid. Ces problèmes sont de deux types: liés au shebang et liés au shell; Je vais dans plus de détails ci-dessous.
Si vous ne vous souciez pas de la sécurité et souhaitez autoriser les scripts setuid, sous Linux, vous devrez patcher le noyau. À partir des noyaux 3.x, je pense que vous devez ajouter un appel à install_exec_creds
dans la load_script
fonction, avant l'appel à open_exec
, mais je n'ai pas encore testé.
Setuid shebang
Il existe une condition de concurrence inhérente à la manière dont shebang ( #!
) est généralement implémentée:
- Le noyau ouvre l'exécutable et constate qu'il commence par
#!
.
- Le noyau ferme l'exécutable et ouvre l'interpréteur.
- Le noyau insère le chemin du script dans la liste d'arguments (as
argv[1]
) et exécute l'interpréteur.
Si les scripts setuid sont autorisés avec cette implémentation, un attaquant peut invoquer un script arbitraire en créant un lien symbolique vers un script setuid existant, en l'exécutant et en prévoyant de modifier le lien après que le noyau a exécuté l'étape 1 et avant que l'interpréteur ne le ouvrant son premier argument. Pour cette raison, la plupart des utilisateurs ignorent le bit setuid lorsqu'ils détectent un shebang.
Un moyen de sécuriser cette implémentation serait que le noyau verrouille le fichier de script jusqu'à ce que l'interpréteur l'ait ouvert (notez que cela doit empêcher non seulement la suppression de la liaison ou le remplacement du fichier, mais également le changement de nom du répertoire dans le chemin). Mais les systèmes Unix ont tendance à éviter les verrous obligatoires, et les liens symboliques rendraient une fonction de verrouillage correcte particulièrement difficile et invasive. Je pense que personne ne le fait de cette façon.
Quelques systèmes unix (principalement OpenBSD, NetBSD et Mac OS X, qui tous nécessitent un réglage du noyau à activer) mettre en œuvre le tralala setuid sécurisé à l' aide d' une fonction supplémentaire: le chemin fait référence au fichier déjà ouvert le descripteur de fichier N (si l' ouverture est à peu près équivalent à ). Beaucoup de systèmes Unix (y compris Linux) ont des scripts setuid mais pas encore./dev/fd/N
/dev/fd/N
dup(N)
/dev/fd
- Le noyau ouvre l'exécutable et constate qu'il commence par
#!
. Disons que le descripteur de fichier pour l'exécutable est 3.
- Le noyau ouvre l'interpréteur.
- Le noyau insère
/dev/fd/3
la liste d'arguments (as argv[1]
) et exécute l'interpréteur.
La page shebang de Sven Mascheck contient de nombreuses informations sur les shebang à travers les unités, y compris le support setuid .
Interprètes Setuid
Supposons que vous avez réussi à exécuter votre programme en tant que root, soit parce que votre système d'exploitation prend en charge setuid shebang, soit parce que vous avez utilisé un wrapper binaire natif (tel que sudo
). Avez-vous ouvert un trou de sécurité? Peut - être . Le problème ici ne concerne pas les programmes interprétés vs compilés. Le problème est de savoir si votre système d'exécution se comporte de manière sécurisée s'il est exécuté avec des privilèges.
Tout exécutable binaire natif lié dynamiquement est en quelque sorte interprété par le chargeur dynamique (par exemple /lib/ld.so
), qui charge les bibliothèques dynamiques requises par le programme. Sur de nombreux ordinateurs, vous pouvez configurer le chemin de recherche pour les bibliothèques dynamiques via l'environnement ( LD_LIBRARY_PATH
nom commun de la variable d'environnement) et même charger des bibliothèques supplémentaires dans tous les fichiers binaires exécutés ( LD_PRELOAD
). Le invocateur du programme peut exécuter du code arbitraire dans le contexte de ce programme en plaçant un spécialement conçu libc.so
dans $LD_LIBRARY_PATH
(entre autres tactiques). Tous les systèmes sains ignorent les LD_*
variables des exécutables setuid.
Dans les shells tels que sh, csh et dérivés, les variables d'environnement deviennent automatiquement des paramètres de shell. Par le biais de paramètres tels que PATH
, IFS
et bien d’autres, l’invocateur du script offre de nombreuses possibilités d’exécuter du code arbitraire dans le contexte des scripts shell. Certains shells définissent ces variables sur les valeurs par défaut sane s'ils détectent que le script a été appelé avec des privilèges, mais je ne sais pas qu'il existe une implémentation particulière à laquelle je ferais confiance.
La plupart des environnements d'exécution (natifs, en bytecode ou interprétés) ont des fonctionnalités similaires. Peu prennent des précautions spéciales dans les exécutables setuid, bien que ceux qui exécutent du code natif ne fassent souvent rien de plus fantaisiste que la liaison dynamique (qui prend des précautions).
Perl est une exception notable. Il supporte explicitement les scripts setuid de manière sécurisée. En fait, votre script peut exécuter setuid même si votre système d'exploitation a ignoré le bit setuid dans les scripts. En effet, perl est livré avec un assistant setuid root qui effectue les vérifications nécessaires et réinvoque l'interpréteur sur les scripts souhaités avec les privilèges souhaités. Ceci est expliqué dans le manuel perlsec . Il fut un temps que les scripts Perl setuid nécessaires au #!/usr/bin/suidperl -wT
lieu de #!/usr/bin/perl -wT
, mais sur la plupart des systèmes modernes, #!/usr/bin/perl -wT
est suffisante.
Notez que l'utilisation d'un wrapper binaire natif ne fait rien pour empêcher ces problèmes . En fait, il peut rendre la situation pire , car il pourrait empêcher votre environnement d'exécution de détecter qu'il est invoqué avec les privilèges et sans passer par son configurabilité d'exécution.
Un wrapper binaire natif peut sécuriser un script shell s'il désinfecte l'environnement . Le script doit veiller à ne pas faire trop d'hypothèses (par exemple sur le répertoire en cours), mais cela va. Vous pouvez utiliser sudo à cet effet, à condition qu'il soit configuré pour assainir l'environnement. La mise en liste noire des variables est sujette aux erreurs, il faut donc toujours la liste blanche. Sudo, assurez - vous que l' env_reset
option est activée, setenv
c'est hors tension, et que env_file
et env_keep
uniquement contenir des variables anodines.
TL, DR:
- Setuid Shebang n'est pas sécurisé mais est généralement ignoré.
- Si vous exécutez un programme avec des privilèges (via sudo ou setuid), écrivez du code natif ou perl, ou démarrez le programme avec un wrapper qui assainit l'environnement (tel que sudo avec l'
env_reset
option).
¹ Cette discussion s’applique également si vous remplacez «setuid» par «setgid»; ils sont tous deux ignorés par le noyau Linux dans les scripts
suidperl
matériel est déconseillé et doit être retiré depuis des années (mais il persiste non-moins)suidperl
a été supprimé à partir de perl 5.11 (version stable 5.12): perl5110delta:> "suidperl" a été supprimé. Auparavant, il fournissait un mécanisme pour émuler les bits d'autorisation setuid sur des systèmes qui ne le supportaient pas correctement. perl5120delta:> "suidperl" ne fait plus partie de Perl. Auparavant, il fournissait un mécanisme pour émuler les bits d'autorisation setuid sur des systèmes qui ne le supportaient pas correctement.Un moyen de résoudre ce problème consiste à appeler le script shell à partir d'un programme pouvant utiliser le bit setuid.
c'est quelque chose comme sudo. Par exemple, voici comment procéder dans un programme C:
Enregistrez-le sous le nom setuid-test2.c.
compiler
Maintenant, faites le setuid sur ce programme binaire:
Maintenant, vous devriez être capable de l'exécuter et vous verrez que votre script est exécuté avec aucune permission.
Mais ici aussi, vous devez soit coder en dur le chemin du script, soit le transmettre comme argument de ligne de commande à un fichier exe.
la source
PATH
etLD_LIBRARY_PATH
sont des vecteurs évidents. Quelques coquilles exécutent$ENV
ou$BASHENV
ou~/.zshenv
même avant de commencer l' exécution correcte, le script de sorte que vous ne pouvez pas protéger de ces tout dans le script. Le seul moyen sûr d'appeler un script shell avec des privilèges est de nettoyer l'environnement . Sudo sait comment le faire en toute sécurité. Alors n'écrivez pas votre propre wrapper, utilisez sudo .LD_LIBRARY_PATH
entre autres lorsqu’il rencontre le bit setuid.system
, vous pouvez trouver qu'il est plus simple (et plus efficace) d'utiliser l'un des membres de laexec
famille, probablementexecve
. Ainsi, vous ne créez pas de nouveau processus ni démarrez un shell, vous pouvez également transférer des arguments (en supposant que votre script privilégié puisse gérer les arguments en toute sécurité).Je préfixe quelques scripts qui sont dans ce bateau ainsi:
Notez que ceci n'utilise pas
setuid
mais exécute simplement le fichier actuel avecsudo
.la source
sudo
invite. (Pour moi, le but de setuid est de permettre aux choses de fonctionner en tant que root sans avoir besoin de sudo.)Si vous voulez éviter d'appeler,
sudo some_script
vous pouvez simplement faire:Les programmes SETUID doivent être conçus avec un soin extrême car ils s'exécutent avec les privilèges root et que les utilisateurs ont un grand contrôle sur eux. Ils doivent tout contrôler. Vous ne pouvez pas le faire avec des scripts car:
sed
,awk
etc. devraient également être vérifiésS'il vous plaît noter que
sudo
fournit une certaine vérification de la santé mentale, mais cela ne suffit pas - vérifiez chaque ligne dans votre propre code.Dernière remarque: envisagez d'utiliser les capacités. Ils vous permettent d'accorder à un processus exécuté en tant qu'utilisateur des privilèges spéciaux nécessitant normalement des privilèges root. Cependant, par exemple, même s'il
ping
doit manipuler le réseau, il n'a pas besoin d'avoir accès aux fichiers. Je ne suis pas sûr cependant si elles sont héritées.la source
/ust/bin/env
devrait être/usr/bin/env
.Vous pouvez créer un alias pour sudo + le nom du script. Bien sûr, cela demande encore plus de travail, car vous devez également configurer un alias, mais vous évitez de taper sudo.
Mais si vous ne craignez pas d’horribles risques pour la sécurité, utilisez un shell setuid comme interprète du script shell. Je ne sais pas si cela fonctionnera pour vous, mais j'imagine que ça pourrait l'être.
Permettez-moi de dire que je déconseille de faire cela, cependant. Je le mentionne simplement à des fins éducatives ;-)
la source
rm -rf /
(et d'autres commandes de la série NE LE FAITES PAS À LA MAISON ).super [-r reqpath] commande [args]
Super permet aux utilisateurs spécifiés d'exécuter des scripts (ou d'autres commandes) comme s'ils étaient root; ou il peut définir les groupes uid, gid et / ou supplémentaires, commande par commande, avant l'exécution de la commande. Il s'agit d'une alternative sécurisée à la création de scripts setuid root. Super permet également aux utilisateurs ordinaires de fournir des commandes à exécuter par d’autres utilisateurs; ceux-ci s'exécutent avec les uid, gid et les groupes de l'utilisateur offrant la commande.
Super consulte un fichier `` super.tab '' pour voir si l'utilisateur est autorisé à exécuter la commande demandée. Si l'autorisation est accordée, super exécutera pgm [args], où pgm est le programme associé à cette commande. (La racine est autorisée à exécuter par défaut, mais peut toujours être refusée si une règle exclut la racine. Les utilisateurs ordinaires sont interdits à l'exécution par défaut.)
Si commande est un lien symbolique (ou un lien physique) avec le super programme, taper% command args équivaut à taper% super commande args (la commande ne doit pas être super, sinon super ne reconnaîtra pas qu’elle est invoquée via un lien.)
http://www.ucolick.org/~will/RUE/super/README
http://manpages.ubuntu.com/manpages/utopic/fr/man1/super.1.html
la source
Si pour une raison quelconque
sudo
n'est pas disponible, vous pouvez écrire un script wrapper en C:Et une fois que vous compilez le définir comme
setuid
avecchmod 4511 wrapper_script
.Cela ressemble à une autre réponse publiée, mais le script est exécuté avec un environnement propre et utilise explicitement à la
/bin/bash
place du shell appelé parsystem()
, ce qui ferme certaines failles de sécurité potentielles.Notez que ceci élimine complètement l'environnement. Si vous souhaitez utiliser certaines variables d'environnement sans ouvrir de vulnérabilités, vous devez simplement les utiliser
sudo
.De toute évidence, vous voulez vous assurer que le script lui-même ne peut être écrit que par root.
la source
J'ai d'abord trouvé cette question, non convaincue par toutes les réponses, en voici une bien meilleure, qui vous permet également de masquer complètement votre script bash, si vous le souhaitez!
Cela devrait être explicite.
Alors tu cours
la source