Se em uma tela de login o usuário enviar um formulário com seu nome de usuário e senha, a senha será enviada em texto simples (mesmo com POST, corrija-me se eu estiver errado).
Portanto, a questão é qual é a maneira correta de proteger o usuário e sua senha contra terceiros que possam estar espionando os dados de comunicação?
Estou ciente de que HTTPS é uma solução para o problema, mas existe alguma maneira de garantir pelo menos algum nível de segurança usando o protocolo HTTP padrão (solicitação POST)? (talvez usando javascript de alguma forma)
EDIT Eu posso ter deixado de fora algumas coisas importantes.
Eu estava tratando de uma página - que é uma página de login gerada por PHP, que é enviada ao usuário em uma solicitação HTTP GET como um arquivo HTML. Não há nenhuma conexão (@Jeremy Powel) estabelecida entre o servidor e o cliente, então não posso criar esse protocolo de handshaking. E eu quero que o processo completo seja transparente para o usuário - ele quer enviar uma senha, não lidar com criptografia.
Obrigado.
Respostas:
Usar HTTP com SSL tornará sua vida muito mais fácil e você poderá ficar à vontade. Pessoas muito inteligentes (pelo menos mais inteligentes do que eu!) Examinaram esse método de comunicação confidencial por anos.
fonte
A autenticação segura é um tópico amplo. Resumindo, como @ jeremy-powell mencionou, sempre favorece o envio de credenciais por HTTPS em vez de HTTP. Isso vai tirar muitas dores de cabeça relacionadas à segurança.
Os certificados TSL / SSL são muito baratos atualmente. Na verdade, se você não quiser gastar dinheiro, existe um letsencrypt.org grátis - Autoridade de Certificação automatizada.
Você pode ir um passo além e usar caddyserver.com, que chama o letsencrypt em segundo plano.
Agora, uma vez que tiramos o HTTPS do caminho ...
Você não deve enviar login e senha via carga útil POST ou parâmetros GET. Em vez disso, use um cabeçalho de autorização (esquema de autenticação de acesso básico), que é construído da seguinte maneira:
Pode parecer um pouco complicado, mas não é. Existem muitas bibliotecas boas por aí que fornecerão essa funcionalidade para você fora da caixa.
Existem alguns bons motivos pelos quais você deve usar um cabeçalho de autorização
https://user:[email protected]/login
(o Chrome, por exemplo, irá convertê-lo automaticamente emAuthorization
cabeçalho)IMPORTANTE:
Como apontado por @zaph em seu comentário abaixo, enviar informações confidenciais como consulta GET não é uma boa ideia, pois muito provavelmente terminará nos logs do servidor.
fonte
Authorization
cabeçalho. Apenas dê uma chance. Logs lembrarão limpo. E, claro, se você estiver fazendo uma chamada do servidor (se for esse o cenário com o qual está se preocupando), você deve gerar o cabeçalho programaticamente, é claro.username:password@url
do navegador se traduz em:url
+Authorization
cabeçalho da solicitação. Quanto a consultas GET ... bem como eu disse, use o cabeçalho Authroziation. É melhor.Você pode usar um esquema de resposta de desafio. Digamos que o cliente e o servidor conheçam um segredo S. Então o servidor pode ter certeza de que o cliente sabe a senha (sem revelá-la):
Editar:
Há um problema aqui com a atualização do R e o fato de que o HTTP não tem estado. Isso pode ser resolvido fazendo com que o servidor crie um segredo, chame-o de Q, que apenas o servidor conhece . Então, o protocolo é assim:Para notar, uma vez que H (R, Q) não pode ser forjado pelo cliente, H (R, Q) atua como um cookie (e poderia, portanto, ser implementado na verdade como um cookie).Outra edição:
A edição anterior do protocolo está incorreta, pois qualquer pessoa que observou H (R, Q) parece ser capaz de reproduzi-la com o hash correto. O servidor precisa lembrar quais Rs não são mais recentes. Estou fazendo CW esta resposta para que vocês possam editar e descobrir algo bom.
fonte
Se o seu host permitir ou você precisará lidar com dados confidenciais, use HTTPS, ponto final. (Muitas vezes é exigido pela lei afaik).
Caso contrário, se você quiser fazer algo por HTTP. Eu faria algo assim.
Dessa forma, a senha é protegida e o mesmo hash de autenticação não pode ser reproduzido.
Sobre a segurança do token de sessão. Isso é um pouco mais difícil. Mas é possível tornar a reutilização de um token de sessão roubado um pouco mais difícil.
Portanto, se o token de sessão for roubado e uma solicitação for enviada por outra pessoa, na próxima solicitação do usuário original, a sessão será destruída. Portanto, se o usuário estiver navegando ativamente no site, clicando em links com frequência, o ladrão não irá longe com o token roubado. Este esquema pode ser fortalecido exigindo outra autenticação para as operações confidenciais (como exclusão de conta).
EDIT: Observe que isso não evita ataques MITM se o invasor configurar sua própria página com uma chave pública diferente e solicitações de proxy para o servidor. Para se proteger contra isso, a chave pública deve ser fixada no armazenamento local do navegador ou dentro do aplicativo para detectar esse tipo de truque.
Sobre a implementação: RSA é provavelmente o algoritmo mais conhecido, mas é bastante lento para chaves longas. Não sei quão rápida seria uma implementação de PHP ou Javascript. Mas provavelmente existem algoritmos mais rápidos.
fonte
Eu usaria um sistema de troca de chaves Diffie-Hellman do lado do servidor e do lado do cliente com AJAX ou múltiplos envios de formulário (eu recomendo o primeiro), embora não veja nenhuma boa implementação na Internet. Lembre-se de que uma biblioteca JS sempre pode ser corrompida ou alterada pelo MITM. O armazenamento local pode ser usado para ajudar a combater isso, até certo ponto.
fonte
Você pode usar o SRP para usar senhas seguras em um canal inseguro. A vantagem é que mesmo se um invasor farejar o tráfego ou comprometer o servidor, ele não poderá usar as senhas em um servidor diferente. https://github.com/alax/jsrp é uma biblioteca javascript que oferece suporte a senhas seguras sobre HTTP no navegador ou no lado do servidor (via nó).
fonte
HTTPS é tão poderoso porque usa criptografia assimétrica. Esse tipo de criptografia não só permite que você crie um túnel criptografado, mas também pode verificar se está falando com a pessoa certa, e não com um hacker.
Aqui está o código-fonte Java que usa a cifra assimétrica RSA (usada pelo PGP) para se comunicar: http://www.hushmail.com/services/downloads/
fonte
você pode usar SSL para o seu host, há um projeto gratuito para SSL como o letsencrypt https://letsencrypt.org/
fonte
Usar https parece a melhor opção aqui (os certificados não são tão caros hoje em dia). No entanto, se http for um requisito, você pode usar alguma encriptação - encriptá-la no lado do servidor e decript no navegador do usuário (enviar chave separadamente).
Usamos isso durante a implementação do safevia.net - a inscrição é feita nos lados dos clientes (remetente / destinatário), de modo que os dados dos usuários não estão disponíveis na rede nem na camada do servidor.
fonte