Quiero volver a escribir mis scripts de inicio de sesión para los sitios web de los clientes para que sean más seguros. Quiero saber qué mejores prácticas puedo implementar en esto. Los paneles de control protegidos con contraseña son abundantes, pero muy pocos parecen implicar mejores prácticas en términos de escritura de código, velocidad y seguridad.
Usaré PHP y una base de datos MYSQL.
Solía usar md5, pero veo que sha256 o sha512 serían mejores (junto con hash seguro y sal).
Algunos scripts de inicio de sesión registran la dirección IP durante toda la sesión o incluso el agente de usuario, pero quiero evitarlo ya que no es compatible con servidores proxy.
También estoy un poco por detrás de las mejores prácticas en el uso de sesiones en PHP 5 (la última vez que leí fue PHP 4), por lo que algunas de las mejores prácticas con esto serían útiles.
Gracias.
fuente
Respuestas:
Lo mejor es no reinventar la rueda. Pero, entiendo, en el mundo de PHP puede ser difícil encontrar un componente de alta calidad que ya lo haga (incluso estoy bastante seguro de que los marcos implementan tales cosas y sus implementaciones ya están probadas, sólidas, revisadas por código, etc. )
Si, por alguna razón, no puede usar un marco, aquí hay algunas sugerencias:
Sugerencias relacionadas con la seguridad
Usa PBKDF2 o Bcrypt si puedes . Está hecho para eso.
Justificación: ambos algoritmos pueden hacer que el proceso de hashing sea arbitrariamente lento, que es exactamente lo que desea cuando se usan contraseñas de hashing (las alternativas más rápidas significan una fuerza bruta más fácil). Idealmente, debe ajustar los parámetros para que el proceso se vuelva más y más lento con el tiempo en el mismo hardware, mientras se lanza un hardware nuevo y más rápido.
Si no puede, al menos no use MD5 / SHA1. Nunca. Olvídate de eso . Utilice SHA512 en su lugar, por ejemplo. Usa sal también.
Justificación: MD5 y SHA1 son demasiado rápidos. Si el atacante tiene acceso a su base de datos que contiene los hashes y tiene una máquina (ni siquiera particularmente poderosa), forzar una contraseña con fuerza bruta es rápido y fácil. Si no hay sales, las posibilidades de que el atacante encuentre la contraseña real aumenta (lo que podría causar un daño adicional si la contraseña se reutilizara en otro lugar).
En PHP 5.5.0 y posterior, use
password_hash
ypassword_verify
.Justificación: llamar a una función proporcionada por el marco es fácil, por lo que se reduce el riesgo de cometer un error. Con esas dos funciones, no tiene que pensar en parámetros diferentes como el hash. La primera función devuelve una sola cadena que luego puede almacenarse en la base de datos. La segunda función usa esta cadena para la verificación de contraseña.
Protégete de la fuerza bruta . Si el usuario envía una contraseña incorrecta cuando ya envió otra contraseña incorrecta hace 0.01 segundos, es una buena razón para bloquearla. Si bien los seres humanos pueden escribir rápido, probablemente no puedan ser tan rápidos.
Otra protección sería establecer un límite de fallas por hora. Si el usuario envió 3600 contraseñas incorrectas en una hora, 1 contraseña por segundo, es difícil creer que se trata de un usuario legítimo.
Justificación: si sus contraseñas están codificadas de forma insegura, la fuerza bruta puede ser muy efectiva. Si las contraseñas se almacenan de forma segura, la fuerza bruta sigue desperdiciando los recursos del servidor y el ancho de banda de la red, lo que causa un menor rendimiento para los usuarios legítimos. La detección de fuerza bruta no es fácil de desarrollar y acertar, pero para cualquier sistema que no sea pequeño, vale la pena.
No solicite a sus usuarios que cambien sus contraseñas cada cuatro semanas. Esto es extremadamente molesto y disminuye la seguridad, ya que fomenta la seguridad basada en post-it.
Justificación: la idea de que obligar a cambiar las contraseñas cada n semanas protege al sistema de la fuerza bruta es errónea. Los ataques de fuerza bruta suelen tener éxito en segundos, minutos, horas o días, lo que hace que los cambios mensuales de contraseña sean irrelevantes. Por otro lado, los usuarios son malos para recordar contraseñas. Si, además, necesitan cambiarlos, intentarán usar contraseñas muy simples o simplemente anotarán sus contraseñas en los post-it.
Auditar todo, siempre. Almacene inicios de sesión, pero nunca almacene contraseñas en el registro de auditoría. Asegúrese de que el registro de auditoría no pueda modificarse (es decir, puede agregar datos al final, pero no modificar los datos existentes). Asegúrese de que los registros de auditoría estén sujetos a copias de seguridad periódicas. Idealmente, los registros deberían almacenarse en un servidor dedicado con accesos muy restrictivos: si otro servidor es pirateado, el atacante no podrá borrar los registros para ocultar su presencia (y la ruta tomada durante el ataque).
No recuerde la credencial de usuario en las cookies, a menos que el usuario solicite hacerlo (la casilla de verificación "Recordarme" debe estar desmarcada de forma predeterminada para evitar errores humanos).
Sugerencias de facilidad de uso
<span/>
. Los navegadores no pueden completar el campo de contraseña en este caso (al menos Firefox no puede hacer eso), por lo que obliga a cerrar la sesión y luego iniciar sesión con un formulario normal, completado por el navegador.fuente
bcrypt
lo realizan personas altamente calificadas. También se ha probado, revisado, etc. Así que no hay razón para implementar lo mismo usted mismo. Es como crear su propio algoritmo de criptografía para su sitio web. * "¿Por qué no md5 / sha1?": Ver por ejemplo en.wikipedia.org/wiki/MD5#Securitybcrypt
si es posible. De lo contrario, use algún otro tipo de hash iterado.mysql_real_escape_string
. Nunca use la concatenación de cadenas para elaborar su consulta. Use consultas preparadas y parametrizadas. La mayoría, si no todos, los controladores DB para PHP lo admiten. Que si no sabe cómo hacerlo, pasar algún tiempo en aprender cómoprepare
,bind
yexecute
utilizando cualquier base de datos que está utilizando. Es la única forma segura de protegerse contra la inyección de SQL. PDO apoya esto.fuente
mysql_real_escape_string
es falsa seguridad, no es una garantía. Las consultas parametrizadas son.Use un hash unidireccional salado (preferiblemente SHA512 usando http://au2.php.net/manual/en/function.hash.php ) ... de esa manera, si alguien piratea su base de datos, incluso si conocen la sal , no pueden extraer las contraseñas (sin una tabla de arcoíris, que sería suficiente para SHA512).
Usa HTTPS.
No envíe confirmaciones de nombre de usuario / contraseña por correo electrónico al usuario cuando se registre.
Si permite las cookies para 'recordarme', agregue un inicio de sesión adicional para acceder a las funciones de administración y edición de perfil.
Si un usuario se equivoca con una contraseña, no diga que se equivocó (diga que se equivocó de nombre de usuario o contraseña en todo momento), de esa manera, hay menos pistas sobre los nombres de usuario válidos.
Pruebe e implemente el nombre de usuario frente al inicio de sesión: de esa forma, menos usuarios mostrarán su nombre de inicio de sesión en las listas de usuarios.
fuente
fuente
Aquí hay un pequeño consejo: asegúrese de que no se pueda acceder a sus cookies con JS para evitar el robo, consulte Protección de sus cookies: artículo de HttpOnly de Jeff Atwood
fuente