La guía definitiva para la autenticación de sitios web basada en formularios

Autenticación basada en formularios para sitios web

Creemos que Stack Overflow no debería ser sólo un recurso para preguntas técnicas muy específicas, sino también para directrices generales sobre cómo resolver variaciones de problemas comunes. "La autenticación basada en formularios para sitios web" debería ser un buen tema para tal experimento.

Debería incluir temas como:

  • Cómo iniciar la sesión
  • Cómo cerrar la sesión
  • Cómo permanecer conectado
  • Gestión de las cookies (incluida la configuración recomendada)
  • Cifrado SSL/HTTPS
  • Cómo almacenar las contraseñas
  • Uso de preguntas secretas
  • Funcionalidad de nombre de usuario/contraseña olvidada
  • Uso de nonces para evitar falsificaciones de solicitudes en sitios cruzados (CSRF)
  • OpenID
  • Casilla de verificación "Recuérdame".
  • Autocompletado de nombres de usuario y contraseñas en el navegador
  • URLs secretas (públicas URL protegidas por digest)
  • Comprobación de la solidez de la contraseña
  • Validación del correo electrónico
  • y mucho más sobre autenticación basada en formularios...

No debería incluir cosas como:

  • Roles y autorización
  • Autenticación básica HTTP

Por favor, ayúdenos con:

  1. Sugiriendo subtemas
  2. Enviando buenos artículos sobre este tema
  3. Editar la respuesta oficial
Solución

PARTE I: Cómo iniciar sesión

