Onde armazenar a chave privada?

22

Digamos que eu queira que algumas partes do meu software sejam criptografadas. Por exemplo, as credenciais de um banco de dados etc. Eu preciso armazenar esses valores em algum lugar, mas fazer isso em texto não criptografado tornaria mais fácil para um invasor obter acesso não autorizado.

No entanto, se eu criptografar algum texto não criptografado, onde armazeno a chave? Qualquer coisa a que o software tenha acesso, um determinado invasor teria acesso, independentemente do nível de ofuscação:

  • Digamos que a chave esteja protegida pelo modelo de segurança do sistema de arquivos; mas e os superusuários (maliciosos) ou plataformas que não fornecem essa fidelidade?
  • Ou a chave está codificada nos binários de software, mas sempre pode ser descompilada, e o software de código aberto ou o código interpretado?
  • Se a chave for gerada, esse algoritmo precisará ser determinístico (presumivelmente) e, em seguida, o mesmo problema se aplica à semente.
  • etc.

A criptografia é tão forte quanto o elo mais fraco de sua cadeia, e isso parece ser bastante solto! Presumindo que seja a ferramenta certa para o trabalho (como eu me entendo), como proteger essas informações de maneira robusta?


Em relação à ferramenta certa para o trabalho: provavelmente, por exemplo - no caso de acesso ao serviço (DBs, servidores de autenticação etc.), você restringiria o acesso a esse nível com uma conta de serviço, talvez com algum nível de serviço auditoria etc. e, portanto, ter as credenciais em texto não criptografado não é uma preocupação.

Para mim, no entanto, isso ainda parece inadequado: eu não quero ninguém bisbilhotando onde não deveria estar!

Xophmeister
fonte
6
Você pode encontrar várias postagens em Security.SE para lhe interessar. Observarei que algumas estruturas e idiomas fornecem suporte especializado para isso (por exemplo, seções de configuração criptografada em .net).
Brian
9
infelizmente, não há muito o que você possa fazer contra um "superusuário malicioso". Como o seu software precisa acessar as chaves, qualquer superusuário também, pois ele tem a capacidade de alterar / ignorar praticamente qualquer ACL que você possa colocar em prática.
DXM
16
A única maneira absolutamente segura de evitar ter que confiar em um segredo para o usuário é evitar a necessidade desse segredo. Uma solução comum é executar o software em um servidor sob seu controle e distribuir apenas um front-end desprotegido através do qual o usuário possa se autenticar no servidor e, em seguida, consumir serviços do servidor.
amon
2
A resposta de Amon não se limita a um usuário, mas a qualquer cliente. O DXM também levanta um ponto em que você não pode proteger seu sistema de alguém que queira adulterá-lo e não deve gastar energia para dificultar sua ação. Em vez disso gastar a energia no produto para que eles não têm interesse em fazê-lo
Kevin
3
O melhor que você pode fazer sobre clientes mal-intencionados é restringi-los a uma API de serviço bem definida, sem conceder-lhes acesso direto ao banco de dados. Você realmente não pode fazer nada além disso, pois não pode ocultar um segredo no cliente.
CodesInChaos

Respostas:

25

Antes de tudo, não me referiria a mim mesmo como especialista em segurança, mas tive a oportunidade de responder a essa pergunta. O que descobri me surpreendeu um pouco: não existe um sistema completamente seguro . Bem, acho que um sistema completamente seguro seria aquele em que todos os servidores estão desligados :)

Alguém que trabalhava comigo na época descreveu o projeto de um sistema seguro em termos de elevar o nível dos invasores. Portanto, cada camada de segurança diminui a oportunidade de um ataque.

Por exemplo, mesmo se você pudesse proteger perfeitamente a chave privada, o sistema não é completamente seguro. Porém, o uso correto dos algoritmos de segurança e a atualização dos patches aumentam o nível. Mas, sim, um super computador poderoso o suficiente e com tempo suficiente pode quebrar a criptografia. Tenho certeza de que tudo isso está entendido, então voltarei a pergunta.

A pergunta é clara, então primeiro tentarei abordar cada um dos seus pontos:

Digamos que a chave esteja protegida pelo modelo de segurança do sistema de arquivos; mas e os superusuários (maliciosos) ou plataformas que não fornecem essa fidelidade?

Sim, se você usar algo como Windows Key Store ou uma chave privada TLS criptografada por senha, estará exposto aos usuários que possuem a senha (ou acesso) às chaves privadas. Mas acho que você concorda que isso aumenta a fasquia. As ACLs do sistema de arquivos (se implementadas corretamente) fornecem um nível de proteção bastante bom. E você está em posição de examinar pessoalmente e conhecer seus superusuários.

