una partir para palabra online masivo lista generador ejemplos contraseñas claves security encryption passwords security-by-obscurity

security - partir - Encriptación/hash de contraseñas de texto sin formato en la base de datos



generador de contraseñas wifi (16)

Heredé una aplicación web que acabo de descubrir almacena más de 300,000 nombres de usuario / contraseñas en texto plano en una base de datos de SQL Server. Me doy cuenta de que esto es una cosa muy mala ™.

Sabiendo que tendré que actualizar los procesos de inicio de sesión y contraseña para cifrar / descifrar, y con el menor impacto en el resto del sistema, ¿cuál recomendaría como la mejor manera de eliminar las contraseñas de texto sin formato de la base de datos?

Cualquier ayuda es apreciada.

Editar: Disculpe si no estaba claro, quise preguntar cuál sería su procedimiento para encriptar / cifrar las contraseñas, no métodos específicos de cifrado / hash.

Debería solo:

  1. Haga una copia de seguridad de la base de datos
  2. Actualizar el código de inicio de sesión / actualización de contraseña
  3. Después de horas, revise todos los registros en la tabla de usuarios, ingrese la contraseña y reemplace cada uno
  4. Prueba para garantizar que los usuarios aún puedan iniciar sesión / actualizar contraseñas

Supongo que mi preocupación es más por la gran cantidad de usuarios, así que quiero asegurarme de estar haciendo esto correctamente.


Como con todas las decisiones de seguridad, hay compensaciones. Si hashe la contraseña, que es probablemente tu movimiento más fácil, no puedes ofrecer una función de recuperación de contraseña que devuelva la contraseña original, ni tu personal puede buscar la contraseña de una persona para acceder a su cuenta.

Puede usar el cifrado simétrico, que tiene sus propios inconvenientes de seguridad. (Si su servidor está en peligro, la clave de encriptación simétrica también puede verse comprometida).

Puede utilizar el cifrado de clave pública y ejecutar la recuperación de contraseña / servicio al cliente en una máquina separada que almacena la clave privada aislada de la aplicación web. Este es el más seguro, pero requiere una arquitectura de dos máquinas, y probablemente un firewall en el medio.


Como mencionaron los otros, no desea descifrar si puede evitarlo. La mejor práctica estándar es encriptar usando un hash de una vía, y luego cuando el usuario inicia sesión en hash su contraseña para compararla.

De lo contrario, tendrá que usar una encriptación fuerte para encriptar y luego descifrar. Solo recomendaría esto si los motivos políticos son fuertes (por ejemplo, los usuarios están acostumbrados a llamar al servicio de ayuda para recuperar su contraseña, y usted tiene una fuerte presión de la parte superior para no cambiar eso). En ese caso, comenzaría con encriptación y luego comenzaría a construir un caso de negocios para pasar a hash.


Creo que deberías hacer lo siguiente:

  1. Crea una nueva columna llamada HASHED_PASSWORD o algo similar.
  2. Modifique su código para que compruebe ambas columnas.
  3. Gradualmente migre las contraseñas de la tabla sin hash al hash. Por ejemplo, cuando un usuario inicia sesión, migre su contraseña automáticamente a la columna hash y elimine la versión no actualizada. Todos los usuarios recién registrados tendrán contraseñas hash.
  4. Después de horas, puede ejecutar un script que migra n usuarios a un tiempo
  5. Cuando ya no le quedan más contraseñas sin contraseña, puede eliminar su columna de contraseña anterior (es posible que no pueda hacerlo, depende de la base de datos que esté utilizando). Además, puede eliminar el código para manejar las contraseñas antiguas.
  6. ¡Terminaste!

EDITAR (2016): use Argon2 , scrypt , bcrypt o PBKDF2 , en ese orden de preferencia. Use un factor de desaceleración tan grande como sea posible para su situación. Use una implementación existente verificada. Asegúrese de utilizar una sal adecuada (aunque las bibliotecas que está utilizando deben asegurarse de esto).

Cuando use las contraseñas, use NO USAR PLAIN MD5 .

