Subvertir l'indicateur d'exécution sur les systèmes Linux. Pourquoi est-ce possible?

23

En lisant ceci , j'ai trouvé l'exploit suivant:

% cp /usr/bin/id ~
% chmod -x ~/id
% ls -al ~/id
-rw-r--r-- 1 edd edd 22020 2012-08-01 15:06 /home/edd/id
% ~/id
zsh: permission denied: /home/edd/id
% /lib/ld-linux.so.2 ~/id
uid=1001(edd) gid=1001(edd) groups=1001(edd),1002(wheel)

Cet extrait montre que nous pouvons contourner trivialement les autorisations d'exécution du système de fichiers en tant qu'utilisateur normal non privilégié. J'ai exécuté cela sur un Ubuntu 12.04.

Alors que le chargeur Linux est un objet partagé selon le fichier (1), il possède également un point d'entrée qui permet de l'exécuter directement. Lorsqu'il est exécuté de cette manière, le chargeur Linux agit comme un interpréteur pour les binaires ELF.

Sur ma machine OpenBSD, cependant, cet exploit n'est pas efficace, car vous ne pouvez pas exécuter le chargeur en tant que programme. La page de manuel d'OpenBSD dit: "ld.so est lui-même un objet partagé qui est initialement chargé par le noyau.".

Essayez ceci sur Solaris 9 et vous obtiendrez une erreur de segmentation. Je ne sais pas ce qui se passe ailleurs.

Mes questions sont donc:

  • Pourquoi le chargeur Linux (lorsqu'il est exécuté directement) ne vérifie pas les attributs du système de fichiers avant d'interpréter un binaire ELF?
  • Pourquoi mettre en œuvre un mécanisme conçu pour interdire l'exécution de fichiers, s'il est si trivialement ignoré? Ai-je raté quelque chose?
Edd Barrett
la source
1
Aucune bonne raison, mais si vous avez déjà réussi à supprimer votre système libc(je l'ai fait une fois, en mettant à niveau une boîte Arch), vous serez reconnaissant pour cette petite bizarrerie.
new123456
1
@ new123456 oh mon dieu, le canal IRC après cette mise à niveau a été pénible.
Rob
C'est le chargeur , pas l'éditeur de liens.
Arrêtez de nuire à Monica

Réponses:

33

Le but de l' executeautorisation n'est pas d'empêcher l'exécution en général . C'est (1) d'indiquer aux programmes quels fichiers sont destinés à être exécutés, et (2) d'empêcher l'exécution en tant qu'utilisateur privilégié , lorsque le bit setuid (etc.) est spécifié.

Le hack de l'éditeur de liens est moins un exploit qu'il n'y paraît. Vous pouvez exécuter n'importe quel fichier non exécutable que vous êtes autorisé à lire encore plus facilement:

$ cp unexecutable_file ~/runme
$ chmod +x ~/runme
$ ~/runme

Voir cette discussion sur le forum Arch Linux .

En résumé:

Marquage des fichiers à exécuter

Lorsque vous écrivez un script shell, vous pouvez le marquer comme exécutable avec chmod +x. Cela indique à votre shell que vous avez l'intention qu'il soit exécutable (sinon, pour tout le shell sait, c'est juste un autre fichier texte brut). Le shell peut ensuite l'afficher dans la tabulation lorsque vous tapez ./Tab.

De même: les something.drépertoires (par exemple init.d) contiennent des scripts shell de démarrage ou de contrôle qui sont généralement exécutés automatiquement par les démons. Vous souhaiterez peut-être placer un commentaire ou un fichier README dans le répertoire en tant que fichier texte brut. Ou vous pouvez désactiver temporairement l'un des scripts. Vous pouvez le faire en effaçant le bit d'exécution pour ce fichier particulier. Cela indique au démon de l'ignorer.

Empêcher l'exécution privilégiée

Le setuidbit signifie que lorsque vous exécutez le fichier, il est exécuté en tant qu'utilisateur spécifié (par exemple, root).

Le message du forum l'explique bien:

Vous voulez qu'un exécutable soit setuid pour un utilisateur, mais vous voulez seulement que les personnes d'un groupe spécifique puissent l'exécuter en tant que setuid. Ils peuvent toujours l'exécuter en copiant, mais l'indicateur setuid est perdu, donc ils l'exécuteront eux-mêmes, plutôt que l'utilisateur qui possédait le fichier d'origine.

Escargot mécanique
la source
2
Merci - J'ai ignoré le fait que l'utilisateur peut copier n'importe quel fichier qu'il peut lire et donc choisir des autorisations arbitraires.
Edd Barrett
que diriez-vous des fichiers avec autorisation d'exécution mais sans autorisation de lecture?
Lie Ryan
@LieRyan Et eux?
Rétablir Monica
@BrendanLong: Vous ne pouvez évidemment pas les copier, vous ne pouvez donc pas modifier leurs autorisations. (Mais pourquoi vous voulez, je ne peux pas dire - la seule chose que vous puissiez faire avec la copie de toute façon est de supprimer l'autorisation d'exécution)
MSalters
9

Si vous avez accès en lecture à un fichier, vous pouvez toujours en faire une copie.

Si vous pouvez faire une copie personnelle, vous pouvez toujours marquer cette copie comme exécutable.

Cela n'explique pas le comportement de ld-linux mais indique qu'il ne s'agit peut-être pas d'une faille de sécurité très utile.

Si vous voulez une sécurité renforcée, pensez à SELinux

RedGrittyBrick
la source
C'est très vrai.
Edd Barrett
C'était juste une question conceptuelle. Je suppose que vous pouvez également définir nonexec sur les systèmes de fichiers.
Edd Barrett
2

En regardant la question un peu différemment: comme le dit Mechanical Snail, l'autorisation d'exécution sur un fichier n'est pas destinée à empêcher l'exécution. Cependant, l'option de système de fichiers "noexec" empêche l'exécution et n'est pas si facilement contournée (non prise en charge par tous les systèmes de fichiers, mais certainement par les plus populaires de Linux). Si l'administrateur voulait empêcher les utilisateurs d'exécuter leurs propres programmes, il pouvait spécifier l'option noexec sur les répertoires home et tmp, et sur tous les autres où les utilisateurs pouvaient créer des fichiers.

$ mount -o noexec /dev/sdd1 /test
$ cd /test
$ cp /usr/bin/id .
$ ./id
-bash: ./id: Permission denied

Apparemment, il était possible de contourner l'option noexec en utilisant l'astuce de chargeur mentionnée dans la question, mais cela a été corrigé dans le noyau quelques versions en arrière.

De http://linux.die.net/man/8/mount :

noexec

N'autorisez pas l'exécution directe de fichiers binaires sur le système de fichiers monté. (Jusqu'à récemment, il était de toute façon possible d'exécuter des binaires en utilisant une commande comme /lib/ld*.so / mnt / binary. Cette astuce échoue depuis Linux 2.4.25 / 2.6.0.)

Randy Orrison
la source