Ou a chave está codificada nos binários de software, mas sempre pode ser descompilada, e o software de código aberto ou o código interpretado?

Sim, eu vi chaves codificadas em binários. Novamente, isso eleva um pouco a fasquia. Alguém que esteja atacando esse sistema (se for Java) precisa entender que o Java produz código de bytes (etc) e deve entender como descompilar a leitura. Se você estiver usando um idioma que grava diretamente no código da máquina, poderá ver que isso eleva a fasquia um pouco mais. Não é uma solução de segurança ideal, mas poderia fornecer algum nível de proteção.

Se a chave for gerada, esse algoritmo precisará ser determinístico (presumivelmente) e, em seguida, o mesmo problema se aplica à semente.

Sim, basicamente o algoritmo se torna a informação da chave privada para criar a chave privada. Portanto, agora precisaria ser protegido.

Portanto, acho que você identificou um problema central em qualquer política de segurança, gerenciamento de chaves . Ter uma política de gerenciamento de chave em vigor é essencial para fornecer um sistema seguro. E, é um tópico bastante amplo .

Portanto, a questão é: qual é a segurança do seu sistema (e, portanto, a chave privada)? Quão alto, no seu sistema, a barra precisa ser elevada?

Agora, se você estiver disposto a pagar, há algumas pessoas por aí que produzem soluções para isso. Acabamos usando um HSM (Hardware Security Module) . É basicamente um servidor inviolável que contém uma chave no hardware. Essa chave pode ser usada para criar outras chaves usadas para criptografia. A idéia aqui é que (se configurada corretamente), a chave nunca sai do HSM. HSMs custam muito . Mas em algumas empresas (protegendo os dados do cartão de crédito, digamos), o custo de uma violação é muito maior. Então, há um equilíbrio.

Muitos HSMs usam cartões-chave da manutenção e administração dos recursos. Um quorum de cartões-chave (5 de 9, digamos) deve ser fisicamente colocado no servidor para alterar uma chave. Portanto, isso eleva a fasquia bastante alto, permitindo apenas uma violação se um quorum de superusuários conspirar.

Pode haver soluções de software por aí que oferecem recursos semelhantes aos de um HSM, mas não estou ciente do que eles são.

Eu sei que isso só serve para responder à pergunta, mas espero que isso ajude.

Davin Tryon
fonte
2
"Bem, acho que um sistema completamente seguro seria aquele em que todos os servidores estão desligados" e não existe maneira de ligá-los.
precisa saber é o seguinte
2

O que você quer não pode ser feito.

Digamos que a chave esteja protegida pelo modelo de segurança do sistema de arquivos; mas e os superusuários (maliciosos) ou plataformas que não fornecem essa fidelidade?

Você basicamente quer proteção contra pessoas que se tornam maliciosas. No seu modelo, em algum momento alguém terá acesso à chave. E se essa pessoa for maliciosa? E se você é malicioso? Veja, o problema que você afirma é insolúvel, exceto por não ter uma chave.

Portanto, não trabalhe com credenciais de banco de dados, mas com outros mecanismos de autenticação. Mas não importa o quê, alguém em algum momento precisa acessar os dados e alguém pode ser malicioso.

Pieter B
fonte
2

Este é um daqueles problemas que realmente não podem ser resolvidos no mesmo nível em que foram criados. Teremos que dar um passo atrás para algumas filosofias fundamentais e seguir a cascata na esperança de uma resolução.

A primeira filosofia é "nunca confie no cliente" e a intimamente relacionada "se você realmente deseja manter um segredo, não conte a ninguém!"

Um exemplo simples são as credenciais do banco de dados, como você mencionou. Obviamente, você deseja que seu cliente tenha acesso a ele, mas não qualquer Internet Stranger aleatório, então você precisa de algum tipo de sistema de identidade / verificação / login. Mas a principal premissa de ocultar isso é um problema: se o próprio usuário deve possuir um segredo, mas você não quer que ele saiba qual é esse segredo, tudo o que você pode fazer é ocultá-lo ou dificultá-lo a abrir " o pacote secreto ". Mas eles ainda podem descobrir, então é melhor você ter um plano de backup!

A solução mais fácil é "não faça isso". Use as credenciais da conta do próprio usuário para permitir acesso no nível do cliente ao banco de dados do software, e é isso. Se o cliente se tornar mal-intencionado, o pior cenário é que ele possa estragar seus próprios dados. É isso aí. Seu banco de dados e sistema devem, no máximo, agora conter entradas indesejadas desse cliente, exclusivamente para esse cliente, com mais ninguém (incluindo você) sofrendo com o caos.

