¿Definitivamente el esquema de almacenamiento de contraseñas más seguro?

3

Ya pregunté esto en StackOverflow pero me sugirieron que este sería un lugar más adecuado y no encontré la forma de "mover" la pregunta, así que tengo que copiarla.

Créeme, lo sé, hay cientos de preguntas sobre este tema. Leí muchos de ellos para encontrar la manera MÁS SEGURA de almacenar una contraseña, pero cada respuesta dada me da la sensación de que todavía podemos hacerlo mucho mejor. Y estoy planeando usar esto en PHP pero creo que se aplica a cualquier lenguaje de codificación.

No soy un experto en seguridad pero ¿no es solo un método no lo suficientemente seguro?

ENCRYPT

Si entendí correctamente La contraseña cifrada (con PHP) se puede descifrar a texto simple si conoce la cadena que se usó. La mayoría de las cuentas de alojamiento que he visto hackeado primero obtienen acceso a los archivos y luego buscan la contraseña de DB almacenada en config.php o algo así.

Incluso si utilizo una cadena grande y complicada para cifrar la contraseña, si el intruso va a create_account.php (o donde sea que se cree el usuario), encontrará la cadena allí y podrá descifrar la contraseña completa. Columna en unos minutos (¿verdad?)

HASHING

Lo bueno de hashing es que la contraseña no se puede devolver a texto sin formato, lo cual es genial pero ... Muchos métodos de hashing tienen vulnerabilidades y he estado leyendo algunos artículos que obtienen valores posibles para un hashing (un cadena de hash puede significar más de una cadena de texto sin formato). Leí un artículo que decía que algunas personas podían recuperar la contraseña del hash usando Amazon EC2 en segundos para contraseñas débiles y horas para contraseñas fuertes.

Incluso vi directorios de índice de hash donde los hackers y j * rks aleatorios almacenan grandes cantidades de valores de cadena de hash > por lo tanto, si ingresas el hash que obtuviste, puedes obtener una posible contraseña en solo un segundo. Esto sigue siendo una especie de ataque de diccionario, pero bastante efectivo.

Para el hash común como MD5, incluso vi un artículo en el que un pirata informático descubrió fácilmente que Google indiza de alguna manera los hashes MD5 debido a su uso (como en los nombres de archivo, gravatar.com y API similares, etc.), por lo que tuvo una Diccionario de HUUUGE indexado de hash que solo toma un segundo para asociarse a los valores.

Una vez se creyó que MD5 y SHA1 eran seguros, pero luego aparecieron las vulnerabilidades. ¿Qué pasa si el método de confianza utilizado ahora (leo el pez globo es el mejor, es correcto?) Obtiene algún tipo de vulnerabilidad en el futuro?

Y por último, sé que esto es ridículo, pero me siento incómodo con la posibilidad de que 2 contraseñas tengan el mismo resultado hash. Sé que las posibilidades de que alguien adivine el otro valor que tiene el mismo hash es muy baja, pero, ¡estamos en 2012! ¿No se suponía que tendríamos coches voladores y computadoras que podrían hacer que la película de Avatar en una hora ya? ? : P Ya debería haber algo mejor ...

SAL

Incluso si uso sal para dificultar la recuperación de la contraseña, si el pirata informático ve la cadena de sal fija (o donde se almacenó la sal aleatoria), la fuerza bruta con la nube no sería mucho más complicada. , ¿lo haría?

¿NO HAY ALGO MEJOR?

Como dije, estoy lejos de ser un experto en seguridad, pero ¿no hay alguna opción por ahí? He leído muchas preguntas sobre esto aquí en Desbordamiento de pila y el resultado de Google (que son la mayoría de las respuestas de desbordamiento de pila: D) y casi siempre dicen lo mismo.

Si el hash y el cifrado son las únicas opciones, ¿es una manera de mejorarlo? ¿Hay alguna forma de ocultar la contraseña de cifrado en el caso de que se acceda al archivo que crea los usuarios?

En todas esas respuestas nunca vi a alguien que sugiriera combinar métodos como:

sha1 (cripta [blowfish.salt], sal) ¿Es esta una mala idea por alguna razón? (Solo puedo pensar en consumir demasiado procesador en un sitio con miles de usuarios que se registran e inician sesión, pero puedo manejarlo en los sitios que planeo usar)

