Rastreando executável sem permissões de leitura

17

Encontrei algum comportamento surpreendente no Ubuntu 14.04 ao usar straceum executável, no qual não tenho permissão de leitura. Gostaria de saber se isso é um bug ou se algum padrão exige esse comportamento obscuro.

Primeiro vamos ver o que acontece quando inicio um executável comum em segundo plano e o anexo a ele. Como esperado, isso funciona:

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

Em seguida, tento com um executável, no qual não tenho permissão de leitura:

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

Anexar a este processo em execução não é permitido:

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

Isso também é o que eu esperaria. Conceder permissão de execução sem permissão de leitura não faria muito bem, se eu pudesse simplesmente anexar um depurador ao processo e efetivamente ter permissões de leitura no executável dessa maneira.

Mas se eu iniciar o executável em um processo já rastreado, tenho permissão para fazê-lo:

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

Isso é inesperado para mim. Isso é um bug de segurança ou é um recurso exigido por um padrão?

Kasperd
fonte
3
@ StéphaneChazelas: O ponto é que ele pode rastrear, simplesmente usando-o como argumento para rastrear. A causa raiz parece ser que, nas execvechamadas, as permissões de leitura do arquivo executado não são verificadas novamente se o processo já estiver rastreado. Sua pergunta é se isso é um bug de segurança ou um recurso obrigatório (se este último, eu ainda consideraria um bug de segurança, apenas um bug de segurança da especificação).
Celtschk 3/09/14
@celtschk, desculpe, eu li a pergunta muito rapidamente.
Stéphane Chazelas
1
O EPERMparece vir de get_dumpable()(usado também para verificar se o dumping núcleo é permitido, portanto, "dumpable") chamado a partir __ptrace_may_access()chamado de ptrace_attach()on kernel/ptrace.c.
ninjalj
Quando um programa está sendo executado, informações suficientes estarão disponíveis para o depurador para gerar um executável executável que contenha seu código ou o carregador do programa descartará coisas como correções de realocação que seriam necessárias para que um programa realmente funcionasse?
Supercat 03/09
@supercat Até onde eu sei, o depurador tem acesso a uma única etapa através de todo o código do modo de usuário que está sendo executado, incluindo o código de realocação. Com esse nível de acesso, não deve ser muito difícil reproduzir um executável em funcionamento.
precisa saber é

Respostas:

7

Esta não é uma resposta, mas uma coleção de links e pensamentos, caso outra pessoa também queira estudar. Porque isso é uma coisa bastante interessante.

Resposta relacionada no Unix e Linux mencionando que é (ou foi, não é possível testar com o kernel da baunilha agora) possível despejar binários somente leitura dessa maneira.

O Grsecurity estava tentando corrigir esta opção de configuração e o próprio patch (embora possa ter sido alterado desde então)

Esse commit realmente faz parecer que, os desenvolvedores do kernel realmente se preocupam apenas com o despejo de binários suid.

Mas, a partir dessa linha, eu acho que o kernel quer impedir o despejo de binários ilegíveis em relação ao status do SUID. E essa linha sugere que os binários que não são despejáveis ​​não devem ser rastreáveis.

Então, à primeira vista, parece que você encontrou um bug no kernel com implicações de segurança. Mas eu não sou desenvolvedor de kernel, então não posso dizer com certeza. Eu perguntaria no LKML.

Edit: mais uma descoberta, com relação ao depurador, mencionada nos comentários da postagem original - do rastreamento rápido (novamente) me parece que o gdb usa os binários rastreados e /proc/<pid>/mem. Quando o binário em execução não estiver legível, cat /proc/<pid>/memretornará EPERM. Se o binário estiver legível, ele retornará EIO. (Testei isso no Ubuntu 14.10, que executa várias correções de segurança, portanto, isso pode ser diferente do kernel da baunilha. Novamente, não tenho o kernel da baunilha sendo executado em qualquer lugar útil :()

Raposa
fonte