2009-09-01 29 views
5

¿Cómo escribo/trabajo un inicio de sesión seguro en PHP? El website developer guide dijo que no debería hacer mi propia versión, por lo que referirse a muestras disponibles a través de Google es inútil.Inicio de sesión seguro con la autenticación adecuada en PHP

¿Cómo lo hacen los profesionales? Digamos que estás construyendo una aplicación de clase mundial en rieles, ¿se podrían usar las mismas bibliotecas/técnicas aquí?

Gracias

+0

es posible que desee echar un vistazo a https://github.com/delight-im/PHP-Auth que es tanto independiente del marco y base de datos agnóstica. – caw

Respuesta

20

En Rails, generalmente se usaría una biblioteca preexistente. La autenticación es fácil de hacer mal, y el problema se ha resuelto tantas veces que rara vez vale la pena el esfuerzo para resolverlo de nuevo. Si está interesado en escribir su propia implementación, describiré cómo funciona la autenticación moderna.

El método ingenuo de autenticar a un usuario es almacenar su contraseña en una base de datos y compararla con la contraseña que el usuario envía. Esto es simple pero increíblemente inseguro. Cualquiera que pueda leer su base de datos puede ver la contraseña de cualquier persona. Incluso si pone controles de acceso a la base de datos, usted (y sus usuarios) son vulnerables a cualquiera que los piratee.

La forma correcta es utilizar una función hash criptográfica para procesar la contraseña cuando se elige y luego cada vez que se envía. Una buena función de hash es prácticamente irreversible: no puede tomar un hash y convertirlo en una contraseña. Entonces, cuando el usuario inicia sesión, toma la contraseña enviada, la modifica y la compara con el hash en la base de datos. De esta forma, nunca almacena la contraseña en sí. En el lado negativo, si el usuario olvida su contraseña, debe restablecerla en lugar de enviársela.

Incluso esto, sin embargo, es vulnerable a ciertos ataques. Si un atacante se apodera de los hashes de su contraseña y sabe cómo hash sus contraseñas, entonces puede hacer un ataque de diccionario: simplemente toma cada palabra en el diccionario y la mezcla con la original. Esta estructura de datos se llama tabla de arco iris. Luego, si alguno de los hashes de la palabra del diccionario coincide con un hash de contraseña, el atacante puede concluir que la contraseña es la palabra del diccionario que contiene esa contraseña. En resumen, un atacante que puede leer su base de datos aún puede iniciar sesión en cuentas con contraseñas débiles.

