¿Por qué mi cliente no debe enviar el nombre de usuario y la contraseña del usuario con cada solicitud?

2

Tengo un servidor PHP y un cliente Android / iOS, y SSL se usa para todas las comunicaciones.

El servidor PHP es una API JSON con 2 funciones públicas (registro, inicio de sesión) y muchas funciones privadas (que requieren que el usuario esté "conectado").

He pasado por algunas iteraciones y este es el método actual para "iniciar sesión":

  1. El usuario envía una solicitud de inicio de sesión al servidor con un nombre de usuario y contraseña.
  2. El servidor intenta autenticar el nombre de usuario y la contraseña con lo que está almacenado en la base de datos (password_hash () se usa cuando se almacena la contraseña, password_verify () cuando se intenta autenticar, los datos de entrada se validan y sanean, etc.).
  3. Si el nombre de usuario y la contraseña están autenticados, el usuario recibe un JWT que caducará después de 1 minuto.
  4. El JWT contiene: hora de caducidad, nombre de usuario y tipo de usuario.

Todas las funciones privadas requieren un JWT válido y no caducado. 1 función privada está disponible para solicitar un nuevo JWT. Prefiero esta forma de mantener la sesión porque proporciona una especie de latido (el servidor sabe que en un minuto después de que el cliente se vuelve inactivo).

Implementé el sistema de esta manera para que el usuario solo tenga que enviar su nombre de usuario y contraseña una vez, para que el servidor solo tenga que realizar una búsqueda en la base de datos para autenticar al usuario al inicio de la sesión.

Mi pregunta es: ¿se está autenticando una vez y manteniendo una sesión (ya sea que lo haga de esta manera u otra) más seguro que enviar el nombre de usuario y la contraseña con cada solicitud y autenticar cada vez?

    
pregunta 27.04.2018 - 16:36
fuente

3 respuestas

3

Si tiene HTTPS implementado todo el tiempo, no debe preocuparse por la pérdida de la contraseña durante las interacciones entre el usuario y el punto final de la API. HTTPS lo protegerá durante el tránsito en el inicio de sesión, ya que protegerá la contraseña en cada solicitud.

Usted no está más seguro ni menos seguro al enviar información de inicio de sesión en cada solicitud, pero está creando una carga innecesaria en el servidor de aplicaciones. Mucha carga.

Las contraseñas están hechas para ser difíciles de descifrar. El algoritmo de hash espera que alguien intente descifrar las contraseñas fuera de línea, por lo que emplean varias pasadas para ralentizar el proceso de hash. Si la aplicación debe codificar cada contraseña para cada usuario en cada interacción, le está dando a su servidor de aplicaciones un trabajo difícil de hacer.

Entonces, quédate con las fichas. No desde un punto de vista de seguridad, sino desde el punto de vista de rendimiento. Los tokens son para eso, para garantizar que el usuario esté autenticado, lo que cuesta una lectura de un archivo o una búsqueda en la base de datos.

    
respondido por el ThoriumBR 27.04.2018 - 21:12
fuente
4

Si le pide al usuario que ingrese un nombre de usuario y una contraseña cada vez que la aplicación necesite hacer una llamada a la API, tendrán un mal momento y dejarán de usarla. Especialmente si surge una situación en la que una sola "acción" desde su perspectiva inicia múltiples llamadas a la API que necesitarían autenticación por separado. Eso simplemente no es viable. Esa no es la única manera en que "

La alternativa es tener el nombre de usuario y la contraseña del usuario almacenados en su dispositivo, por lo que la aplicación no tiene que preguntar para enviar la solicitud. El usuario no puede distinguir la diferencia entre la aplicación que posee un token arbitrario que permite el acceso en comparación con el nombre de usuario y la contraseña que permite el acceso, así que eso es bueno. Desafortunadamente, también hay algunas fallas en eso, y esas fallas son más relevantes para la seguridad.

Primero, a menos que su aplicación realice un cifrado interno, el nombre de usuario y la contraseña terminan efectivamente almacenados uno al lado del otro en texto plano. Incluso si hay encriptación, la clave de encriptación tiene que ser almacenada cerca de lo que está encriptando, lo que no es mucho mejor. No puedo decir con precisión cuánta vulnerabilidad es esto, y es probable que un token sea igual de vulnerable, pero es probable que un atacante que adquiera un solo token sea menos dañino que uno que obtenga el nombre de usuario completo y la contraseña.

En segundo lugar, como usted sabe, se espera que los tokens caduquen con una frecuencia relativamente alta en comparación con los nombres de usuario y las contraseñas. Por la forma en que está redactada su pregunta, parece que está considerando el nombre de usuario y la contraseña en cada solicitud, ya que el "nivel más alto" de tokens expira rápidamente, pero en realidad es lo contrario: sin token entre, el nombre de usuario y la contraseña se convierten en el token y solo caducan cuando se cambia. Eso hace que la aplicación sea algo más vulnerable a los ataques de reproducción, y hace que sea mucho más incómodo para el usuario si alguna vez implementa controles para detectar comportamientos maliciosos: con un token, puede vencer el token inmediatamente, pero un usuario real puede proporcionar un nombre de usuario y una contraseña para obtén uno nuevo mientras un atacante que obtuvo solo el token está bloqueado. Un usuario que ingresa sus credenciales de vez en cuando es bastante menor, pero forzar el restablecimiento de contraseñas aleatorias es mucho más oneroso y se apoya mucho en una función de restablecimiento seguro de contraseñas.

Por último, el nombre de usuario y la contraseña se transmitirían con mucha más frecuencia. Idealmente, la conexión segura es perfecta y eso no es un problema, pero en la práctica hay algunas vulnerabilidades que son más susceptibles de ser explotadas. Por ejemplo, la vulnerabilidad de CRIME explotó el tamaño de los mensajes enviados para filtrar partes de información, pero requería que exista un valor constante en muchos mensajes. Esa vulnerabilidad exacta probablemente esté parcheada, pero podrían existir otras similares en el futuro y, si sus solicitudes son un tanto filtradas, tener siempre un nombre de usuario y una contraseña en ellos permitirá a la información de un ataque reunir esa información durante mucho tiempo, en comparación con un token que tiene menos impacto al filtrar y limita el tiempo que tiene un atacante para obtenerlo.

Todo eso podría no sumar un compromiso de seguridad grande , pero no me arriesgaría.

    
respondido por el Kamil Drakari 27.04.2018 - 20:37
fuente
0

En primer lugar, si se envían un nombre de usuario y una contraseña en cada solicitud, entonces podrían estar expuestos en cada solicitud, y si tiene un canal seguro (HTTPS), puede mitigarlo, pero puede abrir la posibilidad de un diccionario ataque o ataque de fuerza bruta para tener éxito, ya que un atacante podría tener muchas páginas de su aplicación web para probar una combinación válida de nombre de usuario y contraseña, podría limitar el número de intentos de inicio de sesión por solicitud, pero un atacante podría cambiar la solicitud cuando / Ella estaba bloqueada. Ahora, debe considerar que una aplicación debe tener un equilibrio entre el rendimiento y la seguridad, si su aplicación solicita un nombre de usuario y una contraseña para cada solicitud, su rendimiento se verá afectado y los usuarios podrían decidir no usar más la aplicación por ese motivo. En mi opinión, es mejor tener una sesión de administración que varias solicitudes de autenticación.

Espero que esta información te ayude.

    
respondido por el hmrojas.p 27.04.2018 - 19:23
fuente

Lea otras preguntas en las etiquetas