2011-08-30 11 views
7

Objetivo:¿Protege PII en la base de datos de aplicaciones web al cifrar con clave pública emparejada con clave privada protegida por las propias contraseñas de los usuarios?

me gustaría para permitir a los usuarios crear preguntas y recoger información de otros usuarios en una aplicación web personalizada (PHP/MySQL en un entorno de alojamiento apuntalado) y protegen los datos recogidos.

Antecedentes:

Las preguntas predeterminadas que todos los usuarios deberán responder son lo suficientemente que no pueden ser interpretados como información de identificación personal (PII) en general, lo que limita mi responsabilidad para protegerlo, pero los usuarios que crear su propia es probable que las preguntas soliciten PII, que luego se convierte en una responsabilidad.

Lo que me gustaría hacer es proteger esta información de manera que si la cuenta de hosting o la base de datos se veían comprometidas (¡o ambas cosas!), La PII no sería recuperable sin una cantidad significativa de trabajo, e incluso entonces, solo una pequeña porción sería teóricamente recuperable.

solución propuesta:

Asumiendo de MySQL incorporada AES_ENCRYPT()/AES_DECRYPT() funciones se utilizan para cifrar la tabla de información de identificación personal, tendría que ser almacenada en la cuenta de alojamiento, por lo que si la cuenta de alojamiento se comprometió la frase de contraseña, los datos podría leerse fácilmente

Como las contraseñas de los usuarios están bien protegidas (mezcladas con sal), estoy pensando en capturar su contraseña de texto plano durante la autenticación, encriptarla y almacenarla en la sesión de PHP hasta que el usuario cierre la sesión.

Se creará un combo de clave pública/privada para cada usuario con la clave privada protegida por contraseña con la contraseña + contraseña del usuario.

Luego, cuando los datos PII basados ​​en las preguntas personalizadas de ese usuario se agregan a la base de datos, la clave pública del usuario se usaría para encriptar la PII que recopilaron a través de la aplicación. Cuando se leen los datos (solo cuando el usuario está conectado), los datos se descifrarán con la clave privada del usuario (que se desbloquea con su contraseña + sal).

Los beneficios que veo son:

  1. en el peor de los casos, donde los servidores completamente comprometidos, código de aplicación se lee para encontrar las claves de cifrado, los archivos de sesión de PHP se descifran para encontrar las contraseñas de usuario, entonces entradas en la tabla de PII asociada con ese usuario se descifran, entonces solo se pudo recuperar la información de identificación personal recopilada de las preguntas de los usuarios que actualmente están conectados. Cualquier usuario que no haya iniciado sesión estaría seguro.
  2. incluso el DBA o similar no podría leer la PII.

Los inconvenientes veo son:.

  1. las contraseñas de usuario se almacenan en una forma recuperable mientras están conectados en
  2. usuarios que olvidan sus contraseñas podrían perder el acceso a sus datos.
  3. cada bit relativamente pequeño de datos ocupará mucho más espacio en la base de datos debido a la encriptación.

Mi pregunta es: ¿Existe alguna otra forma de hacerlo?

+0

Es casi imposible garantizar la protección tan pronto como el servidor se vea comprometido. Tan pronto como alguien tiene acceso al código php, puede modificar fácilmente el código para escribir todas las contraseñas (o pares de claves) en un archivo de texto sin formato al iniciar sesión. Tan pronto como se conoce la sal (o se sabe cómo se construye), el hash no se guarda para protección. – Fge

+0

Sí, mientras no se descubra la violación, se podrían capturar las contraseñas. La idea es contención y fuga minimizada. Al menos algunos datos aún estarían protegidos porque, con suerte, la brecha se descubriría con bastante rapidez y no todos los usuarios iniciarían sesión dentro de ese marco de tiempo. –

+0

¿Qué es exactamente lo que quiere almacenar en la sesión de PHP? No veo por qué necesita una clave de cifrado adicional en la memoria si solo descifra la clave privada al iniciar sesión. –

Respuesta

6

Veo un número de problemas con este diseño desde una perspectiva de seguridad. En primer lugar, las contraseñas nunca deben cifrarse, esta es una vulnerabilidad identificada por CWE-257.

Más aún AES_ENCRYPT() de MySQL es basura completa por más de un motivo. Utiliza el modo EBC, y aquí es un buen ejemplo de por qué esto es una porquería:

imagen original:

enter image description here

