Si en una pantalla de inicio de sesión el usuario envía un formulario con su nombre de usuario y contraseña, la contraseña se envía en texto sin formato (incluso con POST, corríjame si me equivoco).
Entonces, la pregunta es ¿cuál es la forma correcta de proteger al usuario y su contraseña contra terceros que podrían estar escuchando los datos de comunicación?
Soy consciente de que HTTPS es una solución al problema, pero ¿hay alguna forma de garantizar al menos algún nivel de seguridad utilizando el protocolo HTTP estándar (solicitud POST)? (quizás usando javascript de alguna manera)
EDITAR Es posible que haya omitido algunas cosas importantes.
De lo que trataba era de una página, es decir, una página de inicio de sesión generada por PHP, que por supuesto se envía al usuario en una solicitud HTTP GET como un archivo HTML. No hay una conexión (@Jeremy Powel) establecida entre el servidor y el cliente, por lo que no puedo crear dicho protocolo de intercambio de información. Y quiero que el proceso completo sea transparente para el usuario: quiere enviar una contraseña, no tratar con la criptografía.
Gracias.
Respuestas:
Usar HTTP con SSL le hará la vida mucho más fácil y podrá estar tranquilo. Las personas muy inteligentes (¡al menos más inteligentes que yo!) Han examinado este método de comunicación confidencial durante años.
fuente
La autenticación segura es un tema amplio. En pocas palabras, como mencionó @ jeremy-powell, siempre favorezca el envío de credenciales a través de HTTPS en lugar de HTTP. Eliminará muchos dolores de cabeza relacionados con la seguridad.
Los certificados TSL / SSL son bastante baratos en estos días. De hecho, si no desea gastar dinero en absoluto, existe una autoridad de certificación automatizada de letsencrypt.org gratuita .
Puede ir un paso más allá y usar caddyserver.com que llama a letsencrypt en segundo plano.
Ahora, una vez que sacamos HTTPS del camino ...
No debe enviar el nombre de usuario y la contraseña a través de la carga útil POST o los parámetros GET. En su lugar, utilice un encabezado de autorización (esquema de autenticación de acceso básico), que se construye de la siguiente manera:
Puede parecer un poco complicado, pero no lo es. Hay muchas buenas bibliotecas que le proporcionarán esta funcionalidad de forma inmediata.
Hay algunas buenas razones por las que debería utilizar un encabezado de autorización
https://user:[email protected]/login
(Chrome, por ejemplo, lo convertirá automáticamente enAuthorization
encabezado)IMPORTANTE:
como señala @zaph en su comentario a continuación, enviar información confidencial como consulta GET no es una buena idea, ya que probablemente terminará en los registros del servidor.
fuente
Authorization
encabezado. Solo pruébalo. Los registros recordarán que están limpios. Y, por supuesto, si realiza una llamada desde el servidor (si ese es el escenario que le preocupa), debe generar un encabezado mediante programación, por supuesto.username:password@url
desde el navegador se traduce en:url
+Authorization
encabezado de solicitud. En cuanto a las consultas GET ... bueno, como dije, use el encabezado Authroziation. Es mejor.Puede utilizar un esquema de respuesta al desafío. Digamos que el cliente y el servidor conocen un secreto S. Entonces el servidor puede estar seguro de que el cliente conoce la contraseña (sin revelarla) al:
Editar:
Aquí hay un problema con la actualización de R y el hecho de que HTTP no tiene estado. Esto se puede manejar haciendo que el servidor cree un secreto, llámelo Q, que solo el servidor conoce . Entonces el protocolo es el siguiente:Tenga en cuenta que, dado que el cliente no puede falsificar H (R, Q), H (R, Q) actúa como una cookie (y, por lo tanto, podría implementarse realmente como una cookie).Otra edición:
La edición anterior del protocolo es incorrecta, ya que cualquiera que haya observado H (R, Q) parece ser capaz de reproducirlo con el hash correcto. El servidor debe recordar qué R ya no están actualizadas. Estoy CW'ing esta respuesta para que puedan editar esto y resolver algo bueno.
fuente
Si su proveedor de alojamiento web lo permite, o tendrá que tratar con datos confidenciales, utilice HTTPS, punto. (A menudo es requerido por la ley afaik).
De lo contrario, si desea hacer algo a través de HTTP. Yo haría algo como esto.
De esta manera, la contraseña está protegida y no se puede reproducir el mismo hash de autenticación.
Acerca de la seguridad del token de sesión. Eso es un poco más difícil. Pero es posible hacer que la reutilización de un token de sesión robado sea un poco más difícil.
Entonces, si el token de sesión fue robado y otra persona envía una solicitud, en la próxima solicitud del usuario original, la sesión se destruirá. Entonces, si el usuario navega activamente por el sitio, haciendo clic en los enlaces con frecuencia, el ladrón no llegará muy lejos con el token robado. Este esquema se puede fortalecer al requerir otra autenticación para las operaciones sensibles (como la eliminación de la cuenta).
EDITAR: tenga en cuenta que esto no evita los ataques MITM si el atacante configura su propia página con una clave pública diferente y envía solicitudes de proxy al servidor. Para protegerse contra esto, la clave pública debe estar anclada en el almacenamiento local del navegador o dentro de la aplicación para detectar este tipo de trucos.
Acerca de la implementación: RSA es probablemente el algoritmo más conocido, pero es bastante lento para claves largas. No sé qué tan rápida sería una implementación de PHP o Javascript. Pero probablemente haya algoritmos más rápidos.
fuente
Usaría un sistema de intercambio de claves Diffie-Hellman del lado del servidor y del lado del cliente con AJAX o envíos de formularios múltiples (recomiendo el primero), aunque no veo ninguna buena implementación del mismo en Internet. Recuerde que MITM siempre puede dañar o modificar una biblioteca JS. El almacenamiento local se puede utilizar para ayudar a combatir esto, hasta cierto punto.
fuente
Puede utilizar SRP para utilizar contraseñas seguras en un canal inseguro. La ventaja es que incluso si un atacante rastrea el tráfico o compromete el servidor, no puede usar las contraseñas en un servidor diferente. https://github.com/alax/jsrp es una biblioteca de JavaScript que admite contraseñas seguras a través de HTTP en el navegador o en el servidor (a través del nodo).
fuente
HTTPS es tan poderoso porque usa criptografía asimétrica. Este tipo de criptografía no solo te permite crear un túnel encriptado, sino que puedes verificar que estás hablando con la persona adecuada y no con un hacker.
Aquí está el código fuente de Java que usa el cifrado asimétrico RSA (usado por PGP) para comunicarse: http://www.hushmail.com/services/downloads/
fuente
puede usar ssl para su host, hay un proyecto gratuito para ssl como letsencrypt https://letsencrypt.org/
fuente
Usar https suena como la mejor opción aquí (los certificados no son tan caros hoy en día). Sin embargo, si http es un requisito, puede usar alguna encripción: encriptarlo en el lado del servidor y describirlo en el navegador de los usuarios (envíe la clave por separado).
Lo hemos utilizado al implementar safevia.net : la inscripción se realiza en el lado de los clientes (remitente / receptor), por lo que los datos de los usuarios no están disponibles en la red ni en la capa del servidor.
fuente