Existe um shell que verifica se o código está assinado?

18

Eu estava brincando com o PowerShell esta semana e descobri que você é obrigado a assinar seus scripts para que eles possam ser executados. Existe alguma funcionalidade segura similar no Linux relacionada à prevenção de execução de scripts bash?

A única funcionalidade semelhante a esta, que eu saiba é que o SSH requer uma determinada chave.

    
por leeand00 09.08.2016 / 00:32

8 respostas

10

Se você estiver bloqueando a capacidade dos usuários de executar scripts por meio de sudo , você poderá usar a funcionalidade digest .
Você pode especificar o hash de um script / executável em sudoers , que será verificado por sudo antes de ser executado. Portanto, embora não seja o mesmo que assinar, ele fornece uma garantia básica de que o script não foi modificado, pelo menos, sem que os sudoers também sejam modificados.

If a command name is prefixed with a Digest_Spec, the command will only match successfully if it can be verified using the specified SHA-2 digest. This may be useful in situations where the user invoking sudo has write access to the command or its parent directory. The following digest formats are supported: sha224, sha256, sha384 and sha512. The string may be specified in either hex or base64 format (base64 is more compact). There are several utilities capable of generating SHA-2 digests in hex format such as openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.

link

    
por 10.08.2016 / 15:20
13

Sim e não.

A distribuição de software Linux funciona de maneira um pouco diferente da distribuição de software do Windows. No mundo Linux (não incorporado), o principal método para distribuir software é através de uma distribuição (Ubuntu, Debian, RHEL, Fedora, Arch, etc.). Todas as principais distribuições têm assinado seus pacotes sistematicamente há cerca de uma década.

Quando o software é distribuído de forma independente, cabe ao fornecedor decidir como ele enviará seu software. Bons fornecedores fornecem fontes de pacotes que são compatíveis com as principais distribuições (não há mecanismo de distribuição unificado para todo o Linux: a distribuição de software é um dos principais pontos de diferenciação entre distribuições) e são assinadas com a chave do fornecedor. Distribuições Linux raramente agem como uma autoridade de assinatura para fornecedores terceirizados (a Canonical faz isso com parceiros Ubuntu, mas isso cobre muito poucos fornecedores), e eu acho que todas as grandes distribuições usam a rede de confiança PGP ao invés da infra-estrutura de chave pública TLS, então cabe ao usuário descobrir se eles querem confiar em uma chave.

Não há nenhum mecanismo especial que selecione pacotes de software que consistam em um único script de pacotes de software que consistem em um executável nativo, um arquivo de dados ou vários arquivos. Nem qualquer verificação de assinatura é incorporada a nenhum interpretador de scripts comum, porque a verificação de um pacote de software é uma preocupação completamente ortogonal da execução de um script.

Acho que o Windows anota arquivos com origem e exige confirmação do usuário para executar um arquivo cuja origem seja "baixada" em vez de "local". O Linux não tem realmente um mecanismo similar. O mais próximo disso é a permissão de execução: um arquivo baixado não tem permissão de execução, o usuário precisa ativá-lo explicitamente ( chmod +x na linha de comando ou a ação equivalente em um gerenciador de arquivos).

    
por 09.08.2016 / 02:06
9

O Linux não fornece a capacidade de limitar a execução de scripts bash baseados em assinaturas digitais.

Existe algum trabalho na autenticação de executáveis binários. Consulte o link para obter informações.

    
por 09.08.2016 / 01:02
8

Em uma palavra, "não".

O Linux não diferencia realmente entre executáveis e scripts; o #! no começo é uma maneira de dizer ao kernel qual programa executar para avaliar a entrada, mas não é a única maneira de executar um script.

Então, por exemplo, se eu tiver um script

$ cat x
#!/bin/sh 
echo hello

Então eu posso rodar isso com o comando

$ ./x

Isso fará com que o kernel tente executá-lo, localize o #! e, em seguida, execute efetivamente o /bin/sh x .

No entanto, eu poderia também executar qualquer uma dessas variantes também:

$ sh ./x
$ bash ./x
$ cat x | sh
$ cat x | bash
$ sh < x

ou até mesmo

. ./x

Assim, mesmo que o kernel tente impor a assinatura na camada exec , podemos ignorar isso executando apenas o interpretador com o script como um parâmetro.

Isso significa que o código de assinatura deve 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 aplicação de assinatura?

A solução padrão para isso não é usar assinatura, mas usar Mandatory Access Controls (MAC), como SELinux . Com os sistemas MAC, você pode especificar exatamente o que cada usuário pode executar e fazer a transição de camadas. Então, por exemplo, você pode dizer "usuários normais podem executar qualquer coisa, mas o servidor web e os processos CGI só podem acessar coisas do diretório /var/httpd ; todo o restante é rejeitado".

    
por 09.08.2016 / 01:19
2