modo EBC (que es AES_ENCRYPT() utiliza lo que MySQL):

enter image description here

Pero si la base de datos comprometió al atacante va a derrotar AES_ENCRYPT() habilitando el query log.

Se debe evitar el uso de la contraseña del usuario para el cifrado, debe utilizar una fuente criptográfica. Si usa una contraseña, asegúrese de utilizar un funciton String2Key. También debe usar el modo CBC o CMAC con un random iv. Realmente no veo cómo la criptografía asimétrica puede ayudar. La criptografía asimétrica es muy lenta, con memoria intensiva. Los datos que protege se vuelven menos seguros cuando el atacante controla el mensaje porque puede comparar los mensajes de texto de cifrado. Es por esto que un IV aleatorio is important, y en el mundo asimétrico no tiene este nivel de protección.

generación de claves debe ser algo como: $key=string2key($base_nonce.$salt.$user_password)

Asegúrese de que la salida de su función string2key es del mismo tamaño que el espacio de claves. Entonces aes 128 necesita una clave de 128 bits. Cada contraseña debe tener su propia $salt, y $base es una fuente criptográfica almacenada en archivo de texto. (Un atacante tendría que leer este archivo antes de que pueda descifrar la clave; si este valor es grande, como 128 bits, entonces es un punto discutible). Cada mensaje necesita su propio $iv y este valor también debe ser un código criptográfico (similar a un sal). Yo generaría el $salt, $iv y $base_nonce de /dev/urandom. El IV se puede almacenar en texto sin formato en una columna en su base de datos junto con el texto de cifrado.

Desde el punto de vista legal, incluso si construye un sistema criptográfico seguro, aún tiene problemas con las amenazas internas y si el servidor está completamente comprometido, todos los datos seguirán estando en peligro. Esto realmente no es un problema de ingeniería.

La mejor defensa contra una amenaza legal es unos Términos y condiciones fuertes escritos por un abogado experto.

+0

+1 para esta demostración agradable de las debilidades de EBC y el asesoramiento con respecto a las amenazas legales. Sin embargo, estoy bastante seguro de que OP no quiere usar 'AES_ENCRYPT' y su contraparte, porque afirma en su publicación que" si la cuenta de alojamiento se viera comprometida, los datos podrían leerse fácilmente ", lo cual quiere evitar al usar un esquema de cifrado/descifrado asimétrico. –

+0

@Niklas, sí, quiere usar una criptografía asimétrica que, por todas las cuentas, es una idea peor. – rook

0

Una preocupación que tengo es la siguiente. La parte "cualquier usuario que no haya iniciado sesión sería seguro" es demasiado optimista. Al proteger la clave privada con la contraseña del usuario, se abre a varios ataques de contraseña de fuerza bruta. No solo para las sesiones actuales, sino para todas. Uno efectivo es simplemente enumerar las 100 contraseñas comunes más importantes, por ejemplo, y simplemente probarlas contra todos los usuarios. El atacante está obligado a descubrir algunas claves. (Supongo que está almacenando sal aleatoria por usuario con el registro de usuario, que el atacante puede ver, o bien que tiene una sal secreta que el atacante pudo obtener a través del compromiso.)

+0

Mejores formas de evitar el descifrado de contraseñas son algoritmos hash iterados (un ataque de fuerza bruta no será viable si solo puedes verificar 10 contraseñas/segundo) y especialmente forzar una política estricta de contraseñas a tus usuarios (longitud mínima, necesita caracteres especiales/números/superior/minúscula). No subestime el poder de los crackers GPU modernos, que pueden verificar fácilmente cientos de millones de contraseñas con hash débil por segundo (y esta es solo una única tarjeta gráfica). –

+0

Sí, la estricta política de contraseñas es de gran ayuda. Sin eso, incluso las 10 contraseñas/segundo probablemente sean lo suficientemente rápidas como para descubrir contraseñas de alta frecuencia. Hace años yo era el administrador de sistemas de un sistema donde todas las contraseñas se almacenaban como texto sin formato, y definitivamente vi varias contraseñas que seguían apareciendo (se sabía que los usuarios eran únicos): "contraseña", "p @ ssword", "naranja" , "ilove [algún_nombre]", "f * ckyou" y variantes, "flor", 1337 versiones de palabras comunes, etc. Sin embargo, el estiramiento de la tecla también ayuda. –

Cuestiones relacionadas