Em uma palavra, "não".
O Linux não diferencia realmente entre executáveis e scripts; o #!
no início é uma maneira de dizer ao kernel qual programa executar para avaliar a entrada, mas não é a única maneira que um script pode ser executado.
Então, por exemplo, se eu tiver um script
$ cat x
#!/bin/sh
echo hello
Então eu posso executar isso com o comando
$ ./x
Isso fará com que o kernel tente executá-lo, localize o #!
e então efetivamente execute /bin/sh x
.
No entanto, eu também poderia executar qualquer uma dessas variantes:
$ sh ./x
$ bash ./x
$ cat x | sh
$ cat x | bash
$ sh < x
ou mesmo
. ./x
Portanto, mesmo que o kernel tente impor a assinatura na exec
camada, podemos contornar isso executando apenas o interpretador com o script como parâmetro.
Isso significa que o código de assinatura teria que estar no próprio intérprete. E o que impediria um usuário de compilar sua própria cópia de um shell sem o código de execução de assinatura?
A solução padrão para isso não é usar assinatura, mas usar Controles de Acesso Obrigatório (MAC), como SELinux
. Com os sistemas MAC, você pode especificar exatamente o que cada usuário tem permissão para executar e fazer a transição de camadas. Assim, por exemplo, você pode dizer "usuários normais podem executar qualquer coisa, exceto o servidor da web e os processos CGI podem acessar apenas itens do /var/httpd
diretório; todo o resto é rejeitado".