O armazenamento local pode ser considerado seguro? [fechadas]

160

Sou obrigado a desenvolver um aplicativo Web que funcione offline por longos períodos. Para que isso seja viável, não posso evitar salvar dados confidenciais (dados pessoais, mas não o tipo de dados que você armazenaria apenas com hash) no armazenamento local.

Aceito que essa prática não seja recomendada, mas, com poucas opções, estou fazendo o seguinte para proteger os dados:

  • criptografar tudo o que entra no armazenamento local usando a biblioteca de criptografia stanford javascript e o AES-256
  • a senha do usuário é a chave de criptografia e não é armazenada no dispositivo
  • veiculação de todo o conteúdo (quando online) de um único servidor confiável via SSL
  • validando todos os dados indo e vindo do armazenamento local no servidor usando o projeto owasp antisamy
  • na seção de rede do appcache, não usando * e, em vez disso, listando apenas os URIs necessários para a conexão com o servidor confiável
  • em geral, tentando aplicar as diretrizes sugeridas na folha de dicas do OWASP XSS

Aprecio que o diabo esteja frequentemente nos detalhes e sei que há muito ceticismo sobre o armazenamento local e a segurança baseada em javascript em geral. Alguém pode comentar se existem:

  • falhas fundamentais na abordagem acima?
  • possíveis soluções para essas falhas?
  • Existe uma maneira melhor de proteger o armazenamento local quando um aplicativo html 5 deve funcionar offline por longos períodos?

Obrigado por qualquer ajuda.

user1173706
fonte
"Eu aceito que isso não seja uma prática recomendada" - É mesmo? Não é o contrário que ele foi criado realmente para isso?
hakre
2
Para esclarecer, eu quis dizer prática não recomendada para armazenar dados confidenciais no armazenamento local.
user1173706
Dessa forma, você não deve transmitir dados confidenciais por redes grandes?
hakre
@ user1173706 Por que o aplicativo precisa funcionar para ser executado por longos períodos offline? Como são os usuários? Quais navegadores você tem para oferecer suporte? Eu acho que é possível, mas preciso saber detalhes sobre o seu cenário.
Benjamin Gruenbaum
@ Benjamin eu atualizei a pergunta. Obrigado.
user1173706

Respostas:

74

WebCrypto

As preocupações com criptografia em javascript do lado do cliente (navegador) são detalhadas abaixo. Todas essas preocupações, exceto uma, não se aplicam à API WebCrypto , que agora é razoavelmente bem suportada .

Para um aplicativo offline, você ainda deve projetar e implementar um keystore seguro.

Além: Se você estiver usando o Node.js, use a API criptográfica incorporada .

Criptografia Javascript Nativo (pré-WebCrypto)

Presumo que a principal preocupação seja alguém com acesso físico ao computador lendo o localStoragepara o seu site, e você deseja criptografia para ajudar a impedir esse acesso.

Se alguém tiver acesso físico, você também estará aberto a ataques diferentes e piores do que a leitura. Isso inclui (mas não se limita a): keyloggers, modificação de script offline, injeção de script local, envenenamento de cache do navegador e redirecionamentos de DNS. Esses ataques só funcionam se o usuário usar a máquina após ter sido comprometida. No entanto, o acesso físico nesse cenário significa que você tem problemas maiores.

Portanto, lembre-se de que o cenário limitado em que a criptografia local é valiosa seria se a máquina fosse roubada.

Existem bibliotecas que implementam a funcionalidade desejada, por exemplo, Stanford Javascript Crypto Library . Existem pontos fracos inerentes (como mencionado no link da resposta da @ ircmaxell):

  1. Falta de entropia / geração de números aleatórios;
  2. Falta de um armazenamento de chaves seguro, ou seja, a chave privada deve ser protegida por senha se armazenada localmente ou armazenada no servidor (que impede o acesso offline);
  3. Falta de apagamento seguro;
  4. Falta de características de tempo.

Cada uma dessas fraquezas corresponde a uma categoria de compromisso criptográfico. Em outras palavras, embora você possa ter "criptografia" pelo nome, ele estará bem abaixo do rigor que se almeja na prática.