Asumiremos que ya sabes cómo construir un formulario HTML de login+contraseña que envía los valores a un script en el lado del servidor para la autenticación. Las secciones siguientes tratarán sobre los patrones para una autenticación práctica y sólida, y sobre cómo evitar las trampas de seguridad más comunes. ¿HTTPS o no HTTPS? A menos que la conexión sea ya segura (es decir, que se haya hecho un túnel a través de HTTPS usando SSL/TLS), los valores de tu formulario de inicio de sesión se enviarán en texto claro, lo que permite que cualquiera que espíe la línea entre el navegador y el servidor web sea capaz de leer los inicios de sesión a medida que pasan. Este tipo de espionaje es realizado rutinariamente por los gobiernos, pero en general, no abordaremos los cables "propios" más que para decir esto: Simplemente usa HTTPS. En esencia, la única forma práctica de protegerse contra el espionaje telefónico/espionaje de paquetes durante el inicio de sesión es utilizando HTTPS u otro esquema de encriptación basado en certificados (por ejemplo, [TLS][1]) o un esquema de respuesta a desafíos probado y comprobado (por ejemplo, el SRP basado en [Diffie-Hellman][2]). Cualquier otro método puede ser fácilmente burlado por un atacante que espíe. Por supuesto, si estás dispuesto a ser un poco impráctico, también podrías emplear algún tipo de esquema de autenticación de dos factores (por ejemplo, la aplicación Google Authenticator, un libro de códigos físico al estilo de la "guerra fría", o un dongle generador de claves RSA). Si se aplica correctamente, esto podría funcionar incluso con una conexión no segura, pero es difícil imaginar que un desarrollador esté dispuesto a implementar la autenticación de dos factores pero no el SSL. (No) Enrolle su propio cifrado/cashing de JavaScript. Dado el coste percibido (aunque ahora [evitable][27]) y la dificultad técnica de configurar un certificado SSL en tu sitio web, algunos desarrolladores se ven tentados a implementar sus propios esquemas de cifrado o hashing en el navegador para evitar pasar los inicios de sesión en texto claro por un cable no seguro. Aunque se trata de una idea noble, es esencialmente inútil (y puede ser un [fallo de seguridad][3]) a menos que se combine con una de las medidas anteriores, es decir, asegurando la línea con un cifrado fuerte o utilizando un mecanismo de desafío-respuesta probado (si no sabes lo que es, sólo tienes que saber que es uno de los conceptos más difíciles de probar, más difíciles de diseñar y más difíciles de implementar en la seguridad digital). Si bien es cierto que el hashing de la contraseña puede ser efectivo contra la revelación de la contraseña, es vulnerable a los ataques de repetición, a los ataques Man-In-The-Middle / hijackings (si un atacante puede inyectar unos pocos bytes en su página HTML no segura antes de que llegue a su navegador, puede simplemente comentar el hashing en el JavaScript), o a los ataques de fuerza bruta (ya que está entregando al atacante tanto el nombre de usuario, como la sal y la contraseña hashed). CAPTCHAS contra la humanidad Los [CAPTCHA][4] están pensados para frustrar una categoría específica de ataque: diccionario automatizado/fuerza bruta de ensayo y error sin operador humano. No hay duda de que esta es una amenaza real, sin embargo, hay maneras de lidiar con ella sin problemas que no requieren un CAPTCHA, específicamente esquemas de estrangulamiento de inicio de sesión del lado del servidor diseñados adecuadamente - hablaremos de ellos más adelante. Sepa que las implementaciones de CAPTCHA no son creadas de la misma manera; a menudo no son solucionables por humanos, la mayoría de ellas son realmente ineficaces contra los bots, todas ellas son ineficaces contra la mano de obra barata del tercer mundo (según [OWASP][5], la tasa actual de explotación es de 12 dólares por 500 pruebas), y algunas implementaciones pueden ser técnicamente ilegales en algunos países (ver [OWASP Authentication Cheat Sheet][6]). Si tienes que usar un CAPTCHA, usa el de Google [reCAPTCHA][7], ya que es OCR-difícil por definición (ya que usa escaneos de libros mal clasificados por OCR) y se esfuerza por ser amigable con el usuario. Personalmente, tiendo a encontrar los CAPTCHAS molestos, y los utilizo sólo como último recurso cuando un usuario ha fallado en el inicio de sesión un número de veces y los retrasos de estrangulamiento están al máximo. Esto ocurrirá en contadas ocasiones para que sea aceptable, y refuerza el sistema en su conjunto. Almacenamiento de contraseñas/verificación de inicios de sesión Puede que esto sea finalmente de dominio público después de todos los hackeos y filtraciones de datos de usuarios que hemos visto en los últimos años, pero hay que decirlo: No almacene las contraseñas en texto claro en su base de datos. Las bases de datos de usuarios se piratean, se filtran o se obtienen a través de la inyección de SQL, y si almacena contraseñas en texto plano, la seguridad de su inicio de sesión se acaba al instante. Entonces, si no puedes almacenar la contraseña, ¿cómo compruebas que la combinación de nombre de usuario y contraseña enviada desde el formulario de acceso es correcta? La respuesta es un hash usando una [función de derivación de clave][24]. Cada vez que se crea un nuevo usuario o se cambia una contraseña, se toma la contraseña y se ejecuta a través de una KDF, como Argon2, bcrypt, scrypt o PBKDF2, convirtiendo la contraseña en texto claro ("correcthorsebatterystaple") en una cadena larga y de aspecto aleatorio, que es mucho más segura para almacenar en su base de datos. Para verificar un inicio de sesión, se ejecuta la misma función hash en la contraseña introducida, esta vez pasando la sal y comparando la cadena hash resultante con el valor almacenado en su base de datos. Argon2, bcrypt y scrypt ya almacenan la sal con el hash. Consulta este [artículo][23] en sec.stackexchange para obtener información más detallada. La razón por la que se utiliza una sal es que el hash en sí mismo no es suficiente - querrás añadir una "sal" para proteger el hash contra [tablas arco iris][8]. Una sal previene efectivamente que dos contraseñas que coincidan exactamente sean almacenadas como el mismo valor hash, previniendo que toda la base de datos sea escaneada en una sola ejecución si un atacante está ejecutando un ataque de adivinación de contraseñas. Un hash criptográfico no debería usarse para el almacenamiento de contraseñas porque las contraseñas seleccionadas por el usuario no son lo suficientemente fuertes (es decir, no suelen contener suficiente entropía) y un ataque de adivinación de contraseñas podría ser completado en un tiempo relativamente corto por un atacante con acceso a los hashes. Por eso se utilizan los KDF, que efectivamente ["estiran la clave"][25], lo que significa que cada vez que un atacante adivina la contraseña provoca múltiples repeticiones del algoritmo hash, por ejemplo 10.000 veces, lo que hace que el atacante adivine la contraseña 10.000 veces más lentamente. **Datos de la sesión: "Ha iniciado sesión como Spiderman69". Una vez que el servidor ha verificado el nombre de usuario y la contraseña con su base de datos de usuarios y ha encontrado una coincidencia, el sistema necesita una forma de recordar que el navegador ha sido autenticado. Este hecho sólo debe ser almacenado del lado del servidor en los datos de la sesión.

