Traçage de l'exécutable sans autorisations de lecture


17

J'ai trouvé un comportement surprenant sur Ubuntu 14.04 lors de l'utilisation stracesur un exécutable, sur lequel je n'ai pas d'autorisation de lecture. Je me demande s'il s'agit d'un bug, ou si une norme impose ce comportement obscur.

Voyons d'abord ce qui se passe lorsque je démarre un exécutable ordinaire en arrière-plan et que je l'attache. Comme prévu, cela fonctionne:

$ /bin/sleep 100 &
[2] 8078
$ strace -p 8078
Process 8078 attached
restart_syscall(<... resuming interrupted call ...>

Ensuite, j'essaie avec un exécutable, sur lequel je n'ai aucune autorisation de lecture:

---x--x--x 1 root root 26280 Sep  3 09:37 sleep*

La connexion à ce processus en cours n'est pas autorisée:

$ ./sleep 100 &
[1] 8089
$ strace -p 8089
strace: attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted

C'est aussi ce à quoi je m'attendrais. Accorder une autorisation d'exécution sans autorisation de lecture ne serait pas très utile si je pouvais simplement attacher un débogueur au processus et avoir effectivement des autorisations de lecture sur l'exécutable de cette façon.

Mais si je démarre l'exécutable dans le cadre d'un processus déjà tracé, je suis autorisé à le faire:

$ strace ./sleep 100
execve("./sleep", ["./sleep", "100"], [/* 69 vars */]) = 0
brk(0)                                  = 0x9b7a000

C'est inattendu pour moi. S'agit-il d'un bogue de sécurité ou s'agit-il d'une fonctionnalité mandatée par une norme?


3
@ StéphaneChazelas: Le fait est qu'il peut le retracer, simplement en l'utilisant comme argument pour le caler. La cause première semble être que lors des execveappels, les autorisations de lecture du fichier exécuté ne sont pas vérifiées à nouveau si le processus est déjà tracé. Sa question est de savoir si c'est un problème de sécurité ou d' une fonction obligatoire (si celui - ci, je considère qu'il est encore un bug de sécurité, juste un bug de sécurité de la spécification).
celtschk

@celtschk, désolé, j'ai lu la question trop rapidement.
Stéphane Chazelas

1
Le EPERMsemble provenir get_dumpable()(également utilisé pour vérifier si le dumping est autorisé noyau, donc « dumpable ») appelé à partir __ptrace_may_access()appelée à partir ptrace_attach()de kernel/ptrace.c.
ninjalj

Lorsqu'un programme est en cours d'exécution, le débogueur disposera-t-il d'informations suffisantes pour générer un exécutable exécutable contenant son code, ou le chargeur de programme rejettera-t-il des éléments comme les corrections de relocalisation qui seraient nécessaires pour faire fonctionner un programme?
supercat

@supercat Pour autant que je sache, le débogueur a accès à une seule étape à travers tout le code du mode utilisateur en cours d'exécution, y compris le code de relocalisation. Avec ce niveau d'accès, il ne devrait pas être trop difficile de reproduire un exécutable fonctionnel.
kasperd

Réponses:


7

Ce n'est pas une réponse, mais plutôt un ensemble de liens et de réflexions au cas où quelqu'un d'autre aimerait également étudier. Parce que c'est une chose assez intéressante.

Réponse connexe sur Unix et Linux mentionnant qu'il est (ou était, ne peut pas tester avec le noyau vanilla en ce moment) possible de vider les binaires en lecture seule de cette façon.

Grsecurity essayait de corriger cette option de configuration et le correctif lui-même (bien qu'il ait peut-être changé depuis)

Cette validation donne vraiment l'impression que les développeurs du noyau ne se soucient vraiment que de vider les binaires suid.

Mais en fait, à partir de cette ligne, je suppose que le noyau veut empêcher le dumping des fichiers binaires illisibles du statut SUID. Et cette ligne suggère que les binaires qui ne sont pas vidables ne devraient pas être traçables.

Donc, à première vue, il semble que vous ayez trouvé un bogue dans le noyau avec des implications de sécurité. Mais je ne suis pas développeur de noyau, donc je ne peux pas dire avec certitude. Je demanderais sur LKML.

Edit: une conclusion de plus, en ce qui concerne le débogueur, mentionnée dans les commentaires au message d'origine - à partir d'un stracing rapide (encore), il me semble que gdb utilise les binaires tracés et /proc/<pid>/mem. Une fois que le binaire en cours d'exécution n'est pas lisible, cat /proc/<pid>/memrevient EPERM. Si le binaire est lisible, il revient EIO. (Testé sur Ubuntu 14.10, qui exécute plusieurs correctifs de sécurité, donc cela pourrait être différent du noyau vanilla. Encore une fois, je n'ai pas de noyau vanilla en cours d'exécution à portée de main :()

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.