Pergunta

Por razões de segurança, é desejável verificar a integridade do código antes da execução, evitando software adulterado por um atacante.Então, minha pergunta é

Como assinar código executável e executar apenas software confiável no Linux?

Eu li o trabalho de van Doom e outros., Design e implementação de executáveis ​​assinados para Linux, e o da IBM TLC (Cliente Linux confiável) por Safford & Zohar.O TLC usa controlador TPM, o que é legal, mas o artigo é de 2005 e não consegui encontrar alternativas atuais.

Você conhece outras opções?

ATUALIZAR:E sobre outros sistemas operacionais?AbrirSolaris?Família BSD?

Foi útil?

Solução

O DigSig módulo do kernel implementa verificação de binários assinados por uma ferramenta chamada bsign.No entanto, não houve nenhum trabalho desde a versão 2.6.21 do kernel Linux.

Outras dicas

Sei que esta é uma pergunta antiga, mas só agora a encontrei.

Eu escrevi suporte executável assinado para o kernel Linux (por volta da versão 2.4.3) há algum tempo e tinha todo o conjunto de ferramentas pronto para assinar executáveis, verificando as assinaturas em execve(2) tempo, armazenando em cache as informações de validação de assinatura (limpando a validação quando o arquivo foi aberto para gravação ou modificado de outra forma), incorporando as assinaturas em programas ELF arbitrários, etc.Ele introduziu algumas penalidades de desempenho na primeira execução de cada programa (porque o kernel teve que carregar no inteiro arquivo, em vez de apenas solicitar as páginas necessárias), mas uma vez que o sistema estava em estado estável, ele funcionou bem.

Mas decidimos parar de prosseguir porque enfrentava vários problemas que eram grandes demais para justificar a complexidade:

  • Ainda não havíamos construído suporte para bibliotecas assinadas.Bibliotecas assinadas exigiriam também a modificação do ld.so carregador e o dlopen(3) mecanismo.Isso não era impossível, mas complicou a interface:devemos fazer com que o carregador peça ao kernel para validar uma assinatura ou o cálculo deve ser feito inteiramente no espaço do usuário?Como alguém se protegeria contra um strace(2)d processo se esta parte da validação for feita no espaço do usuário?Seríamos forçados a proibir strace(2) inteiramente em tal sistema?

    O que faríamos sobre programas que fornecem seu próprio carregador?

  • Muitos programas são escritos em linguagens que não são compiladas para objetos ELF.Precisaríamos fornecer específico do idioma modificações para bash, perl, python, java, awk, sed, e assim por diante, para que cada um dos intérpretes seja capaz de também validar assinaturas.Como a maioria desses programas é de texto simples em formato livre, eles não possuem a estrutura que tornou tão fácil incorporar assinaturas digitais em arquivos de objeto ELF.Onde as assinaturas seriam armazenadas?Nos roteiros?Em atributos estendidos?Em um banco de dados externo de assinaturas?

  • Muitos intérpretes são bem aberto sobre o que eles permitem; bash(1) pode se comunicar com sistemas remotos inteiramente por conta própria usando echo e /dev/tcp, e pode ser facilmente induzido a executar qualquer coisa que um invasor precise fazer.Assinados ou não, você não poderia confiar neles uma vez que estivessem sob o controle de um hacker.

  • O principal motivador para o suporte a executáveis ​​assinados vem dos rootkits que substituem os fornecidos pelo sistema. /bin/ps, /bin/ps, /bin/kill, e assim por diante.Sim, existem outros motivos úteis para assinar executáveis.No entanto, os rootkits tornaram-se significativamente mais impressionantes ao longo do tempo, com muitos contando com núcleo hacks para ocultar suas atividades dos administradores.Depois que o kernel for hackeado, todo o jogo termina.Como resultado da sofisticação dos rootkits, as ferramentas que esperávamos evitar que fossem usadas estavam caindo em desuso na comunidade hacker.

  • A interface de carregamento de módulos do kernel estava totalmente aberta.Uma vez que um processo tenha root privilégio, foi fácil injetar um módulo do kernel sem qualquer verificação.Poderíamos também ter escrito outro verificador para módulos do kernel, mas a infraestrutura do kernel em torno dos módulos era muito primitiva.

