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

23

Ao ler isso , 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)

Esse trecho mostra que podemos evitar trivialmente as permissões de execução do sistema de arquivos como um usuário normal sem privilégios. Eu executei isso em um 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 sua execução direta. Quando executado dessa maneira, o carregador do Linux atua como um intérprete para os 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 é 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 outros lugares.

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 projetado para impedir a execução de arquivos, se for tão trivialmente contornado? Perdi alguma coisa?
Edd Barrett
fonte
1
Não há uma boa razão, mas se você já conseguiu excluir o sistema libc(fiz uma vez, atualizando uma caixa do Arch), ficará agradecido por essa pequena peculiaridade.
precisa saber é o seguinte
1
@ new123456 oh Deus, o canal de IRC depois que a atualização era doloroso estar em.
Rob
É o carregador , não o vinculador.
Pare de prejudicar Monica

Respostas:

33

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

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

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

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

Em suma:

Marcando arquivos que devem ser executados

Quando você escreve um script de shell, pode marcá-lo como executável com chmod +x. Isso indica ao seu shell que você pretende que ele seja executável (caso contrário, pelo que o shell sabe, é apenas mais um arquivo de texto sem formatação). O shell pode então mostrá-lo na conclusão da guia quando você digita ./Tab.

Da mesma forma: os something.ddiretórios (por exemplo init.d) contêm scripts de shell de inicialização ou controle que normalmente são executados automaticamente pelos daemons. Você pode colocar um comentário ou arquivo README no diretório como um arquivo de texto sem formatação. 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 ignorá-lo.

Impedindo a execução privilegiada

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

A postagem do fórum explica bem:

Você deseja que um executável seja configurado para algum usuário, mas você deseja que apenas pessoas de um grupo específico possam executá-lo como definido. Eles ainda podem executá-lo copiando, mas o sinalizador setuid se perde, então eles o executam como eles mesmos, em vez do usuário que possuía o arquivo original.

Caracol mecânico
fonte
2
Obrigado - eu esqueci o fato de que o usuário pode copiar qualquer arquivo que possa ler e, portanto, escolher permissões arbitrárias.
Edd Barrett
que tal arquivos com permissão de execução, mas sem permissão de leitura?
Lie Ryan
@LieRyan E eles?
Reintegrar Monica
@BrendanLong: Você obviamente não pode copiá-los, portanto não pode alterar as permissões deles. (Mas por que você iria querer, eu não posso dizer - a única coisa que poderia fazer com a cópia de qualquer maneira está caindo a permissão de execução)
MSalters
9

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

Se você pode fazer uma cópia pessoal, sempre pode marcar essa cópia como executável.

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

Se você deseja uma segurança mais rígida, considere o SELinux

RedGrittyBrick
fonte
Isso é verdade.
Edd Barrett
Era apenas uma questão conceitual. Suponho que você também possa definir o noxec em sistemas de arquivos.
Edd Barrett
2

Olhando para a pergunta um pouco diferente: como o Mechanical Snail diz, a permissão de execução em um arquivo não se destina a impedir a execução. No entanto, a opção "noexec" do sistema de arquivos impede a execução e não é tão facilmente contornada (não é suportada por todos os sistemas de arquivos, mas certamente pelos mais populares do Linux). 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 em qualquer outro em que os usuários possam 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 pergunta, mas isso foi corrigido no kernel algumas versões anteriores.

A partir de http://linux.die.net/man/8/mount :

noexec

Não permita a execução direta de nenhum binário no sistema de arquivos montado. (Até recentemente, era possível executar binários de qualquer maneira usando um comando como /lib/ld*.so / mnt / binary. Esse truque falha desde o Linux 2.4.25 / 2.6.0.)

Randy Orrison
fonte