Si no estás familiarizado con los datos de sesión, así es como funcionan: Una única cadena generada aleatoriamente se almacena en una cookie que expira y se utiliza para referenciar una colección de datos -los datos de sesión- que se almacenan en el servidor. Si está utilizando un marco de trabajo MVC, sin duda esto ya se maneja. Si es posible, asegúrese de que la cookie de sesión tiene las banderas de seguridad y HTTP Only establecidas cuando se envía al navegador. La bandera HttpOnly proporciona cierta protección contra la lectura de la cookie a través de un ataque XSS. La bandera segura asegura que la cookie sólo se envía de vuelta a través de HTTPS, y por lo tanto protege contra los ataques de sniffing de la red. El valor de la cookie no debe ser predecible. Cuando se presenta una cookie que hace referencia a una sesión inexistente, su valor debe ser reemplazado inmediatamente para evitar la fijación de la sesión.

PARTE II: Cómo permanecer conectado - La infame casilla "Recuérdame"

Las cookies persistentes de inicio de sesión (funcionalidad "recuérdame") son una zona de peligro; por un lado, son totalmente tan seguras como los inicios de sesión convencionales cuando los usuarios entienden cómo manejarlas; y por otro lado, son un enorme riesgo de seguridad en manos de usuarios descuidados, que pueden usarlas en ordenadores públicos y olvidarse de cerrar la sesión, y que pueden no saber qué son las cookies del navegador o cómo eliminarlas. Personalmente, me gustan los inicios de sesión persistentes para los sitios web que visito regularmente, pero sé cómo manejarlos de forma segura. Si está seguro de que sus usuarios saben lo mismo, puede utilizar los inicios de sesión persistentes con la conciencia tranquila. Si no es así, entonces puede suscribir la filosofía de que los usuarios que son descuidados con sus credenciales de inicio de sesión se lo buscaron si son hackeados. Tampoco es que vayamos a las casas de nuestros usuarios y arranquemos todas esas notas Post-It con las contraseñas que tienen alineadas en el borde de sus monitores. Por supuesto, algunos sistemas no pueden permitirse el lujo de tener cualquier cuenta hackeada; para tales sistemas, no hay manera de justificar tener inicios de sesión persistentes. **Si decide implementar cookies de inicio de sesión persistente, así es como debe hacerlo

  1. Primero, tómate un tiempo para leer el artículo de Paragon Initiative sobre el tema. Necesitarás tener un montón de elementos correctos, y el artículo hace un gran trabajo explicando cada uno de ellos.
  2. El token de inicio de sesión es equivalente a una contraseña, por lo que si un atacante tiene en sus manos su base de datos, podría utilizar los tokens para iniciar sesión en cualquier cuenta, como si fueran combinaciones de texto claro de inicio de sesión y contraseña. Por lo tanto, utiliza hash (según https://security.stackexchange.com/a/63438/5002 un hash débil servirá para este propósito) cuando almacenes tokens de acceso persistentes.

    PARTE III: Utilización de preguntas secretas

    **No implementes las "preguntas secretas". La función de "preguntas secretas" es un anti-patrón de seguridad. Lee el artículo del enlace número 4 de la lista de LECTURAS IMPRESCINDIBLES. Puedes preguntarle a Sarah Palin sobre eso, después de que su cuenta de correo electrónico de Yahoo! fuera hackeada durante una campaña presidencial anterior porque la respuesta a su pregunta de seguridad era... ¡"Wasilla High School"! Incluso con preguntas especificadas por el usuario, es muy probable que la mayoría de los usuarios elijan cualquiera de ellas:

  • Una pregunta secreta "estándar" como el nombre de soltera de la madre o la mascota favorita
  • Un simple dato que cualquiera podría sacar de su blog, perfil de LinkedIn o similar
  • Cualquier pregunta que sea más fácil de responder que adivinar su contraseña. Lo cual, para cualquier contraseña decente, es cualquier pregunta que puedas imaginar **En conclusión, las preguntas de seguridad son intrínsecamente inseguras en prácticamente todas sus formas y variaciones, y no deberían emplearse en un esquema de autenticación por ningún motivo. La verdadera razón por la que las preguntas de seguridad existen en la naturaleza es que ahorran convenientemente el coste de unas cuantas llamadas de soporte de usuarios que no pueden acceder a su correo electrónico para conseguir un código de reactivación. Esto a costa de la seguridad y de la reputación de Sarah Palin. ¿Merece la pena? Probablemente no.

    PARTE IV: Funcionalidad de la contraseña olvidada

    Ya he mencionado por qué no deberías nunca utilizar preguntas de seguridad para gestionar las contraseñas olvidadas/perdidas de los usuarios; tampoco hace falta decir que nunca deberías enviar por correo electrónico a los usuarios sus contraseñas reales. Hay al menos otros dos escollos demasiado comunes que hay que evitar en este campo:

  1. Este tipo de contraseñas son muy difíciles de recordar, lo que significa que el usuario debe cambiarlas o escribirlas, por ejemplo, en un post-it amarillo brillante en el borde de su monitor. En lugar de establecer una nueva contraseña, deja que los usuarios elijan una nueva de inmediato, que es lo que quieren hacer de todos modos. (Una excepción a esto podría ser si los usuarios utilizan universalmente un gestor de contraseñas para almacenar/gestionar contraseñas que normalmente serían imposibles de recordar sin escribirlas).
  2. Siempre hay que hacer un hash del código/token de la contraseña perdida en la base de datos. AGAIN, este código es otro ejemplo de un equivalente de contraseña, por lo que DEBE ser sometido a hash en caso de que un atacante ponga sus manos en su base de datos. Cuando se solicite un código de contraseña perdido, envíe el código en texto plano a la dirección de correo electrónico del usuario, luego hachéelo, guarde el hash en su base de datos -- y deseche el original. Al igual que una contraseña o un token de inicio de sesión persistente. Una nota final: asegúrate siempre de que tu interfaz para introducir el "código de contraseña perdida" es al menos tan segura como tu formulario de acceso, o un atacante simplemente lo utilizará para obtener acceso. Asegurarse de generar "códigos de contraseña perdida" muy largos (por ejemplo, 16 caracteres alfanuméricos que distingan entre mayúsculas y minúsculas) es un buen comienzo, pero considere añadir el mismo esquema de estrangulamiento que hace para el propio formulario de acceso.

    PARTE V: Comprobación de la solidez de la contraseña

    Primero, querrás leer este pequeño artículo para comprobar la realidad: Las 500 contraseñas más comunes Vale, puede que la lista no sea la lista canónica de contraseñas más comunes en cualquier sistema en cualquier lugar, pero es una buena indicación de lo mal que la gente elige sus contraseñas cuando no hay una política impuesta. Además, la lista se ve aterradoramente cerca de casa cuando la comparas con los análisis disponibles públicamente de las contraseñas robadas recientemente. Así pues: Sin requisitos mínimos de seguridad de las contraseñas, el 2% de los usuarios utiliza una de las 20 contraseñas más comunes. Es decir, si un atacante consigue sólo 20 intentos, 1 de cada 50 cuentas de su sitio web será descifrable. Para evitarlo, hay que calcular la entropía de una contraseña y aplicar un umbral. El Instituto Nacional de Estándares y Tecnología (NIST) Publicación Especial 800-63 tiene un conjunto de sugerencias muy buenas. Eso, cuando se combina con un diccionario y un análisis de la disposición del teclado (por ejemplo, "qwertyuiop" es una mala contraseña), puede rechazar el 99% de todas las contraseñas mal seleccionadas a un nivel de 18 bits de entropía. Calcular simplemente la fuerza de la contraseña y mostrar un medidor de fuerza visual a un usuario es bueno, pero insuficiente. A menos que se imponga, lo más probable es que muchos usuarios lo ignoren. Y para una visión refrescante de la facilidad de uso de las contraseñas de alta entropía, es muy recomendable Password Strength xkcd de Randall Munroe. Utiliza Troy Hunt's Have I Been Pwned API para comprobar las contraseñas de los usuarios con las contraseñas comprometidas en las violaciones de datos públicas.

    PARTE VI: Mucho más - O: Cómo prevenir los intentos de inicio de sesión rápidos

    Primero, echa un vistazo a los números: Velocidades de recuperación de contraseñas - Cuánto tiempo resistirá su contraseña Si no tienes tiempo para mirar las tablas en ese enlace, aquí está la lista de ellas:

  3. No se tarda virtualmente nada en descifrar una contraseña débil, incluso si la descifras con un ábaco
  4. No se tarda prácticamente nada en descifrar una contraseña alfanumérica de 9 caracteres si no se distingue entre mayúsculas y minúsculas.
  5. No lleva prácticamente nada de tiempo descifrar una contraseña intrincada, de símbolos y letras y números, en mayúsculas y minúsculas, si tiene menos de 8 caracteres (un PC de sobremesa puede buscar en todo el espacio de claves de hasta 7 caracteres en cuestión de días o incluso horas)
  6. *Sin embargo, se necesitaría un tiempo desmesurado para descifrar incluso una contraseña de 6 caracteres, si se limitara a un intento por segundo. ¿Qué podemos aprender de estas cifras? Bueno, muchas cosas, pero podemos centrarnos en la parte más importante: el hecho de que evitar un gran número de intentos de inicio de sesión sucesivos y rápidos (es decir, el ataque de fuerza bruta) no es tan difícil. Pero prevenirlo bien no es tan fácil como parece. En general, tienes tres opciones que son efectivas contra los ataques de fuerza bruta (y los ataques de diccionario, pero como ya estás empleando una política de contraseñas fuertes, no deberían ser un problema)*:
  • Presentar un CAPTCHA después de N intentos fallidos (molesto como el infierno y a menudo ineficaz - pero me estoy repitiendo aquí)
  • Bloquear las cuentas y requerir la verificación del correo electrónico después de N intentos fallidos (esto es un ataque DoS a punto de ocurrir)
  • Y, por último, el estrangulamiento del inicio de sesión: es decir, establecer un tiempo de espera entre los intentos después de N intentos fallidos (sí, los ataques DoS siguen siendo posibles, pero al menos son mucho menos probables y mucho más complicados de llevar a cabo). La mejor práctica #1: Un corto retraso de tiempo que aumenta con el número de intentos fallidos, como:
  • 1 intento fallido = sin retardo
  • 2 intentos fallidos = 2 segundos de retraso
  • 3 intentos fallidos = 4 segundos de retraso
  • 4 intentos fallidos = 8 segundos de retraso
  • 5 intentos fallidos = 16 segundos de retraso
  • etc. Un ataque DoS a este esquema sería muy poco práctico, ya que el tiempo de bloqueo resultante es ligeramente mayor que la suma de los tiempos de bloqueo anteriores. Para aclarar: El retraso es no un retraso antes de devolver la respuesta al navegador. Es más bien un tiempo de espera o período refractario durante el cual los intentos de inicio de sesión a una cuenta específica o desde una dirección IP específica no serán aceptados o evaluados en absoluto. Es decir, las credenciales correctas no volverán en un inicio de sesión exitoso, y las credenciales incorrectas no desencadenarán un aumento de la demora. Mejor práctica #2: Un retardo de duración media que entre en vigor después de N intentos fallidos, como:
  • 1-4 intentos fallidos = sin retardo
  • 5 intentos fallidos = 15-30 minutos de retraso Un ataque DoS a este esquema sería bastante poco práctico, pero ciertamente factible. Además, podría ser relevante señalar que un retraso tan largo puede ser muy molesto para un usuario legítimo. A los usuarios olvidadizos no les gustará. Mejor práctica #3: Combinando los dos enfoques - ya sea un retraso fijo y corto que entre en vigor después de N intentos fallidos, como:
  • 1-4 intentos fallidos = sin retardo
  • 5+ intentos fallidos = 20 segundos de retraso O bien, un retraso creciente con un límite superior fijo, como:
  • 1 intento fallido = 5 segundos de retraso
  • 2 intentos fallidos = 15 segundos de retraso
  • Más de 3 intentos fallidos = 45 segundos de retraso Este esquema final fue tomado de las sugerencias de mejores prácticas de OWASP (enlace 1 de la lista MUST-READ) y debería ser considerado como una mejor práctica, incluso si se admite que está en el lado restrictivo. Como regla general, sin embargo, yo diría: cuanto más fuerte sea su política de contraseñas, menos tendrá que molestar a los usuarios con retrasos. Si requieres contraseñas fuertes (alfanuméricas sensibles a mayúsculas y minúsculas + números y símbolos requeridos) de más de 9 caracteres, podrías dar a los usuarios 2-4 intentos de contraseña sin retraso antes de activar el throttling. Un ataque DoS a este esquema de limitación de acceso final sería muy poco práctico. Y como toque final, siempre permita que los inicios de sesión persistentes (con cookies) (y/o un formulario de inicio de sesión verificado con CAPTCHA) pasen, de modo que los usuarios legítimos ni siquiera se retrasen mientras el ataque está en curso. De esta manera, el muy poco práctico ataque DoS se convierte en un ataque extremadamente poco práctico. Además, tiene sentido hacer un estrangulamiento más agresivo en las cuentas de administrador, ya que son los puntos de entrada más atractivos

    PARTE VII: Ataques de fuerza bruta distribuidos

    Sólo como un aparte, los atacantes más avanzados tratarán de eludir el estrangulamiento del inicio de sesión "distribuyendo sus actividades":

  • Distribuyendo los intentos en una red de bots para evitar que se marquen las direcciones IP.
  • En lugar de elegir un usuario y probar las 50.000 contraseñas más comunes (que no pueden, debido a nuestro estrangulamiento), elegirán LA contraseña más común y la probarán contra 50.000 usuarios. De esta manera, no sólo evitan las medidas de intentos máximos como los CAPTCHAs y el estrangulamiento del inicio de sesión, sino que también aumentan sus posibilidades de éxito, ya que la contraseña más común número 1 es mucho más probable que la número 49.995
  • Espaciar las solicitudes de inicio de sesión para cada cuenta de usuario, por ejemplo, con 30 segundos de diferencia, para pasar desapercibido En este caso, la mejor práctica sería registrar el número de inicios de sesión fallidos, en todo el sistema, y utilizar una media de la frecuencia de inicios de sesión incorrectos de su sitio como base para un límite máximo que luego imponga a todos los usuarios. ¿Demasiado abstracto? Lo diré de otra manera: Digamos que su sitio ha tenido una media de 120 inicios de sesión incorrectos al día durante los últimos 3 meses. Utilizando esa media, el sistema podría establecer un límite global 3 veces superior, es decir, 360 intentos fallidos en un periodo de 24 horas. Entonces, si el número total de intentos fallidos a través de todas las cuentas excede ese número dentro de un día (o incluso mejor, monitorear la tasa de aceleración y el gatillo en un umbral calculado), activa el estrangulamiento de inicio de sesión en todo el sistema - lo que significa retrasos cortos para TODOS los usuarios (todavía, con la excepción de los inicios de sesión de cookies y / o de copia de seguridad CAPTCHA). También publiqué una pregunta con más detalles y una muy buena discusión sobre cómo evitar trampas complicadas en la defensa de los ataques de fuerza bruta distribuidos

    PARTE VIII: Autenticación de dos factores y proveedores de autenticación

    Las credenciales pueden verse comprometidas, ya sea por exploits, por anotaciones y pérdidas de contraseñas, por el robo de portátiles con llaves o por la introducción de inicios de sesión en sitios de phishing. Los inicios de sesión pueden protegerse aún más con la autenticación de dos factores, que utiliza factores fuera de banda como códigos de un solo uso recibidos de una llamada telefónica, un mensaje SMS, una aplicación o un dongle. Varios proveedores ofrecen servicios de autenticación de dos factores. La autenticación puede delegarse completamente en un servicio de inicio de sesión único, en el que otro proveedor se encarga de recoger las credenciales. De este modo, el problema se traslada a un tercero de confianza. Google y Twitter ofrecen servicios SSO basados en estándares, mientras que Facebook ofrece una solución propietaria similar.

    ENLACES IMPRESCINDIBLES sobre la autenticación web

  1. Guía OWASP para la autenticación / Hoja de trucos de autenticación OWASP
    1. Dos and Don'ts of Client Authentication on the Web (documento de investigación del MIT muy legible)
  2. Wikipedia: cookie HTTP
  3. Preguntas de conocimiento personal para la autenticación fallida: Cuestiones de seguridad en la era de Facebook (documento de investigación de Berkeley muy legible)
Comentarios (70)

Artículo definitivo

Envío de credenciales

La única forma práctica de enviar credenciales de forma 100% segura es utilizando [SSL][1]. Usar JavaScript para hacer hash de la contraseña no es seguro. Escollos comunes para el hash de contraseñas del lado del cliente:

  • Si la conexión entre el cliente y el servidor no está encriptada, todo lo que se hace es [vulnerable a los ataques del hombre en el medio][2]. Un atacante podría reemplazar el javascript entrante para romper el hashing o enviar todas las credenciales a su servidor, podría escuchar las respuestas del cliente y suplantar a los usuarios perfectamente, etc. etc. SSL con Autoridades de Certificación de confianza está diseñado para prevenir ataques MitM.
  • La contraseña hash recibida por el servidor es [menos segura][3] si no se hace un trabajo adicional y redundante en el servidor. Hay otro método seguro llamado SRP, pero está patentado (aunque tiene [licencia libre][4]) y hay pocas buenas implementaciones disponibles.

    Almacenamiento de contraseñas

    Nunca almacene las contraseñas como texto plano en la base de datos. Ni siquiera si no te importa la seguridad de tu propio sitio. Asume que algunos de tus usuarios reutilizarán la contraseña de su cuenta bancaria online. Entonces, almacene la contraseña con hash, y deseche la original. Y asegúrese de que la contraseña no aparezca en los registros de acceso o de la aplicación. OWASP recomienda el uso de Argon2 como primera opción para las nuevas aplicaciones. Si no está disponible, se debe utilizar PBKDF2 o scrypt en su lugar. Y finalmente, si ninguno de los anteriores está disponible, utilice bcrypt. Los hash por sí mismos también son inseguros. Por ejemplo, contraseñas idénticas significan hashes idénticos - esto hace que las tablas de búsqueda de hash sean una forma efectiva de descifrar muchas contraseñas a la vez. En su lugar, almacena el hash salted. Una sal es una cadena que se añade a la contraseña antes del hash - utiliza una sal diferente (aleatoria) por usuario. La sal es un valor público, así que puedes almacenarla con el hash en la base de datos. Ver aquí para más información sobre esto. Esto significa que no puedes enviar al usuario sus contraseñas olvidadas (porque sólo tienes el hash). No restablezca la contraseña del usuario a menos que haya autenticado al usuario (los usuarios deben demostrar que son capaces de leer los correos electrónicos enviados a la dirección de correo electrónico almacenada (y validada)).

    Preguntas de seguridad

    Las preguntas de seguridad son inseguras - evita usarlas. ¿Por qué? Todo lo que hace una pregunta de seguridad, lo hace mejor una contraseña. Lee Parte III: Uso de preguntas secretas en [@Jens Roland answer][6] aquí en este wiki.

    Cookies de sesión

    Después de que el usuario inicie la sesión, el servidor envía al usuario una cookie de sesión. El servidor puede recuperar el nombre de usuario o el id de la cookie, pero nadie más puede generar dicha cookie (TODO explicar los mecanismos). [Las cookies pueden ser secuestradas][7]: son tan seguras como el resto de la máquina del cliente y otras comunicaciones. Pueden ser leídas desde el disco, olfateadas en el tráfico de red, levantadas por un ataque de cross-site scripting, suplantadas desde un DNS envenenado para que el cliente envíe sus cookies a los servidores equivocados. No envíe cookies persistentes. Las cookies deben expirar al final de la sesión del cliente (cierre del navegador o salida de su dominio). Si quieres autologizar a tus usuarios, puedes establecer una cookie persistente, pero debe ser distinta de una cookie de sesión completa. Puede establecer una bandera adicional que indique que el usuario se ha autolocalizado, y que necesita entrar de verdad para las operaciones sensibles. Esto es muy popular en los sitios de compras que quieren ofrecerle una experiencia de compra personalizada y sin problemas, pero protegiendo sus datos financieros. Por ejemplo, cuando vuelves a visitar Amazon, te muestran una página que parece que has iniciado la sesión, pero cuando vas a hacer un pedido (o a cambiar tu dirección de envío, tarjeta de crédito, etc.), te piden que confirmes tu contraseña. Los sitios web financieros, como los bancos y las tarjetas de crédito, por otro lado, sólo tienen datos sensibles y no deberían permitir el inicio de sesión automático o un modo de baja seguridad.

    Lista de recursos externos

Comentarios (5)

En primer lugar, una fuerte advertencia de que esta respuesta no es la más adecuada para esta pregunta exacta. Definitivamente no debería ser la respuesta principal.

Me adelantaré y mencionaré la propuesta de Mozilla BrowserID (o quizás más precisamente, el Protocolo de Correo Electrónico Verificado) en el espíritu de encontrar un camino de actualización hacia mejores enfoques de autenticación en el futuro.

Lo resumiré así:

  1. Mozilla es una organización sin ánimo de lucro con valores que se alinean bien con la búsqueda de buenas soluciones a este problema.
  2. La realidad actual es que la mayoría de los sitios web utilizan la autenticación basada en formularios
  3. La autenticación basada en formularios tiene un gran inconveniente, que es un mayor riesgo de phishing. Se pide a los usuarios que introduzcan información sensible en un área controlada por una entidad remota, en lugar de un área controlada por su Agente de Usuario (navegador).
  4. Dado que los navegadores son de confianza implícita (la idea de un Agente de Usuario es actuar en nombre del Usuario), pueden ayudar a mejorar esta situación.
  5. La principal fuerza que frena el progreso aquí es el bloqueo del despliegue. Las soluciones deben descomponerse en pasos que proporcionen algún beneficio incremental por sí mismos.
  6. El método descentralizado más sencillo para expresar una identidad que está integrada en la infraestructura de Internet es el nombre de dominio.
  7. Como segundo nivel de expresión de la identidad, cada dominio gestiona su propio conjunto de cuentas.
  8. La forma "cuenta@dominio" es concisa y soportada por una amplia gama de protocolos y esquemas URI. Este identificador es, por supuesto, el más universalmente reconocido como una dirección de correo electrónico.
  9. Los proveedores de correo electrónico ya son los principales proveedores de identidad en línea. Los flujos actuales de restablecimiento de contraseñas suelen permitirte tomar el control de una cuenta si puedes demostrar que controlas la dirección de correo electrónico asociada a esa cuenta.
  10. El protocolo de correo electrónico verificado se propuso para proporcionar un método seguro, basado en la criptografía de clave pública, para agilizar el proceso de demostrar al dominio B que se tiene una cuenta en el dominio A.
  11. Para los navegadores que no soportan el Verified Email Protocol (actualmente todos), Mozilla proporciona un shim que implementa el protocolo en código JavaScript del lado del cliente.
  12. Para los servicios de correo electrónico que no soportan el Protocolo de Correo Electrónico Verificado, el protocolo permite que terceras partes actúen como intermediarios de confianza, afirmando que han verificado la propiedad de una cuenta por parte de un usuario. No es deseable tener un gran número de estos terceros; esta capacidad está pensada sólo para permitir una ruta de actualización, y es muy preferible que los servicios de correo electrónico proporcionen estas afirmaciones ellos mismos.
  13. Mozilla ofrece su propio servicio para actuar como una tercera parte de confianza. Los proveedores de servicios (es decir, las partes que confían) que implementan el protocolo de correo electrónico verificado pueden optar por confiar o no en las afirmaciones de Mozilla. El servicio de Mozilla verifica la propiedad de la cuenta de los usuarios utilizando el medio convencional de enviar un correo electrónico con un enlace de confirmación.
  14. Los proveedores de servicios pueden, por supuesto, ofrecer este protocolo como una opción además de cualquier otro método(s) de autenticación que deseen ofrecer.
  15. Una gran ventaja de la interfaz de usuario que se busca aquí es el "selector de identidad". Cuando un usuario visita un sitio y elige autenticarse, su navegador le muestra una selección de direcciones de correo electrónico ("personal", "trabajo", "activismo político", etc.) que puede utilizar para identificarse ante el sitio.
  16. Otro gran beneficio de la interfaz de usuario que se está buscando como parte de este esfuerzo es ayudar al navegador a saber más sobre la sesión del usuario -como quién ha iniciado la sesión actualmente, principalmente- para que pueda mostrar eso en el cromo del navegador.
  17. Debido a la naturaleza distribuida de este sistema, se evita el bloqueo de los principales sitios como Facebook, Twitter, Google, etc. Cualquier persona puede poseer su propio dominio y, por tanto, actuar como su propio proveedor de identidad.

No se trata estrictamente de una "autenticación basada en formularios para sitios web". Pero sí es un esfuerzo para pasar de la norma actual de autenticación basada en formularios a algo más seguro: la autenticación soportada por el navegador.

Comentarios (2)