O modelo GNU/Linux/FOSS na verdade incentiva a adulteração – de certa forma.Os usuários e criadores de distros devem ser livres para modificar (adulterar) o software para atender às suas necessidades.Mesmo apenas recompilar o software (sem alterar nenhum código-fonte) para personalização é algo feito com bastante frequência, mas que quebraria a assinatura de código binário.Como resultado, o modelo de assinatura de código binário não é particularmente adequado para GNU/Linux/FOSS.

Em vez disso, esse tipo de software depende mais da geração de assinaturas e/ou hashes seguros dos pacotes fonte.Em combinação com um modelo de distribuição de pacotes confiável e confiável, isso pode ser tão seguro (se não mais, em termos de transparência no código-fonte) quanto a assinatura de código binário.

Veja isso: http://linux-ima.sourceforge.net/

Ainda não está assinando, mas ainda permite a verificação.

Posso responder à pergunta da perspectiva do sistema operacional Solaris 10 e 11, todos os binários estão assinados.Para verificar a assinatura use 'elfsign'...

$ elfsign verify -v /usr/bin/bash
elfsign: verification of /usr/bin/bash passed.
format: rsa_sha1.
signer: O=Oracle Corporation, OU=Corporate Object Signing, OU=Solaris Signed Execution, CN=Solaris 11.
signed on: Fri Oct 04 17:06:13 2013.

A Oracle também adicionou recentemente um processo de inicialização verificado para Solaris 11, para obter detalhes, consulte - Introdução à inicialização verificada do Solaris

Existem alguns forks de nível de produção do código OpenSolaris, três que valem a pena investigar são Illumos, SmartOS e OmniOS.

Dê uma olhada Medusa DS9.Eu brinquei com ele por um longo tempo (longo) há algum tempo, mas se bem me lembro, você poderia registrar binários específicos e qualquer modificação não era permitida no nível do kernel.É claro que isso pode ser substituído pelo acesso local à máquina, mas não foi muito fácil.Existe um daemon inteligente, chamado policial, que verifica tudo o que acontece na máquina e se algo fora do comum acontece, ela começa a gritar.

Nunca experimentei, mas dê uma olhada: http://blog.codenoise.com/signelf-digitally-signing-elf-binaries.A solução funciona sem a necessidade de suporte do kernel e parece estar pronta para uso.

O código do signatário pode ser encontrado em http://sourceforge.net/projects/signelf/

Ele não resolve a questão "Executar apenas código confiável no Linux", mas resolve parcialmente o problema, abrindo uma maneira para o programa detectar uma possível adulteração/corrupção.

http://en.wikipedia.org/wiki/PKCS

Use um sinal PKCS7 (S/MIME).Gere seu próprio par de certificado/chave privada, autoassine o certificado e, em seguida, assine seu arquivo com a chave privada e o certificado usando PKCS7.Ele anexará o certificado a ele e poderá verificar-se em tempo de execução usando o comando openssl (man smime ou apenas do openssl help).Isso é inviolável porque mesmo que a chave pública esteja nos arquivos que você distribui, a assinatura S/MIME dessa chave pública só pode ser gerada com a chave privada que você não distribuirá.Portanto, se o arquivo estiver assinado pelo seu certificado, ele deve ter sido assinado por alguém com a chave privada e, como você não deu a chave privada a ninguém, ela deve ter vindo de você.

Veja como fazer o certificado autoassinado.

http://www.akadia.com/services/ssh_test_certificate.html

Você terá que convencer o openssl a confiar em seu certificado como raiz de autoridade (-CAfile), em seguida, verificá-lo como raiz e também verificar se o certificado no arquivo é seu (hash do certificado) e verificar o hash.Observe que, embora não esteja documentado, o status de saída do openssl reflete a validade do sinal que você está verificando ao fazer uma verificação smime.É 0 se corresponder, diferente de zero se não corresponder.

Observe que tudo isso não é seguro porque se a verificação estiver em seu código, eles podem simplesmente removê-la se quiserem vencê-lo.A única maneira segura de fazer isso seria colocar o verificador no sistema operacional e verificar seu binário e recusar-se a executá-lo se não estiver assinado.Mas como não há verificador no sistema operacional e o Linux pode ser modificado para removê-lo/ignorá-lo de qualquer maneira...Isso é realmente bom apenas para detectar arquivos corrompidos, em vez de tentar impedir que as pessoas o ignorem.

Concordo que a filosofia em torno do Linux, GNU et al.gira em torno de mexer.Por outro lado, acredito também que alguns sistemas merecem protecção contra vulnerabilidades como a adulteração de software, que pode minar a privacidade e a integridade dos utilizadores de um sistema.