La solución es que antes de que se contrate una contraseña, se combina (generalmente concatenada o xor'd) con un valor llamado sal que es exclusivo para cada usuario. Puede generarse aleatoriamente, o puede ser una marca de tiempo de creación de cuenta o algo así. Entonces, un atacante no puede usar una tabla de arcoíris porque cada contraseña es esencialmente hash ligeramente diferente; tendría que crear una tabla de arcoiris separada para cada sal distinta (prácticamente para cada cuenta), lo que sería prohibitivamente costoso desde el punto de vista computacional.

Me haré eco del consejo de los otros que responden: esto no es algo simple, y no necesita hacerlo porque ya se ha hecho antes, y si lo hace usted mismo tiene una muy buena oportunidad de hacer una error e inadvertidamente comprometiendo la seguridad de su sistema. Pero si, por alguna razón, realmente desea escribir uno usted mismo, espero haber proporcionado un bosquejo (incompleto) de cómo se hace.

+2

+1 - Para una respuesta muy buena. –

+1

+1 - Agradable pero largo y divagante. : escalofríos: ¿estoy en una sala de conferencias con paneles de roble? –

+1

hash contraseñas saladas no es realmente tan difícil de hacer. – Herbert

-2

Mi respuesta es "no lo hagas"

Esta es un área muy compleja, llena de seguridad potenciales gotcha. Si no eres un experto en este campo, entonces realmente solo estás pidiendo problemas y problemas en el futuro.

Recomendaría buscar una solución existente para hacer. Lamentablemente, no conozco ninguno que me complacería recomendar, aparte de openid. Estoy seguro de que obtendrá algunas buenas sugerencias aquí ...

4

El Zend Framework tiene un 'Auth' module que sería un buen lugar para comenzar. O bien, si su sitio albergará una instalación de WordPress o PHPBB, existen formas de aprovechar los módulos de autenticación de esas tecnologías para iniciar sesión en otras páginas de un sitio.

+0

El módulo Zend Auth no resuelve la pregunta de OPs.Y, además, los ejemplos usan múltiples prácticas inseguras. En conclusión: Zend Auth es un sabio de seguridad horrible. – Jacco

+0

inseguro? Es una herramienta que depende de cómo la uses; ¿Te importa dar ejemplos/discusiones de cómo es inseguro? Zend_Auth es un módulo de autenticación existente con un historial, que es lo opuesto a "rodar uno mismo", que es lo que era la pregunta original; ¿Cómo es que eso no lo está satisfaciendo? – MidnightLightning

+0

[Uso avanzado mediante el ejemplo] (http://zendframework.com/manual/en/zend.auth.adapter.dbtable.html) usa MD5, envía la contraseña a la base de datos en lugar de verificar el lado de PHP (que puede hacer que la contraseña aparezca en los registros de consulta), etc. Lo que ocurre con los chicos de Zend es que se consideran expertos e ignoran los comentarios. – Jacco

2

Una cosa a tener en cuenta cuando intenta autenticar es cuál es su objetivo real.

Por ejemplo, el SO uso mi acceso a Google y que funciona, ya que sólo necesitan saber quién soy, y que pueden confiar en que Google tiene una idea. Entonces, si ese modelo funciona para usted, entonces considere usar OpenID, ya que hay varias herramientas para eso.

Si usted debe hacer su propia, entonces habrá varias pruebas para asegurarse de que es seguro, una vez más, dependiendo de lo paranoico que desea ser.

  • Nunca confíes en nada del usuario, a menos que hayas usado alguna verificación estricta.
  • Use https para ayudar a proteger la contraseña del usuario, se los debe tanto.

Terminaré mi respuesta aquí ya que Thom hizo una respuesta fantástica.

0

por Soulmerge:

creo que el accepted answer in your other question establece bastante bien. Hash las contraseñas con una sal. Aparte de eso, hay algunas ideas de seguridad en la capa de transporte:

  • Use https para enviar contraseñas. Esto se asegura de que nadie puede cogerlos en el cable (man-in-the-middle attack o el cliente utiliza un proxy mal)
  • Una alternativa es hash de la contraseña usando javascript cuando se envía el formulario de acceso. Esto asegura que la contraseña nunca se transporta en texto sin formato. Debería hash el valor hash nuevamente con una sal en el servidor. (md5($_POST['postedPwHash'] . $salt))
-1

un buen método para asegurar un tanto la transacción de cliente-servidor (si no hay SSL está disponible) es el uso de una clave aleatoria de una sola vez para crear un hash único de las credenciales, entonces sólo enviar ese único hash al servidor. el servidor compara este hash con su propio hash generado en lugar de compararlo con las credenciales reales. esto proporcionaría una buena defensa contra el ataque del hombre en el medio. La desventaja es que para hacer esto el usuario debe tener JS habilitado (al menos no conozco un buen método para encriptar los datos del lado del cliente sin él). esto significa que necesitará una reserva suficiente cuando no esté encendida. incluso puede crear el formulario en JS para asegurarse de que esté habilitado.

this library es una simple biblioteca i escribió una vez que lo hace el procedimiento he descrito, aunque probablemente necesita algunas mejoras.

nota que esto es además de utilizar "salazón" métodos y otras medidas de seguridad del lado del servidor. también es bastante vulnerable a los ataques de diccionario, ya que todo el proceso de hashing es, por definición, de procedimiento, predecible y visible para el usuario (como siempre lo es JS).

Cuestiones relacionadas