Tudo isso dito, a avaliação atuarial não é tão trivial quanto "A criptografia Javascript é fraca, não a use". Isso não é um endosso, é estritamente uma advertência e exige que você compreenda completamente a exposição das fraquezas acima, a frequência e o custo dos vetores que você enfrenta e sua capacidade de mitigação ou seguro em caso de falha: criptografia Javascript, em apesar de suas fraquezas, pode reduzir sua exposição, mas apenas contra ladrões com capacidade técnica limitada. No entanto, você deve presumir que a criptografia Javascript não tem valor contra um invasor determinado e capaz que está direcionando essas informações. Alguns considerariam enganoso chamar os dados de "criptografados" quando se sabe que muitos pontos fracos são inerentes à implementação. Em outras palavras, você pode diminuir marginalmente sua exposição técnica, mas aumenta sua exposição financeira a partir da divulgação. Cada situação é diferente, é claro - e a análise de redução da exposição técnica à exposição financeira não é trivial. Aqui está uma analogia ilustrativa:Alguns bancos exigem senhas fracas , apesar do risco inerente, porque sua exposição a perdas de senhas fracas é menor do que os custos do usuário final para suportar senhas fortes.

🔥 Se você leu o último parágrafo e pensou "Um cara na Internet chamado Brian diz que eu posso usar criptografia Javascript", não use criptografia Javascript.

Para o caso de uso descrito na pergunta, parece fazer mais sentido para os usuários criptografar sua partição local ou diretório inicial e usar uma senha forte. Esse tipo de segurança geralmente é bem testado, amplamente confiável e geralmente disponível.

Brian M. Hunt
fonte
Há documentação adicional (citações) disponível para a postura geral de "não use criptografia JavaScript" fornecida pelo Grupo NCC a partir de 2011: Criptografia JavaScript considerada prejudicial (principalmente devido ao problema de baixar a ferramenta para verificar os downloads ... qualidade do PRNG ... etc)
amcgregor
58

Bem, a premissa básica aqui é: não, ainda não é seguro.

Basicamente, você não pode executar criptografia no JavaScript: Criptografia JavaScript considerada prejudicial .

O problema é que você não pode obter com segurança o código criptográfico no navegador e, mesmo que pudesse, o JS não foi projetado para permitir que você o execute com segurança. Portanto, até que os navegadores tenham um contêiner criptográfico (que as Extensões de Mídia Criptografada fornecem, mas estão sendo reunidas para fins de DRM), não será possível fazer isso com segurança.

Quanto a um "caminho melhor", não existe um no momento. Sua única alternativa é armazenar os dados em texto simples e esperar o melhor. Ou não armazene as informações. De qualquer jeito.

Ou isso, ou se você precisar desse tipo de segurança e precisar de armazenamento local, crie um aplicativo personalizado ...

ircmaxell
fonte
8
Downvoter: você pode fornecer uma resposta melhor? Sei que essa é uma questão um tanto controversa, em que há desacordo significativo entre profissionais de segurança (e também não profissionais), portanto vale a pena compartilhar o ponto de vista alternativo. A menos que você faça uma votação por outro motivo, nesse caso, como posso melhorar esta resposta?
ircmaxell
9
@ircmaxell não eu, mas não concordo com esta resposta. "O problema é que você não pode obter com segurança o código criptográfico no navegador e, mesmo que pudesse, o JS não foi projetado para permitir que você o execute com segurança". - Por quê? Qual é o problema inerente ? Você pode usar a biblioteca de criptografia Stanford JavaScript e criptografar / descriptografar nela. Você pode fazer hash e pode fazer tudo com segurança. Não vejo o problema inerente aqui em um aplicativo offline em JS executando criptografia padrão, como um aplicativo criado em qualquer outro idioma.
Benjamin Gruenbaum
11
@BenjaminGruenbaum: o problema é que há vários lugares em que esse código criptográfico precisaria interagir com o código de terceiros. O ponto principal desse artigo ao qual vinculei é que você não pode controlar o ambiente de execução. Então você instala a Stanford Crypto lib. Então, o que acontece se algum plug-in do navegador substituir sjcl.encrypta chave do invasor por e-mail? No JS, isso é 100% possível e não há nada que você possa fazer para impedir isso. E esse é o ponto subjacente. Não existem mecanismos de "segurança" para impedir que outras JS façam coisas desagradáveis ​​aos seus dados. E isso é um problema .
ircmaxell
13
@ircmaxell Se você dorme com cães, não pode esperar não acordar com pulgas. Se o usuário instalar um complemento de malware que seja igual ao usuário que instala um vírus no PC, não será diferente. Seu programa Java ou C pode ser o mais seguro possível, mas assim que o invasor puder executar o código que você está ferrado. Isso não é diferente para o JS. Os complementos não aparecem apenas magicamente no navegador. Além disso, não salvar as informações criptografadas não ajudaria de forma alguma se o usuário tivesse malware, pois ele poderia apenas seqüestrar os dados ao vivo.
Benjamin Gruenbaum
9
@BenjaminGruenbaum: discordo. Em um aplicativo normal, você precisa tanto para comprometer o aplicativo em si (para ler locais de memória), ou acesso root ganho para a caixa (comprometer o OS). De qualquer forma, você precisa comprometer algo mais profundo do que apenas o comportamento normal. JS permite isso em comportamento normal. Qual é o problema ...
ircmaxell
12