Use PBKDF2 , que básicamente significa usar una sal aleatoria para evitar ataques de tabla de arco iris e iterar (volver a realizar hash) suficientes veces para desacelerar la reducción: no tanto que la aplicación tarde demasiado, sino que un atacante intente forzar Se notará una gran cantidad de contraseñas diferentes

Del documento:

  • Itere al menos 1000 veces, preferiblemente más, tiempo de implementación para ver cuántas iteraciones son factibles para usted.
  • 8 bytes (64 bits) de sal son suficientes, y el azar no necesita ser seguro (la sal no está encriptada, no estamos preocupados de que alguien lo adivine).
  • Una buena forma de aplicar la sal cuando hashing es usar HMAC con su algoritmo hash favorito, usando la contraseña como la clave HMAC y el salt como el texto para hash (consulte esta sección del documento).

Ejemplo de implementación en Python, usando SHA-256 como el hash seguro:

EDITAR : como lo menciona Eli Collins, esta no es una implementación de PBKDF2. Debería preferir implementaciones que se PassLib al estándar, como PassLib .

from hashlib import sha256 from hmac import HMAC import random def random_bytes(num_bytes): return "".join(chr(random.randrange(256)) for i in xrange(num_bytes)) def pbkdf_sha256(password, salt, iterations): result = password for i in xrange(iterations): result = HMAC(result, salt, sha256).digest() # use HMAC to apply the salt return result NUM_ITERATIONS = 5000 def hash_password(plain_password): salt = random_bytes(8) # 64 bits hashed_password = pbkdf_sha256(plain_password, salt, NUM_ITERATIONS) # return the salt and hashed password, encoded in base64 and split with "," return salt.encode("base64").strip() + "," + hashed_password.encode("base64").strip() def check_password(saved_password_entry, plain_password): salt, hashed_password = saved_password_entry.split(",") salt = salt.decode("base64") hashed_password = hashed_password.decode("base64") return hashed_password == pbkdf_sha256(plain_password, salt, NUM_ITERATIONS) password_entry = hash_password("mysecret") print password_entry # will print, for example: 8Y1ZO8Y1pi4=,r7Acg5iRiZ/x4QwFLhPMjASESxesoIcdJRSDkqWYfaA= check_password(password_entry, "mysecret") # returns True


Ese fue un problema mío hace un par de semanas. Estábamos implementando un gran proyecto de MIS en 975 ubicaciones geográficas diferentes donde nuestra propia tienda de credenciales de usuario se utilizará como un autenticador para diferentes conjuntos de aplicaciones ya implementadas y en uso. Ya proporcionamos servicios de autenticación basados ​​en REST y SOAP, pero el cliente insistió en poder llegar a la tienda de credenciales del usuario desde otras aplicaciones con solo una conexión de base de datos a la vista de solo lectura de la tabla o vista relacionada. Suspiro ... (esta mala decisión de diseño altamente acoplada es un tema de otra pregunta).

Eso nos obligó a sentarnos y convertir nuestro esquema de almacenamiento de contraseñas salado e iterativamente hash a una especificación y proporcionar algunas implementaciones de lenguaje diferente para una fácil integración.

En resumen, lo FSHP Contraseñas hash bastante seguras o FSHP . Implementado en Python, Ruby, PHP5 y lanzado a dominio público. Disponible para ser consumido, bifurcado, flameado o escupido en GitHub en FSHP

FSHP es una implementación de hashing de contraseñas sateada e iterativa.