No estoy preguntando "por favor, codifíqueme esto", quiero saber cómo hacerlo "lo más imposible posible" (más difícil: P) para obtener las contraseñas en el caso de que el DB y el Código fuente se encontraran en el manos equivocadas

Tal vez entendí mal la forma en que funcionan estos métodos y quizás hay algo como una función PHP para hacer que una cadena sea indescifrable incluso con la contraseña, o tal vez me perdí algo. Todavía me resulta extraño que nadie haya sugerido una combinación de métodos.

Gracias de antemano y gracias de nuevo si todavía estás leyendo los pensamientos de mi mente preocupada

    
pregunta Juan 22.02.2012 - 08:51
fuente

11 respuestas

7

Puede delegar la autenticación a un servidor diferente dentro de su red, con el que su servidor primario habla a través de un servicio web o cualquier protocolo que desee. De esta manera, un pirata informático puede acceder a su servidor primario y a los archivos que desee y aún así no obtener nada.

El servidor de autenticación se puede bloquear mucho más apretado, minimizando el área de superficie para el ataque, sin mencionar que el ataque tendría que ocurrir a través de su servidor principal.

    
respondido por el Supr 22.02.2012 - 08:36
fuente
7

No cifre las contraseñas: hash (de un solo sentido) hash.

No deberías necesitar o querer descifrar las contraseñas. Si lo haces, no estás realmente preocupado por la seguridad.

La seguridad siempre es una compensación con el rendimiento.

Los algoritmos hash estándar (md5, sha1) son seguros a menos que el atacante conozca la sal.

El uso de un algoritmo de hashing lento hará que las contraseñas sean seguras incluso si un atacante tiene acceso al código y al hash almacenado.

La función de cifrado es probablemente lo que quieres en php. El uso de un alto número de rondas de cifrado hará que el cálculo del hash de una entrada determinada sea lento; eso hará inviable el uso de la fuerza bruta, pero también hará que sea más lento para usted / su aplicación verificar que la contraseña ingresada por el usuario sea la misma que el hash que ha almacenado, esa es la compensación.

Las técnicas de duplicación no van a hacer nada para aumentar la seguridad: el parámetro de redondeo de encriptación en la sal significa que está alimentando la salida del hashing de la cadena de entrada al algoritmo de hashing que muchas veces está proponiendo una medida a medida + 1, solo agregue uno al número de rondas que desea ejecutar. Además, para el ejemplo dado sha1(crypt[blowfish.salt],salt) , esto evitará que pueda comparar correctamente el hash con la entrada del usuario, desde El primer ejemplo :

  

Debes pasar todos los resultados de crypt () como la sal para comparar una contraseña

Sin la salida de crypt, no puedes comparar la entrada del usuario con el hash ya generado.

    
respondido por el AD7six 22.02.2012 - 12:15
fuente
7

¿El esquema de almacenamiento de contraseña más seguro? Un fuerte hash lento (como bcrypt) con varios bytes de sal aleatoria que evita atacar las contraseñas en paralelo con una tabla de arco iris. El cifrado de contraseñas solo debe usarse cuando sea absolutamente necesario: por ejemplo, está grabando una contraseña en un sistema externo no controle eso es demasiado tonto como para usar un protocolo adecuado para otorgar acceso a terceros (como openauth), por lo que debe registrar la contraseña de los usuarios en ese sistema.

  

Y por último, sé que esto es ridículo, pero me siento incómodo con la posibilidad de que 2 contraseñas tengan el mismo resultado hash. Sé que las posibilidades de que alguien adivine el otro valor que tiene el mismo hash es muy baja, pero, ¡estamos en 2012! ¿No se suponía que tendríamos coches voladores y computadoras que podrían hacer que la película de Avatar en una hora ya? ? : P Ya debería haber algo mejor ...

