Subvertendo o sinalizador de execução em sistemas Linux. Por que isso é possível?

23

Ao ler este , encontrei a seguinte exploração:

% 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)

Este snippet mostra que podemos, de maneira trivial, deixar de lado as permissões de execução do sistema de arquivos como um usuário normal sem privilégios. Eu corri isso no Ubuntu 12.04.

Embora o carregador do Linux seja um objeto compartilhado de acordo com o arquivo (1), ele também possui um ponto de entrada que permite que ele seja executado diretamente. Quando executado dessa maneira, o carregador do Linux age como um interpretador para binários ELF.

Na minha máquina OpenBSD, no entanto, essa exploração não é eficaz, porque você não pode executar o carregador como um programa. A página de manual do OpenBSD diz: "ld.so é em si um objeto compartilhado que é inicialmente carregado pelo kernel.".

Tente isso no Solaris 9 e você receberá um segfault. Não tenho certeza do que acontece em outro lugar.

Minhas perguntas são, portanto:

  • Por que o carregador do Linux (quando executado diretamente) não verifica os atributos do sistema de arquivos antes de interpretar um binário ELF?
  • Por que implementar um mecanismo que é projetado não permitir a execução de arquivos, se ele é tão trivialmente evitado? Eu perdi alguma coisa?
por Edd Barrett 01.08.2012 / 16:22

3 respostas

32

O objetivo da permissão execute é não para impedir a execução em geral . É (1) informar aos progams quais arquivos devem ser executados e (2) impedir a execução como usuário privilegiado , quando o bit setuid (etc.) é especificado.

O hack de linker é menos explorador do que parece. Você pode executar qualquer arquivo não executável que tenha permissões para ler com mais facilidade:

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

Veja esta discussão no fórum Arch Linux .

Em resumo:

Marcando arquivos que devem ser executados

Quando você escreve um script de shell, pode marcá-lo como executável com chmod +x . Isto sugere ao seu shell que você pretende que ele seja executável (caso contrário, para todos que o shell sabe, é apenas outro arquivo de texto simples). O shell pode mostrá-lo na conclusão da tabulação quando você digita ./ Tab .

Da mesma forma: os diretórios something.d (por exemplo, init.d ) contêm scripts de shell de inicialização ou controle que normalmente são executados automaticamente por daemons. Você pode querer colocar um comentário ou arquivo README no diretório como um arquivo de texto simples. Ou você pode querer desativar temporariamente um dos scripts. Você pode fazer isso limpando o bit de execução para esse arquivo específico. Isso diz ao daemon para pulá-lo.

Prevenindo a execução privilegiada

O bit setuid significa que, quando você executa o arquivo, ele é executado como um usuário especificado (por exemplo, root).

O post do fórum explica bem:

You want an executable to be setuid for some user, but you only want people from a specific group to be able to execute it as setuid. They can still execute it by copying, but the setuid flag gets lost, so they'll be executing it as themselves, rather than the user who owned the original file.

    
por 01.08.2012 / 16:29
9

Se você tiver acesso de leitura a um arquivo, sempre poderá fazer uma cópia dele.

Se você puder fazer uma cópia pessoal, poderá sempre marcar esse executável de cópia.

Isso não explica o comportamento do ld-linux, mas indica que ele pode não ser uma brecha de segurança muito útil.

Se você deseja uma segurança mais rigorosa, SELinux

    
por 01.08.2012 / 16:31
1

Olhando para a pergunta de forma um pouco diferente: como diz o Mechanical Snail, a permissão de execução em um arquivo não se destina a impedir a execução. No entanto, a opção de sistema de arquivos "noexec" impede a execução e não é facilmente contornada (não suportada por todos os sistemas de arquivos, mas certamente pelos linux mais populares). Se o administrador quisesse impedir que os usuários executassem seus próprios programas, eles poderiam especificar a opção noexec nos diretórios home e tmp, e quaisquer outros em que os usuários pudessem criar arquivos.

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

Aparentemente, era possível contornar a opção noexec usando o truque do carregador mencionado na questão, mas isso foi corrigido no kernel algumas versões anteriores.

De link :

noexec

Do not allow direct execution of any binaries on the mounted filesystem. (Until recently it was possible to run binaries anyway using a command like /lib/ld*.so /mnt/binary. This trick fails since Linux 2.4.25 / 2.6.0.)

    
por 11.08.2012 / 15:28