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