Sí, tu incomodidad es ridícula. Si usa, por ejemplo, SHA256 (256 bits) o bcrypt (184 bits), la posibilidad de obtener dos contraseñas aleatorias que vayan al mismo hash es extraordinariamente improbable (aproximadamente 10 veces 66 menos que ganar el premio mayor de powerball ). Para SHA256, todas las contraseñas deben ser únicas hasta que tenga aproximadamente 2 256/2 ~ 10 38 las contraseñas almacenadas en la tabla y luego aproximadamente la mitad del tiempo serán un conjunto de contraseñas duplicadas. Para obtenerlo de modo que cualquier contraseña dada tenga una segunda cadena que también se asigne al mismo hash, necesitaría aproximadamente 2 256 ~ 10 77 . (Todo esto bajo el supuesto de que las funciones hash tienen una buena uniformidad).

Pongamos estos grandes números en perspectiva. La masa de la tierra es de aproximadamente 6x10 ^ 24 kg. Entonces, si usa en promedio 50 bytes para almacenar cada contraseña en una tabla de arco iris, antes de que haya un duplicado con SHA256, necesitará aproximadamente 10 ^ 30 gigabytes de datos. Si pone esto en términos de todos los discos duros de 3 TB que pesan aproximadamente medio kilo cada uno, sus discos duros pesarán aproximadamente 1000 veces más que la Tierra. O como comparación para tener la posibilidad de que la mayoría de los hashes tengan múltiples cadenas, compare el número de 77 SHA256 necesarios para ser mil millones de veces menos que el número de átomos en la Vía Láctea (aproximadamente 10 < sup> 68 ).

    
respondido por el dr jimbob 22.02.2012 - 20:24
fuente
6

Bien, primero, hay una gran cantidad de preguntas aquí, así que mientras lo hago, probablemente deberías leer primero las preguntas vinculadas al lado y las que tienen y . Muchas de sus preguntas son respondidas allí. De hecho, todos están a excepción de su pregunta específica sobre dónde debe almacenar la clave de cifrado.

Un resumen rápido:

  1. PHP - generalmente considerado como bastante inseguro. Puede ser asegurado a varios niveles, pero la estructura y la expansión funcional que a menudo viene acompañada significa que si su objetivo principal es la seguridad, los riesgos deben ser bien apreciados.
  2. No almacene sus claves de cifrado con datos públicos. En un entorno completamente alojado, esto puede ser difícil de administrar, pero es un riesgo importante.
  3. Sí, las tablas de arco iris le permitirán recuperar contraseñas de hashes en segundos si no usa salting: los hashes deben usar sales y un algoritmo lento . Esto se puede hacer de manera muy segura (es decir, la fuerza bruta tomará un tiempo incómodamente largo, por ejemplo, más largo que la vida del universo)
respondido por el Rory Alsop 22.02.2012 - 10:09
fuente
3

Debería estar codificando sus contraseñas (con HMAC + bcrypt), no encriptándolas. Aquí hay algunas reglas generales que sigo:

  1. Use un algoritmo que proporcione suficientes restricciones de tiempo (es decir, bcrypt). Esto se debe a que, bcrypt le permite personalizar el trabajo requerido para calcular cada hash, lo que ayuda a reducir el número de intentos de fuerza bruta que un atacante puede realizar en un período de tiempo determinado.

  2. Use sales por usuario. Al usar sales por usuario, puede estar seguro de que ningún usuario con la misma contraseña tendrá el mismo hash. También reduce el riesgo asociado con las tablas del arco iris.

  3. Use un sal en todo el sistema, que no esté almacenado en la base de datos. Esto proporciona una capa adicional de seguridad en el caso de un compromiso de base de datos completo donde tanto el hash de contraseña como las sales están comprometidos. . Al usar otra sal que solo se almacena en la memoria, un atacante no podría forzar fácilmente la contraseña de cada usuario.

respondido por el Gerry 22.02.2012 - 18:14
fuente
3

Sí, hay "cientos" de preguntas sobre este tema. Esto me obligó para escribir un artículo en él que espero responda de una vez por todas:

enlace

Esencialmente, el almacenamiento seguro de contraseñas implica:

  • El algoritmo correcto: use bcrypt o PBKDF2 , ambos algoritmos lentos que contienen hash Contraseñas con su propia "sal". El cifrado no es ideal porque el exacto la contraseña puede ser recuperable si la clave es conocida, lo que no es necesariamente El caso del hashing. MD5, SHA-1, etc. por sí mismos tampoco son ideales, porque no son lo suficientemente "lentos".

  • La política de contraseña correcta, como forzar a los usuarios a usar contraseñas largas, y alentando contraseñas seguras.