As implementações do kernel não conseguem acompanhar o rápido ciclo de desenvolvimento do próprio kernel.Em vez disso, recomendo implementar uma forma de verificação de assinatura de arquivo executável usando ferramentas de espaço do usuário.Coloque executáveis ​​em um arquivo ou imagem de sistema de arquivos e assine a imagem usando uma chave privada;se essa chave privada permanecer em suas máquinas de desenvolvimento (privadas), quando seu servidor for invadido, os invasores ainda não terão como assinar suas próprias imagens e injetar seu código sem enganar o sistema para montar imagens não assinadas.Ele se estende ainda mais ao longo da cadeia:

  • ter seus serviços contidos em imagens somente leitura montadas em tempo de execução;
  • fazer com que a máquina funcione com um sistema de arquivos assinado e somente leitura;
  • implementar inicialização segura em suas máquinas, executando um bootloader que reforça a integridade da mídia de inicialização;
  • confie que as pessoas da sua organização não interferirão nas suas máquinas.

Fazer tudo certo é uma tarefa difícil.É muito mais simples contornar tudo isso projetando seu sistema sob outra abordagem:

  • colocar usuários em quarentena no sistema.Não introduza meios para os usuários executarem comandos em seu sistema.Evite gastar dinheiro de dentro de programas que dependem de dados alimentados pelo usuário.
  • projete seus procedimentos de implantação usando o gerenciamento de configuração e garanta que suas implantações sejam "repetíveis", o que significa que elas levam ao mesmo resultado funcional quando você as implanta várias vezes.Isso permite que você "destrua em órbita" máquinas que você suspeita terem sido comprometidas.
  • trate suas máquinas como se estivessem comprometidas:execute auditorias regularmente para verificar a integridade de seus sistemas.Salve seus dados em imagens separadas e reimplante sistemas regularmente.Assine imagens e faça com que os sistemas rejeitem imagens não assinadas.
  • usar certificados:favorecer uma abordagem de "fixação de certificado".Implante um certificado raiz para seus aplicativos (que fornecerá rejeição automática de assinaturas que não foram certificadas por sua organização), mas pelo menos faça com que o sistema gerencie as impressões digitais das imagens atuais e notifique os administradores quando as impressões digitais forem alteradas.Embora seja possível implementar tudo isso usando cadeias de chaves, a autenticação baseada em certificado foi projetada exatamente para esta aplicação.

Gosto de pensar na segurança como uma corrente.O elo mais fraco da cadeia pode comprometer todo o sistema.Então a coisa toda se tornou "impedindo que um usuário não autorizado obtenha a senha root".

Conforme sugerido por @DanMoulding, a fonte do software também é importante e, no futuro, provavelmente as lojas oficiais de aplicativos do sistema operacional serão o padrão.Pense nas lojas Play Store, Apple ou Microsoft.

Eu acho que a instalação e a distribuição do código malicioso secreto é o problema muito mais insidioso.Afinal, para carregar código ruim é tem que primeiro ser instalado no sistema em algum lugar.Mais camadas de A segurança costuma ser melhor, claro.A questão é:vale a pena o custo?

Na minha opinião a resposta é “depende”.Você pode reduzir o risco adotando um conjunto de políticas de segurança sugeridas por @sleblanc.Você pode criptografar seu sistema de arquivos (https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup), use sistemas de arquivos somente leitura para os binários ou use um mecanismo para assinar e verificar os binários.

No entanto, seja qual for o mecanismo usado, não há nada que você possa fazer quando o acesso root for obtido por um invasor.As ferramentas de verificação de assinatura podem ser substituídas por uma versão adulterada ou simplesmente desativadas e realmente não importa se as ferramentas são executadas no espaço do usuário ou no espaço do kernel, uma vez que a máquina foi comprometida (embora o último seja mais seguro, é claro ).

Portanto, seria bom se o kernel do Linux pudesse incorporar um módulo de verificação de assinatura e outra camada de segurança entre o usuário root e o sistema operacional.

Por exemplo, esta é a abordagem adoptada na recente Mac OS versões.Alguns arquivos não podem ser modificados (e às vezes lidos) mesmo pela conta root e há restrições também nas políticas e módulos do kernel (por exemplo,somente kext assinado ou autorizado pode ser carregado no sistema). janelas adotou mais ou menos a mesma abordagem com Bloqueador de aplicativos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top