L'autorisation de lecture Unix est en fait la même que l'autorisation d'exécution, donc si par ex. un processus a un accès en écriture, il peut également exécuter le même fichier.
Cela peut être fait assez facilement: ce processus doit d'abord charger le contenu du fichier, qui doit être exécuté, dans un tampon. Ensuite, il appelle une fonction d'une bibliothèque partagée qui analyse l'ELF dans le tampon et le charge aux bonnes adresses (probablement en écrasant l'ancien processus comme d'habitude, lors de l'appel à execvp). Le code saute au point d'entrée du nouveau programme et il est en cours d'exécution.
Je suis sûr que Dennis Ritchie et Ken Thompson étaient au courant de ce problème. Alors pourquoi ont-ils même inventé cette autorisation, quelle est l'intention derrière elle et quel est son sens, si elle ne peut empêcher aucun processus de n'importe quel utilisateur ayant un accès en lecture de s'exécuter? Existe-t-il même un tel sens ou est-il superflu?
Cela pourrait-il même être un grave problème de sécurité, existe-t-il des systèmes qui dépendent de la puissance des autorisations rw- ou r--?
Il existe un moyen encore plus simple de contourner l'autorisation "exécuter": copiez le programme dans un répertoire que vous possédez et définissez le bit "exécuter".
L'autorisation "exécuter" n'est pas une mesure de sécurité. La sécurité est fournie à un niveau inférieur, le système d'exploitation limitant des actions spécifiques. Cela est dû au fait que, sur de nombreux systèmes de type Unix (en particulier à l'époque de Ritchie et Thompson), il est supposé que l'utilisateur est capable de créer ses propres programmes. Dans une telle situation, l'utilisation de l'autorisation "exécuter" comme mesure de sécurité est inutile, car l'utilisateur peut simplement créer sa propre copie d'un programme sensible.
Comme exemple concret, exécuter fdisk
en tant qu'utilisateur non privilégié pour essayer de brouiller la table de partition du disque dur:
$ /sbin/fdisk /dev/sda
Welcome to fdisk (util-linux 2.24.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
...
Changed type of partition 'Linux' to 'Hidden NTFS WinRE'.
Command (m for help): w
fdisk: failed to write disklabel: Bad file descriptor
Cette dernière ligne est fdisk
essayant d'obtenir un descripteur de fichier "d'écriture" pour le disque dur et échoue, car l'utilisateur que je suis en train d'exécuter n'a pas la permission de le faire.
Le but de l'autorisation "exécuter" est double: 1) pour indiquer au système d'exploitation quels fichiers sont des programmes et 2) pour indiquer à l'utilisateur quels programmes ils peuvent exécuter. Ces deux éléments sont consultatifs plutôt qu'obligatoires: vous pouvez créer un système d'exploitation parfaitement fonctionnel sans autorisation, mais cela améliore l'expérience utilisateur.
Comme le souligne R .., il y a un cas particulier où l'autorisation "exécuter" est utilisée pour la sécurité: lorsqu'un programme a également le bit "setuid" défini. Dans ce cas, l'autorisation "exécuter" peut être utilisée pour restreindre les personnes autorisées à exécuter le programme. Toute méthode de contournement de l'autorisation "exécuter" supprimera également le statut "setuid", il n'y a donc aucun risque de sécurité ici.
Vous pouvez définir le bit d'exécution, mais pas le bit de lecture, sur un fichier exécutable. De cette façon, personne ne pourra copier le fichier, mais les gens pourront quand même l'exécuter.
C'est tout à fait inutile aujourd'hui, car a) cela ne fonctionne que pour les programmes compilés, pas pour les scripts (sur la plupart des systèmes); b) de nos jours, avec 90% de tous les unix étant linux, les gens peuvent copier des exécutables de n'importe où, et c) l'espace disque qu'un exécutable copié prend n'a pas vraiment d'importance.
Pourtant, il y avait des utilisations pour cela dans l'ancien temps.
Le système Unix que j'utilisais à l'école, il y a 30 ans, était très limité en RAM et espace disque. Surtout, le
/usr/tmp
le système de fichiers était très petit, ce qui provoquait des problèmes lorsque quelqu'un tentait de compiler un grand programme. Bien sûr, les étudiants n'étaient pas censés écrire de "gros programmes" de toute façon; les grands programmes étaient généralement des codes source copiés de "quelque part". Beaucoup d'entre nous ont copié/usr/bin/cc
à/home/<myname>/cc
, et utilisédd
pour patcher le binaire à utiliser/tmp
au lieu de/usr/tmp
, qui était plus grand. Bien sûr, cela ne faisait qu'aggraver le problème - l'espace disque occupé par ces copies importait à l'époque, et maintenant/tmp
rempli régulièrement, empêchant les autres utilisateurs de même éditer leurs fichiers. Après avoir découvert ce qui s'est passé, les administrateurs système ont fait unchmod go-r /bin/* /usr/bin/*
qui "corrigeait" le problème et supprimait toutes nos copies du compilateur C.
Une autre utilisation consiste à indiquer au shell quels fichiers sont destinés à être exécutés et lesquels ne le sont pas. Vous ne voulez pas qu'un fichier texte aléatoire soit exécuté parce que vous avez tapé son nom; le bit x permet d'éviter cela. (De nos jours, le shell peut simplement regarder le début du fichier et l'exécuter uniquement s'il commence par #!
, mais cela a été introduit beaucoup plus tard). La fonction de complétion de bash
propose également des fichiers avec des bits exécutables uniquement lorsque vous tapez une commande.
Il existe une méthode prête à l'emploi pour exécuter un fichier arbitraire: passez-le comme argument à l'éditeur de liens dynamique (qui est l'interpréteur approprié pour un exécutable chargé dynamiquement). Par exemple. sous Linux,
cp /bin/ls /tmp/
chmod -x /tmp/ls
/lib/ld-linux.so.2 /tmp/ls
Cependant, cela vient avec la même restriction que la lecture du fichier et le passage au code: les bits setuid ne sont pas évalués.
Autrefois, nous avions souvent des binaires comme /bin/su
:
-rwsr-xr-- root wheel ... /bin/su
Seuls les membres du groupe wheel
, que les administrateurs système gardaient limités aux personnes connaissant le mot de passe root
, pourraient même exécuter la commande su
, donc même s'il y avait un dépassement de tampon dans ce binaire, permettant aux appelants de contourner la sécurité, l'exploit ne serait utilisable que par des personnes qui connaissent le mot de passe de toute façon.
Je suis surpris que personne d'autre n'ait fait référence à une autre utilisation des répertoires + x bit :. Peut-être que vous êtes après l'exécution de (exemple) quelque chose dans/bin (script Shell ou autre), mais il y a plus à exécuter des bits que des fichiers (bien sûr, un répertoire IS un fichier mais il est un autre type de fichier).
Si vous avez un accès + x sur un répertoire mais -r sur ce même répertoire, vous aurez alors les capacités suivantes:
Si toutefois vous avez -x et + r, vous pouvez effectuer les opérations suivantes:
Si vous avez + rx, vous pouvez faire tout cela (sauf que vous avez besoin de + w pour écrire dans le répertoire lui-même, c'est-à-dire créer de nouveaux fichiers; l'édition de fichiers fonctionne, la suppression ne fonctionne pas, la création ne fonctionne pas)
Et oui, cela signifie qu'il est possible que certaines personnes consultent ou modifient des fichiers, mais seulement si elles connaissent le chemin exact vers celui-ci (tant qu'elles ont les droits de modification, de toute façon). Et oui: ls est la liste et cela va pour la recherche dans les répertoires. Donc en résumé: exécuter un répertoire, c'est y changer (pour une raison quelconque). Bien sûr, ce sont les bits tous ensemble qui comptent vraiment.
Si, pour une raison quelconque, vous voulez garder le code binaire secret, vous pouvez rendre le programme exécutable sans être lisible. Cela n'est pas utile si ces utilisateurs ont un accès physique à la machine. Il n'est pas non plus utile si le code source ou binaire est largement disponible. Il s'agit donc d'un cas d'utilisation assez limité.
Si le programme a un bit setuid ou setgid, exécuter l'accès fait quelque chose de plus que ce qui peut être obtenu en lisant le binaire. Une approche consiste à créer un exécutable setuid qui n'est exécutable que pour un groupe spécifique. S'il était lisible par tout le monde, les personnes extérieures à ce groupe ne pouvaient toujours pas le copier et utiliser le bit setgid sur l'exécutable d'origine. (Bien que dans la plupart des cas, je préfère utiliser setgid que setuid, puis utiliser le groupe sur le répertoire pour contrôler qui peut accéder à l'exécutable.)
Habituellement, le bit exécutable est simplement utilisé pour indiquer quels fichiers sont des programmes en premier lieu. De cette façon, l'achèvement peut mieux fonctionner et vous n'exécutez pas d'exécutables indésirables par accident.
Si vous souhaitez empêcher les utilisateurs de copier un exécutable et de l'exécuter, vous pouvez monter les répertoires personnels avec noexec
. Pour que cela ait un sens, vous devez utiliser noexec
sur chaque système de fichiers, où l'utilisateur peut écrire n'importe quoi.
L'autorisation d'exécution du bit est vérifiée par le noyau lors de l'exécution de l'appel système exec (2) (et cousins). Vous en aurez besoin uniquement pour exécuter des programmes au niveau du noyau.
Seuls les programmes avec ce bit activé (selon ce qui vous frappe en tant que propriétaire, groupe ou autres est ce qui est vérifié) peuvent être exec () ed par le noyau.
Une autre chose différente est ce que fait le Shell lors de l'interprétation d'un script Shell ou Perl, ou tout autre interprète que vous pourriez avoir. Sur les scripts, le noyau vérifie le #!...
au début du fichier sous forme de nombre magique, et lance le shell indiqué ici (vous aurez également besoin d'une autorisation d'exécution pour le shell), et vous avez besoin lire les autorisations sur ce script, car le shell doit l'ouvrir et le lire pour être interprété. Pour les scripts Shell, vous aurez besoin d'une autorisation de lecture ainsi que d'une autorisation d'exécution. Mais pour les scripts Shell, vous seulement avez besoin d'une autorisation de lecture, car vous pouvez toujours exécuter un script Shell en exécutant le shell et passer le script Shell comme paramètre (ou fichier d'entrée)
Bien sûr, comme cela a été souligné, le bit d'exécution peut être contourné en copiant le programme et en le rendant exécutable, mais vous ne pourrez pas le copier si vous n'avez pas les autorisations de lecture pour faire cette copie (vous continuez pour pouvoir l'exécuter).
Essayez de changer (en tant que root bien sûr) les autorisations en ls (1) et faites-le 0111
(---x--x--x
) et essayez d'en faire une copie exécutable, et voyez comment vous ne pouvez pas obtenir votre copie exécutable, même si vous pouvez continuer à l'exécuter.
Sur les répertoires, exécuter bit signifie une chose différente. Le noyau utilise l'autorisation 'x
' lors de l'itération à travers le chemin (dans la fonction de noyau namei ()) donc si vous n'avez pas d'autorisations d'exécution sur un répertoire, vous ne pouvez pas non plus utiliser ni les fichiers qui y sont accessibles. Même vous pouvez lire le contenu d'un répertoire avec des autorisations de lecture, mais vous ne pouvez pas accéder aux fichiers qu'il contient. Ou au contraire, vous pouvez avoir des autorisations d'exécution sur un répertoire mais pas d'accès en lecture, et vous pourrez utiliser les fichiers à l'intérieur, mais vous ne pourrez pas voir le contenu du répertoire.