Como uma exploração deste tópico, tenho uma apresentação intitulada "Protegendo o TodoMVC usando a API de criptografia da Web" ( vídeo , código ).

Ele usa a API de criptografia da Web para armazenar a lista de tarefas criptografadas no localStorage por senha, protegendo o aplicativo e usando uma chave derivada de senha para criptografia. Se você esquecer ou perder a senha, não haverá recuperação. ( Isenção de responsabilidade - era um POC e não se destinava ao uso em produção. )

Como as outras respostas afirmam, isso ainda é suscetível a XSS ou malware instalado no computador cliente. No entanto, quaisquer dados confidenciais também estariam na memória quando os dados forem armazenados no servidor e o aplicativo estiver em uso. Sugiro que o suporte offline possa ser o caso de uso atraente.

No final, a criptografia localStorage provavelmente protege apenas os dados dos invasores que só têm acesso de leitura ao sistema ou a seus backups. Ele adiciona uma pequena quantidade de defesa em profundidade para a exposição de dados sensíveis ao item A6 do Top 10 da OWASP e permite que você responda "Algum desses dados é armazenado em texto não criptografado a longo prazo?" corretamente.

Kevin Hakanson
fonte
3

Este é um artigo realmente interessante aqui. Estou pensando em implementar a criptografia JS para oferecer segurança ao usar o armazenamento local. É absolutamente claro que isso só oferecerá proteção se o dispositivo for roubado (e implementado corretamente). Não oferecerá proteção contra keyloggers, etc. No entanto, esse não é um problema de JS, pois a ameaça do keylogger é um problema de todos os aplicativos, independentemente de sua plataforma de execução (navegador, nativo). Quanto ao artigo "Criptografia JavaScript considerada prejudicial", referenciado na primeira resposta, tenho uma crítica; afirma "Você pode usar o SSL / TLS para resolver esse problema, mas isso é caro e complicado". Penso que é uma afirmação muito ambiciosa (e possivelmente bastante tendenciosa). Sim, o SSL tem um custo,

Minha conclusão - existe um lugar para o código de criptografia do lado do cliente, no entanto, como em todos os aplicativos, os desenvolvedores devem reconhecer suas limitações e implementar, se for adequado às suas necessidades, e garantir que haja maneiras de atenuar seus riscos.

Paul S
fonte
Historicamente, houve custos extraordinários (mecânicos, não financeiros) associados à negociação inicial da conexão. A ponto de as empresas utilizarem dispositivos dedicados de terminação SSL, que podem se tornar financeiramente caros além dos custos de emissão e garantia de certificados. Hoje, muitos desses problemas foram resolvidos, como persistência de sessão de duração prolongada para evitar o handshake inicial em solicitações subsequentes.
Amcgregor
2

Não é acessível a nenhuma página da Web (true), mas é facilmente acessível e editável através de ferramentas de desenvolvimento, como o chrome (ctl-shift-J). Portanto, criptografia personalizada necessária antes de armazenar o valor.

Porém, se o javascript precisar descriptografar (validar), o algoritmo de descriptografia será exposto e poderá ser manipulado.

O Javascript precisa de um contêiner totalmente seguro e a capacidade de implementar adequadamente variáveis ​​e funções privadas disponíveis apenas para o interpretador js. Mas isso viola a segurança do usuário - já que os dados de rastreamento podem ser usados ​​com impunidade.

Consequentemente, o javascript nunca será totalmente seguro.

rockmo
fonte
-29

Não.

localStorage pode ser acessado por qualquer página da Web e, se você tiver a chave, poderá alterar os dados que desejar.

Dito isto, se você pode criar uma maneira de criptografar as chaves com segurança, não importa como você transfere os dados, se você pode contê-los em um fechamento, os dados são (um pouco) seguros.

hellol11
fonte
19
Não é acessível a "qualquer página da web". É acessível apenas para páginas no domínio atual.
dtabuenc
@dtabuenc ao contrário, fiz uma caneta há um tempo que mostra todos os pares de chave / valor em seu localStorage , sem hacks.
precisa
3
Não! Desculpe. O armazenamento local é isolado por domínio. O código em execução em um domínio não pode acessar valores que foram armazenados no armazenamento local por outro domínio. Por exemplo, o google.com armazena várias coisas no armazenamento local. Você não poderá listar nenhuma das chaves do google.com no seu exemplo de caneta.
Dtabuenc # 7/16
@dtabuenc testou, você está certo.
precisa saber é o seguinte