Problemas de seguridad de la API REST sin token

5

Estoy diseñando una API en PHP / MySQL que, por su diseño, no almacenará la contraseña de un usuario en la base de datos y, por lo tanto, no genera tokens de autorización para que el cliente los tenga. La razón de esto es para evitar cualquier posibilidad de obtener información confidencial y sin cifrar en el caso de un compromiso de la base de datos.

Los datos confidenciales del usuario se cifran con su propia contraseña, de modo que el descifrado de los datos no se puede realizar con nada almacenado en la base de datos (potencialmente comprometida). He implementado algunas funciones de seguridad actualmente:

  1. Como se describió anteriormente, los datos confidenciales se cifran utilizando AES utilizando la contraseña hash SHA-512 del usuario (la contraseña se proporciona con cada solicitud como datos del formulario), más un poco de sal.
  2. Se requiere HTTPS y solo se permiten las solicitudes POST.
  3. Las cuentas de usuario se identifican mediante direcciones de correo electrónico (recortadas y en minúsculas en el almacenamiento) y requieren verificación antes de su uso.
  4. Se requiere que las contraseñas de los usuarios tengan un mínimo de 8 caracteres.
  5. Finalmente, se requerirá un token de API para el uso de aplicaciones de terceros a través del encabezado de Autorización. Las aplicaciones de terceros están restringidas porque no pueden crear, verificar ni eliminar cuentas.

Mi pregunta es, ¿es esto suficiente? Apenas soy un experto en seguridad y lo último que quiero hacer es diseñar algo con una supervisión importante. Mi principal preocupación es que la contraseña del usuario se proporciona con cada solicitud, aunque solo sea a través de SSL.

Editar:

Para aclarar, los usuarios podrán cambiar sus contraseñas siempre que aún tengan la actual. Se realiza una solicitud que contiene la dirección de correo electrónico del usuario, la contraseña actual y la nueva contraseña. La solicitud se autentica como lo hace normalmente, utilizando la dirección de correo electrónico y la contraseña actual. La validación se realiza en la nueva contraseña (también se aplica el mínimo de 8 caracteres) antes de continuar.

Primero, tal como se hace cuando el usuario desea recuperar su información confidencial, la información se descifra con su contraseña actual. En su estado de descifrado, la información se encripta con la nueva contraseña y los datos confidenciales se sobrescriben en la base de datos.

En este punto, no hay un registro almacenado de la contraseña anterior y ya no se puede utilizar. Un administrador no puede realizar un cambio de contraseña o, en cualquier caso, sin la contraseña que se utilizó para cifrar la información anteriormente. Si se pierde la contraseña, no se puede hacer nada.

    
pregunta William Thomas 17.10.2013 - 00:47
fuente

2 respuestas

1

Tu idea no es irrazonable. Encriptar los datos de un usuario mediante una clave que solo se puede generar cuando el usuario está presente es una táctica razonable y, de hecho, se utiliza en varios entornos de alta seguridad. Esto puede proporcionar una seguridad significativa si se hace bien. Pero introduciría las siguientes advertencias y modificaciones:

  • Se debe evitar la autenticación sin estado. Es categóricamente peor que la autenticación de sesión limitada. Si siempre Hay varias razones, pero una de ellas es que si las contraseñas se envían con cada solicitud, las contraseñas se guardan en en alguna parte . Lo ideal es que el usuario inicie sesión, lo que "desbloquea" el almacén de datos y le da una clave de sesión de tiempo limitado que se puede usar para acceder al almacén de datos "desbloqueado" solo por un tiempo limitado. Esto le permite expirar las sesiones de autenticación y ayuda a prevenir una serie de posibles ataques. Tenga en cuenta que esto requiere un cambio de diseño sutil que detallaré a continuación.

  • Si los datos del cliente pueden cifrarse en el lado del cliente, entonces haga eso. Si todo lo que ve de los datos del usuario es un blob de bits cifrados, en ningún momento su servidor podría poner en riesgo esos datos.

  • Debería considerar el uso de una cadena de cifrado de dos pasos. En lugar de cifrar los datos del usuario con la clave derivada de la contraseña, debe cifrar los datos valiosos con una clave totalmente aleatoria, y luego cifrar esa clave totalmente aleatoria con la clave derivada de la contraseña del usuario. Esto le permite (a) cambiar fácilmente las contraseñas de usuario, (b) introducir esquemas de autenticación más complejos (por ejemplo, dos factores) y (c) elimina el requisito de enviar la contraseña con cada solicitud. Simplemente vuelva a cifrar la clave del almacén de datos utilizando una clave temporal que deriva de un token de sesión aleatorio que le da al usuario al iniciar sesión. También debe vincular la hora actual, la IP del usuario y cualquier otra información específica de la sesión que desee utilizar para evitar el robo de sesiones.

  • Use una fórmula de derivación de clave razonable. Una sola pasada de cualquier función de hash no es suficiente para evitar que un atacante pueda forzar bruscamente su clave de cifrado si obtiene los datos cifrados. En su lugar, use una función como PBKDF2 o scrypt con un número razonable de rondas. Esto aumenta dramáticamente la cantidad de trabajo que un atacante tendría que hacer para adivinar la contraseña de un usuario.

respondido por el tylerl 21.10.2013 - 10:26
fuente
2

Antes de reinventar la rueda y crear su propio administrador de sesión, lea el Cheatsheet de administración de sesión OWASP , que ayudará evitas errores comunes.

El problema es que el token de autenticación propuesto sha512(password) utilizado para mantener el estado autenticado, es de hecho un token de sesión muy comprensible por varias razones:

  1. El peor problema es que este ID de sesión propuesto tiene una muy pequeña espacio clave. Es mucho más fácil para un atacante adivinar sha512(password) que adivinar 16 bytes de /dev/urandom .
  2. ¡Cifrado! = Autenticación. Múltiples teclas pueden actuar sobre texto cifrado     para obtener algún resultado, solo la clave correcta producirá el     texto plano real Usted todavía tiene que verificar que ha recibido     la clave exacta y AES-CBC no harán eso. La exactitud de esta clave podría ser verificada con un     Función hash, un CMAC o HMAC. AES en un modo de operación autenticado funcionaría.
  3. CWE-613 indica que los identificadores de sesión o "tokens" deben caducar. Por usando el hash de contraseña, en efecto, se ha creado una nueva contraseña que es sha512(password) que no caduca y puede utilizarse para autenticarse sin conocer la contraseña de texto sin formato. Una vez que este valor está comprometido, un atacante puede acceder a la cuenta.
  4. SHA512 es una mala función de derivación de clave (KDF) y una mala manera de almacenar Contraseñas en general ( CWE-916 ). bcrypt, pbkdf2, scrypt son todas buenas opciones.
  5. Si está siendo RESTful, entonces use el VERBO apropiado ! Utilizando POST para todo es confuso. La aplicación de POST no hace que el sistema sea más seguro, estas solicitudes son tan vulnerables como GET para ataques como CSRF u otros ataques.
respondido por el rook 17.10.2013 - 18:25
fuente

Lea otras preguntas en las etiquetas