¿Cuál es la mejor manera de autenticar a un usuario usando un websocket?

5

Estoy creando un juego multijugador (basado en websockets) que se ejecuta directamente desde el navegador y que tiene funcionalidad multijugador. Cada jugador debe tener su propia cuenta (nombre de usuario y contraseña). Cuando estaba planeando el juego, me di cuenta de que la forma más sencilla de migrarlo a otras plataformas es escribirlo en HTML5. Por lo tanto, necesito crear un sistema de inicio de sesión utilizando JS y websockets. Pero no estoy seguro de cuán seguro es enviar un mensaje con un contenido como nombre de usuario y contraseña al servidor websocket (que se ejecuta en una máquina virtual Java).

    
pregunta zearthur99 18.11.2014 - 00:12
fuente

2 respuestas

7

Si desea seguridad, la transmisión de datos de autenticación a través de TLS es un gran comienzo. Pero supongamos que el websocket ya está configurado sobre TLS. Una solución que recomendaría se basaría en un mecanismo de desafío-respuesta:

  1. El servidor establecería un conjunto aleatorio de bytes (el desafío), establecería un tiempo de espera al final del cual no se autorizaría el desafío.
  2. El cliente enviaría en "texto simple" el nombre de usuario y el desafío y un hash (con un algoritmo SHA2 o SHA3) de challenge || username || f(password) , f(password) es cómo se almacena la contraseña en la base de datos (un SHA256 de password por ejemplo).
  3. El servidor verifica con los datos del nombre de usuario y el desafío de la respuesta y, de ser así, autentica al usuario. También invalida el desafío para invalidar cualquier intento futuro de usar este desafío.

Este método proporciona una funcionalidad anti-reproducción: un atacante no pudo capturar los datos y reproducirlos más tarde para autenticarse.

Sin embargo, tengo un gran problema con este método: f(password) tiene aquí aproximadamente la misma seguridad que password : si la base de datos se filtra, cualquier atacante podría autenticarse como cualquier otra persona. Digo "aproximadamente" porque, si se almacena en texto sin cifrar, ya que muchos usuarios utilizan la misma contraseña en varios sitios web (lo que es malo), sus cuentas podrían verse comprometidas en otro lugar.

No puedo pensar en un método que proteja contra una fuga de base de datos y un mecanismo anti-reproducción, sino un mecanismo de fuga anti-base de datos (enviar la contraseña del usuario en texto claro sobre TLS, la contraseña hash con sal de base de datos y comparar con la base de datos) sobre TLS debería ser suficiente contra la mayoría de los riesgos a los que se enfrentará

    
respondido por el Aniem 18.11.2014 - 00:35
fuente
2

Si desea contraseñas, la mejor manera es usar TLS y luego enviar las contraseñas en claro. Esto es más simple que un mecanismo de desafío-respuesta.

Si, sin embargo, no puede tener TLS para websockets, pero sí tiene TLS para el código (entregado a través de HTTP), lo mejor es hacer el inicio de sesión a través de HTTPS, generar cookies de sesión (o alguna otra forma de clave) y úsalos para autenticarte en el websocket. Si realiza el desafío-respuesta de forma clara, un atacante puede forzar la contraseña de forma brutal utilizando esa comunicación. Con el enfoque de sesión, un atacante solo puede capturar la sesión de su juego (no sensible), pero no la contraseña (posiblemente reutilizada). Sin embargo, cuando no tiene TLS en ninguno de los dos, debe permitir que los usuarios se autentiquen a través de terceros, por ejemplo. a través de OpenID. Entonces no necesita manejar datos confidenciales como contraseñas. OpenID es una buena opción para los otros casos también.

    
respondido por el user10008 18.11.2014 - 02:53
fuente

Lea otras preguntas en las etiquetas