Por favor agregue comentarios que me ayuden a mejorar ese artículo.

    
respondido por el Peter O. 22.02.2012 - 10:22
fuente
1

En primer lugar, siempre debe seguir el principio de privilegio mínimo . Aunque no es directamente aplicable en este caso, debería significar que a menos que definitivamente necesite la contraseña original (por ejemplo, autenticación remota), no use un esquema que permita recuperar la contraseña original.

Por lo tanto, el cifrado solo se considera si definitivamente necesita obtener la contraseña original. De lo contrario, solo almacena un hash de la contraseña.

En cuanto al esquema de hashing, debe usar uno diseñado específicamente para hashing / almacenar contraseñas (por ejemplo, crypt ). Además de funciones hash criptográficas de propósito general como las de las familias MD o SHA, muchas de ellas agregan un factor de costo de tiempo adicional y ajustable que hace que los ataques de fuerza bruta sean menos eficientes / más difíciles.

Hablando de ataques de fuerza bruta, usa un salt único para cada contraseña hash. Algunos esquemas de contraseñas como crypt ya aplican salting automático . Úsalo y no intentes inventar tu propio sistema.

    
respondido por el Gumbo 22.02.2012 - 12:04
fuente
1

Debería codificar las contraseñas que están almacenadas en la base de datos con un salt. No intentaría escribir mi propia biblioteca de hashing de contraseñas. Uno muy popular que se usa en muchos proyectos PHP (incluido el mío) es phpass de enlace : puede crear hashes con sal utilizando bcrypt , DES o MD5.

Para ayudar a que sus usuarios creen contraseñas más seguras, puede pedirles que creen contraseñas de cierta longitud o complejidad.

    
respondido por el pyasi 22.02.2012 - 16:01
fuente
0

Puedo darte rápidamente la función que utilizo para las contraseñas de hash (la clave está, por supuesto, modificada aquí):

$siteLongKey = '5efd8123878793f88bf1362905ae209794a8602f92969a67862b925fd6e50b04dfd31ae74002cb449824fcaa90e2efd096e8653a3f52e2b048e24b289c705129';

    function hashPassword($password, $nonce = '') {
      global $siteLongKey;    
      return hash_hmac('sha512', $password . $nonce, $siteLongKey);
    }

Esto es bastante bueno, $ siteLongKey es su clave global y $ nonce es la sal que puede agregar. Puede ser la dirección de correo electrónico o la fecha en que se creó la cuenta, o cualquier información estática relacionada con la cuenta. En este caso, cada usuario tiene una sal diferente. Esto es hash de una sola vía y (en teoría) no hay recuperación de contraseña, sino solo restablecimiento de contraseña.

    
respondido por el iceduck 22.02.2012 - 08:39
fuente
-2

La mejor opción para almacenar contraseñas en db es un cifrado de una manera usando un algoritmo de compilación de mensajes que produce un valor de hash de 128 bits y no se puede descifrar. Así que la recuperación de contraseña no es posible. Para autenticar a cualquier usuario, siempre creamos un hash de la contraseña proporcionada y comparamos ambos valores de hash.

Si está utilizando algoritmos personalizados para cifrar y descifrar la contraseña, use ionCube para usar códigos binarios de sus algoritmos. así que incluso si el hacker ingresa el código, no será de ninguna utilidad. Puede consultarlo aquí enlace . Esta es otra mejor manera de protegerse.

    
respondido por el Ishan Verma 22.02.2012 - 08:39
fuente
-2

El mejor algoritmo disponible actualmente es bcrypt. Sin embargo, en noviembre se inventó un mejor algoritmo y se está preparando lentamente una solicitud de patente. El algoritmo puede estar disponible en no menos de 18 meses (período de confidencialidad obligatorio de la OMPI). El uso gratuito estará disponible solo con distribuciones de Linux no comerciales.

    
respondido por el nlovric 22.02.2012 - 17:17
fuente

Lea otras preguntas en las etiquetas