As distribuições do Linux geralmente têm gnupg . Parece-me que tudo o que você quer é um simples wrapper bash que verifique uma assinatura gpg independente contra o script de argumento e apenas continue a executar o script se a verificação for bem-sucedida:

#!/bin/sh
gpgv2 $1.asc && bash "$@"
    
por 09.08.2016 / 01:08
2

A contra-pergunta que vem à mente imediatamente é "Por que você sempre quis impedir que os usuários executem programas eles escreveram? " Várias possibilidades existem:

  1. É literalmente impossível detectar quem criou o código em primeiro lugar. O proprietário do arquivo de script é quem realmente salvou o conteúdo desse arquivo, independentemente de onde ele veio. Portanto, aplicar uma assinatura é apenas um substituto complicado para uma caixa de diálogo de confirmação: "Tem certeza de que deseja fazer isso?" No Linux, parte desse problema é resolvida de forma transparente com pacotes assinados e mitigada pelo fato de os usuários terem acesso limitado por padrão. O usuário também deve saber que executar o código de outras pessoas pode ser perigoso *.
  2. Na mesma linha, assinar um script é uma operação muito mais complexa do que salvar um arquivo. No melhor dos casos, isso faz com que o usuário perceba que está realizando uma ação semelhante à assinatura de um documento e deve inspecionar o que ele diz antes de continuar. O mais provável é que simplesmente garanta um nível mínimo de proficiência técnica por parte do usuário para poder executar o script. Na pior das hipóteses, demonstra uma disposição para passar por uma longa série de arcos para executar o que eles queriam. A proficiência técnica é assumida no Linux *.
  3. É mais provável que as pessoas detectem código obviamente malicioso ao digitar / colar uma série de comandos em sua linha de comando. Trechos de texto sem formatação destinados a serem copiados e colados geralmente são menores que a série de comandos necessários para fazer algo propriamente nefasto. O usuário também pode copiar e colar cuidadosamente cada linha separadamente, entendendo o que acontece quando acontece. Com um script, é possível que o usuário nunca tenha olhado o código. Esta pode ser uma aplicação útil de scripts assinados, com o custo muito comum de complacência após a 12ª vez que você tem que fazer isso.

* Isso provavelmente está se tornando cada vez menos verdadeiro à medida que mais pessoas começam a usar o Linux

    
por 09.08.2016 / 10:23
1

A razão pela qual os sistemas evoluíram de maneira diferente é que o Linux tem o atributo de arquivo 'exec' e o Windows usa extensões de arquivo para determinar a executabilidade.

Portanto, no Windows, é fácil enganar o usuário para que baixe um arquivo com a extensão ".exe", ".bat", ".scr", que ficará oculto por padrão . Clicar duas vezes nesse arquivo daria a você uma execução de código arbitrário. Assim, um grande mecanismo de rastreamento de origem e assinatura de executável / script foi criado para atenuar esse risco.

No Linux, você pode conseguir um arquivo para o usuário, mas não pode forçar facilmente o bit 'exec' a ser definido. Além disso, é possível fazer sistemas inteiros de arquivos 'noexec'.

Você pode, em qualquer caso, executar um script explicitamente chamando o interpretador. Você pode até criar scripts de shell em tempo de execução e canalizá-los para o "sh", ou executar "sh -c".

    
por 09.08.2016 / 11:18
0

Por costume, muitos programas de arquivamento não preservam bit de execução em arquivos contidos. Isso impossibilita a execução de executáveis arbitrários. Bem quase.

O ponto é, o que foi descrito em outra resposta que a falta de bit de execução não impede que você passe tal script diretamente para bash . Embora seja discutível que a maioria desses scripts seja bash scripts, o shebang pode especificar qualquer programa como intérprete. Isso significa que cabe ao usuário executar o interpretador apropriado se decidir ignorar a semântica executável.

Embora isso não seja muito, isso praticamente previne a execução de executáveis não confiáveis em * nixes apenas com kernel e shell .

Como mencionei em um dos comentários, há uma outra camada de proteção - SeLinux - que rastreia a origem dos arquivos com base em um conjunto de regras. Uma configuração SeLinux não permitiria, por exemplo, que o root executasse um executável com um conjunto de bits executável que fosse baixado da Internet, mesmo que você copie e mova o arquivo. Pode-se adicionar uma regra de que tais arquivos só podem ser executados através de outro binário que verificaria a assinatura, não muito diferente do que você mencionou na sua pergunta.

Assim, no final, é uma questão de configuração de ferramentas comumente pré-instaladas, e a resposta é sim .

    
por 09.08.2016 / 03:29