El principio de diseño es similar con la especificación PBKDF1 en RFC 2898 (también conocido como PKCS # 5: Especificación de criptografía basada en contraseña versión 2.0). FSHP permite elegir la longitud de sal, el número de iteraciones y la función de cifrado subyacente entre SHA-1 y SHA-2 (256, 384, 512). El prefijo de metadefinición al comienzo de cada salida lo hace portátil y le permite al consumidor elegir su propia línea base de seguridad de almacenamiento de contraseñas.

SEGURIDAD :

El FSHP1 predeterminado usa sales de 8 bytes, con 4096 iteraciones de hash SHA-256. - La sal de 8 bytes hace que los ataques de tabla arcoíris no sean prácticos al multiplicar el espacio requerido por 2 ^ 64. - 4096 iteraciones hace que los ataques de fuerza bruta sean bastante caros. - No hay ataques conocidos contra SHA-256 para encontrar colisiones con un esfuerzo computacional de menos de 2 ^ 128 operaciones en el momento de este lanzamiento.

IMPLEMENTACIONES:

  • Python: probado con 2.3.5 (con hashlib), 2.5.1, 2.6.1
  • Ruby: Probado con 1.8.6
  • PHP5: probado con 5.2.6

Todos son más que bienvenidos para crear implementaciones de idiomas faltantes o pulir las implementaciones actuales.

OPERACIÓN BÁSICA (con Python) :

>>> fsh = fshp.crypt(''OrpheanBeholderScryDoubt'') >>> print fsh {FSHP1|8|4096}GVSUFDAjdh0vBosn1GUhzGLHP7BmkbCZVH/3TQqGIjADXpc+6NCg3g== >>> fshp.validate(''OrpheanBeholderScryDoubt'', fsh) True

PERSONALIZAR LA CRIPTA:

Vamos a debilitar nuestro esquema de hashing de contraseñas. - Disminuya la longitud de la sal del valor predeterminado de 8 a 2. - Reduzca la ronda de iteración de los valores predeterminados 4096 a 10. - Seleccione FSHP0 con SHA-1 como el algoritmo hash subyacente.

>>> fsh = fshp.crypt(''ExecuteOrder66'', saltlen=2, rounds=10, variant=0) >>> print fsh {FSHP0|2|10}Nge7yRT/vueEGVFPIxcDjiaHQGFQaQ==


La estrategia básica es utilizar una función de derivación de clave para "codificar" la contraseña con un poco de sal. El resultado de sal y hash se almacena en la base de datos. Cuando un usuario ingresa una contraseña, la sal y su entrada se procesan de la misma manera y se comparan con el valor almacenado. Si coinciden, el usuario está autenticado.

El diablo está en los detalles. Primero, mucho depende del algoritmo hash que se elija. Un algoritmo de derivación clave como PBKDF2, basado en un código de autenticación de mensaje basado en hash, lo convierte en "computacionalmente inviable" para encontrar una entrada (en este caso, una contraseña) que producirá un resultado determinado (lo que un atacante ha encontrado en la base de datos )

Un ataque de diccionario precalculado usa un índice precomputado, o diccionario, desde salidas de hash a contraseñas. El hash es lento (o se supone que es así, de todos modos), por lo que el atacante calcula una vez todas las contraseñas probables y almacena el resultado indexado de forma tal que, con un hash, puede buscar una contraseña correspondiente. Esta es una clásica compensación de espacio por tiempo. Dado que las listas de contraseñas pueden ser enormes, hay formas de ajustar el intercambio (como las tablas de arcoiris), de modo que un atacante puede ceder un poco de velocidad para ahorrar mucho espacio.

Los ataques previos al cómputo se frustran mediante el uso de "sal criptográfica". Estos son algunos datos que se hastean con la contraseña. No necesita ser un secreto, solo necesita ser impredecible para una contraseña dada. Para cada valor de sal, un atacante necesitaría un nuevo diccionario. Si usa un byte de sal, un atacante necesita 256 copias de su diccionario, cada una generada con una sal diferente. Primero, usaría la sal para buscar el diccionario correcto, luego usaría la salida hash para buscar una contraseña utilizable. Pero, ¿y si agregas 4 bytes? Ahora necesita 4 mil millones de copias del diccionario. Al usar una sal lo suficientemente grande, se impide un ataque de diccionario. En la práctica, de 8 a 16 bytes de datos de un generador de números aleatorios de calidad criptográfica es una buena sal.

Con la computación previa fuera de la mesa, un atacante ha calculado el hash en cada intento. El tiempo que se tarda en encontrar una contraseña ahora depende completamente de cuánto demore el hash de un candidato. Este tiempo se incrementa mediante la iteración de la función hash. El número de iteraciones es generalmente un parámetro de la función de derivación de clave; hoy en día, muchos dispositivos móviles usan de 10,000 a 20,000 iteraciones, mientras que un servidor puede usar 100,000 o más. (El algoritmo bcrypt usa el término "factor de costo", que es una medida logarítmica del tiempo requerido).


MD5 y SHA1 han mostrado un poco de debilidad (dos palabras pueden dar como resultado el mismo hash) por lo que se recomienda usar SHA256-SHA512 / hashes iterativos para cifrar la contraseña.

Escribiría un pequeño programa en el idioma en el que está escrita la aplicación y generará un sal aleatorio único para cada usuario y un hash de la contraseña. La razón por la que tiendo a usar el mismo lenguaje que la verificación es que las diferentes bibliotecas de cifrado pueden hacer las cosas de forma ligeramente diferente (es decir, relleno), por lo que usan la misma biblioteca para generar el hash y verificar que elimine ese riesgo. Esta aplicación también podría verificar el inicio de sesión después de que la tabla se haya actualizado si lo desea, ya que todavía conoce la contraseña de texto sin formato.

  1. No use MD5 / SHA1
  2. Genera una buena sal aleatoria (muchas bibliotecas de cifrado tienen un generador de sal)
  3. Un algoritmo hash iterativo como Orip recomendado
  4. Asegúrese de que las contraseñas no se transmitan en texto sin formato a través del cable

Me gustaría sugerir una mejora para el gran ejemplo de pitón publicado por Orip . Yo redefiniría la función random_bytes para que sea:

def random_bytes(num_bytes): return os.urandom(num_bytes)

Por supuesto, tendría que importar el módulo de os . La función os.urandom proporciona una secuencia aleatoria de bytes que se puede usar de forma segura en aplicaciones criptográficas. Consulte la ayuda de referencia de esta función para obtener más detalles.


Me imagino que tendrá que agregar una columna a la base de datos para la contraseña cifrada y luego ejecutar un trabajo por lotes en todos los registros que obtiene la contraseña actual, la encripta (como otros mencionaron un hash como md5 es una edición bastante estándar, pero no debería ser utilizado solo - ver otras respuestas para buenas discusiones ), lo almacena en la nueva columna y verifica que todo sucedió sin problemas.

Luego, deberá actualizar su interfaz para cifrar la contraseña ingresada por el usuario en el momento del inicio de sesión y verificarla en comparación con el hash almacenado, en lugar de verificar el texto sin formato versus el texto sin formato.

Me parece prudente dejar las dos columnas en su lugar por un tiempo para asegurar que no haya pasado nada, antes de eliminar todas las contraseñas de texto plano.

No olvide también que cada vez que se ingrese la contraseña, el código tendrá que cambiar, como las solicitudes de cambio de contraseña / recordatorio. Por supuesto, perderá la capacidad de enviar por correo electrónico contraseñas olvidadas, pero esto no es malo. En su lugar, tendrá que usar un sistema de restablecimiento de contraseña.

Editar: Un último punto, es posible que desee considerar evitar el error que cometí en mi primer intento en un sitio web de inicio de sesión seguro:

Al procesar la contraseña del usuario, considere dónde se realiza el hash. En mi caso, el hash fue calculado por el código PHP que se ejecuta en el servidor web, ¡pero la contraseña fue transmitida a la página desde la máquina del usuario en texto plano! Esto estaba bien (ish) en el entorno en el que estaba trabajando, ya que estaba dentro de un sistema https de todos modos (red uni). Pero, en el mundo real, me imagino que querría cifrar la contraseña antes de que abandone el sistema del usuario, usar javascript, etc. y luego transmitir el hash a su sitio.


No soy un experto en seguridad, pero creo que la recomendación actual es usar bcrypt / blowfish o una variante SHA-2, no MD5 / SHA1.

Probablemente también deba pensar en términos de una auditoría de seguridad completa


Para cifrar la contraseña, puede usar la función HashBytes . Devuelve un varbinary, por lo que tendría que crear una nueva columna y luego eliminar el varchar uno anterior.

Me gusta

ALTER TABLE users ADD COLUMN hashedPassword varbinary(max); ALTER TABLE users ADD COLUMN salt char(10); --Generate random salts and update the column, after that UPDATE users SET hashedPassword = HashBytes(''SHA1'',salt + ''|'' + password);

Luego modifica el código para validar la contraseña, usando una consulta como

SELECT count(*) from users WHERE hashedPassword = HashBytes(''SHA1'',salt + ''|'' + <password>)

donde <contraseña> es el valor ingresado por el usuario.


Para fines de autenticación, debe evitar almacenar las contraseñas usando cifrado reversible, es decir, solo debe almacenar el hash de la contraseña y verificar el hash de la contraseña proporcionada por el usuario contra el hash que ha almacenado. Sin embargo, ese enfoque tiene un inconveniente: es vulnerable a los ataques de tabla arcoiris , en caso de que un atacante obtenga la base de datos de la tienda de contraseñas.

Lo que debe hacer es almacenar los hashes de un valor de sal pre-elegido (y secreto) + la contraseña. Es decir, concatenar la sal y la contraseña, cortar el resultado y almacenar este hash. Al autenticarse, haga lo mismo: concatene su valor de sal y la contraseña proporcionada por el usuario, hash, luego verifique la igualdad. Esto hace que los ataques de tabla de arco iris sean inviables.

Por supuesto, si el usuario envía contraseñas a través de la red (por ejemplo, si está trabajando en una aplicación web o cliente-servidor), no debe enviar la contraseña en texto claro, de modo que en lugar de almacenar hash (salt + contraseña) debe almacenar y verificar contra hash (salt + hash (contraseña)), y hacer que su cliente haga un pre-hash de la contraseña proporcionada por el usuario y la envíe a través de la red. Esto también protege la contraseña de su usuario, en caso de que el usuario (como muchos) reutilice la misma contraseña para múltiples propósitos.


Paso 1: agrega un campo encriptado a la base de datos

Paso 2: cambie el código para que cuando se cambie la contraseña, actualice ambos campos, pero el inicio de sesión aún utiliza el campo anterior.

Paso 3: ejecutar el script para completar todos los campos nuevos.

Paso 4: cambie el código para que el inicio de sesión use un nuevo campo y cambie las contraseñas para dejar de actualizar el campo anterior.

Paso 5: elimine las contraseñas no cifradas de la base de datos.

Esto debería permitirle realizar el cambio sin interrupción para el usuario final.

Además: Algo que haría sería nombrar el campo de la nueva base de datos como algo que no está relacionado con ninguna contraseña como "LastSessionID" o algo similar aburrido. Luego, en lugar de eliminar el campo de contraseña, rellene con hash de datos aleatorios. Luego, si su base de datos alguna vez se ve comprometida, pueden pasar todo el tiempo que quieran tratando de descifrar el campo "contraseña".

En realidad, esto no puede lograr nada, pero es divertido pensar en alguien sentado allí intentando descifrar información sin valor.



hash ellos con md5. eso es lo que generalmente se hace con contraseñas.


  • Cifre usando algo como MD5, codifíquelo como una cadena hexagonal
  • Necesitas una sal; en su caso, el nombre de usuario puede usarse como sal (tiene que ser único, el nombre de usuario debe ser el valor más exclusivo disponible ;-)
  • utilice el campo de contraseña anterior para almacenar el MD5, pero etiquete el MD5 (ieg "MD5: 687A878 ...") para que las contraseñas antiguas (texto sin formato) y nuevas (MD5) puedan coexistir
  • cambie el procedimiento de inicio de sesión para verificar contra el MD5 si hay un MD5, y contra la contraseña simple de lo contrario
  • cambie las funciones "cambiar contraseña" y "nuevo usuario" para crear solo contraseñas con MD5
  • ahora puede ejecutar el trabajo por lotes de conversión, lo que puede llevar tanto tiempo como sea necesario
  • una vez que se haya ejecutado la conversión, elimine el soporte heredado