Existem casos de uso específicos em que você apenas deseja que o software implantado faça alguma coisa, mas não tem todos no mundo capazes de se conectar e fazer as mesmas coisas, mas, para isso, está apenas escondendo segredos e a única boa razão para fazer isso é apenas reduzir dores de cabeça ou atividade do sistema. Se suas informações ocultas se tornarem de conhecimento geral, é melhor que elas não sejam revolucionárias, apenas na pior das hipóteses irritantes.

Se você estiver em um desses casos de uso restritos, trata-se de ofuscação, que significa ser criativo. É muito parecido com o Code Golf, na verdade - exceto você que criou o quebra-cabeça. Isso é tudo o que realmente é - um quebra-cabeça. E as pessoas gostam de resolver quebra-cabeças, então, é melhor ficar bem quando alguém descobrir.

Mas para a maioria das coisas no mundo, é melhor operar sem se preocupar em manter um segredo do usuário. Em vez disso, a melhor prática é apenas deixar o usuário descobrir o segredo, assumir a responsabilidade de ajudar a protegê-lo (nome de usuário e senha, por exemplo) e limitar o risco de desvantagem do que acontece se o segredo for revelado ou abusado.

Nos verdadeiros contextos criptográficos / de segurança do "gerenciamento de chaves", a resposta de "onde armazenar a chave privada" é "em outro lugar!" Criptografia é proteção ponto a ponto, e a criptografia de chave pública-privada foi projetada para proteger as informações em trânsito no tempo e no espaço. A chave privada é inerentemente vulnerável, e protegê-la não é realmente uma questão de sobreposição de criptografia - está protegendo-a totalmente contra o acesso. E se o sistema precisar acessá-lo, o próprio sistema deverá estar protegido - e você não poderá fazer isso na máquina do cliente. Eles sempre podem executar uma VM, despejar a RAM, detectar o tráfego de rede, instalar um proxy ou NIC virtual, descompilar os executáveis ​​... não se envolvam voluntariamente nessa batalha perdida.

Agora, se você precisar fazer algo como DRM, onde sua necessidade de armazenar um segredo é realmente baseada no controle do uso do próprio software, essa é outra situação .


TLDR: Não guarde segredos do usuário, guarde segredos COM o usuário.

BrianH
fonte
1

Um dos sistemas que atualmente uso funciona dessa maneira.

  • Começo com um formulário de login do serviço de autenticação. Ele usa autenticação de dois fatores para garantir que eu sou quem afirmo ser.
  • Recebo um certificado SSL temporário que posso usar para acessar o serviço protegido. O serviço mantém o controle dos certificados que aceita.
  • Minhas trocas são criptografadas por este certificado de espionagem. Tentar quebrar não é muito útil, pois expira.
  • O certificado expira rapidamente (em várias horas), mas não muito rapidamente, para que eu não precise fornecer uma senha para cada interação.
  • O certificado pode ser revogado instantaneamente do outro lado.

É claro que o serviço protegido está fora do meu alcance. Ele poderia ser executado na minha máquina com uma conta diferente (e possivelmente em um contêiner), mas eu tenho privilégios de superusuário e, em seguida, tente contornar as restrições.

Basicamente, se você tiver um superusuário malicioso, todas as apostas estão desativadas. E você deve assumir a presença de um superusuário mal-intencionado no seu modelo de ameaça.

Portanto, você precisa isolar seu serviço protegido da máquina acessível ao cliente. Mova o serviço protegido para uma máquina acessível apenas via rede. Coloque seus clientes em máquinas virtuais que os impedem de alcançar o restante da máquina física onde o serviço protegido é executado.

Se o seu serviço protegido não for tão precioso a ponto de poder comandar essas medidas, vá com o armazenamento de chaves criptografado que o sistema operacional fornecer: Windows, Linux e OSX têm implementações de chaveiro.

9000
fonte
-1

Na minha opinião, a única maneira de manter isso completamente seguro é ter a chave / senha criptografada com uma senha para desbloquear. Dessa forma, a senha deve ser fornecida para cada início ou uso do segredo. Não é muito útil.

Outra maneira pode ser fazer com que o sistema de segurança seja a própria conta do banco de dados. Não é muito escalável ...

Se cada usuário em um sistema tiver sua própria conta de banco de dados, e essas contas tiverem sido criadas de forma que o aplicativo não tenha direitos para criar contas no banco de dados em nome de um usuário, você poderá chegar bem perto. Também não é uma boa solução, então acho que você precisa ter acesso de leitura muito restrito nos arquivos de configuração e confiar em seus superusuários.

polve
fonte