2009-12-16 9 views
8

Estoy desarrollando un sistema de autenticación y acceso para un nuevo sitio PHP y he estado leyendo sobre los diversos ataques y vulnerabilidades. Sin embargo, es un poco confuso, así que quiero verificar que mi enfoque tenga sentido.Desarrollo de un inicio de sesión seguro de PHP y estrategia de autenticación

que planea almacenar los siguientes datos:

  • En la sesión: identificación de usuario, hash + salada HTTP_USER_AGENT

  • en la cookie y en la base de datos: testigo aleatorio , hashed + salado identificador

En cada página, I planear en hacer lo siguiente:

  1. Si existe una sesión, la autenticación con eso. Compruebe que el HTTP_USER_AGENT coincida con el de la sesión almacenada.

  2. Si no existe sesión, use la cookie para autenticar. Compruebe que el token y el identificador en la cookie coinciden con los de la base de datos.

  3. Si la cookie no es válida o no existe, solicite al usuario que inicie sesión.

¿Hay algún defecto obvio en esto? Mientras establezca un tiempo de espera en la cookie, debería estar bastante seguro, ¿verdad? ¿Hay algo que me estoy perdiendo?

Muchas gracias de antemano.

+0

también consideran usar algún sistema de token una vez para acciones críticas ... – TheHippo

+0

Exactamente, almacenar la identificación de la sesión en la base de datos es un error enorme. Al almacenar la identificación de la sesión en la base de datos, hace que la inyección de sql en su sistema sea mucho más valiosa. Debe suponer que su sistema se dividirá, y debe tener un plan de acción para hacer frente a la violación. Es por eso que las contraseñas se almacenan como hashes. Además, más php viene con un manejador de sesión, si vuelves a inventar el wheal te aseguro que será menos seguro. – rook

+0

También hay una gran cantidad de buena lectura: http://stackoverflow.com/questions/549/the-definitive-guide-to-website-authentication-beta#477579 –

Respuesta

12

Unos pocos pensamientos al azar:

  1. ¿Qué pasa si me roban la cookie de uno de sus usuarios (usando un ataque XSS mediante la inyección de un código JS en su sitio web)? Luego me caeré en el caso 2. y, por lo tanto, podré iniciar sesión. En mi humilde opinión, si desea una autenticación realmente segura, no use las cookies de tipo "Recordarme" para almacenar las credenciales de los usuarios.
  2. Si almacena las credenciales en una cookie, no almacene la contraseña en claro.
  3. La comprobación del HTTP_USER_AGENT es un buen primer paso para evitar el secuestro de la sesión, pero ¿podría combinarlo con la dirección IP? Es mucho más difícil estar en el mismo host que tu objetivo que simplemente usar el mismo navegador.

Pero en cualquier caso, gracias por tomarse el tiempo de pensar en un buen esquema de autenticación. Muchos desarrolladores de PHP no lo hacen.

EDITAR: para que quede constancia, permítanme aclarar un punto aquí: hay dos cookies en esta discusión. Uno configurado automáticamente por PHP para propagar el ID de la sesión (a veces, vemos sitios web que lo ponen en la URL, por ejemplo, www.example.com/page.php?sessionId = [...]), y el segundo creado por usted para almacenar las credenciales del usuario y autenticarlo cuando se pierde la sesión. El ataque XSS se aplica a ambos, es decir, un atacante podría robar la cookie de sesión y secuestrar la sesión (que tiene una vida útil limitada) o robar la cookie de las credenciales y autenticarse más tarde.

+0

Verificando una combinación del agente de usuario y los primeros 3 octetos de la IP es bastante bueno. Escribí un artículo sobre el tema en http://www.jqueryin.com/2009/11/20/php-secure-sessions/. –

+0

De hecho, el agente de usuario + dirección IP es más que suficiente. Pero, ¿por qué perder el último octeto? IMO, es la parte más importante de la dirección IP, ya que mi vecino puede estar en la misma subred de ISP y tener los mismos tres primeros octetos. Gran artículo, por cierto, utilizo dos sales: una fija en un archivo de configuración y otra generada aleatoriamente en la creación del usuario. – Wookai

+0

Almacenar la cookie en la base de datos es una idea HORRILBE. Significa que si un atacante tiene una vulnerabilidad de inyección sql, podría obtener acceso de inmediato sin tener que descifrar una contraseña hash. – rook

2

no debe haber. la sesión php está almacenada en su servidor no es el usuario. php simplemente deja una cookie de sesión apuntando hacia ella. si no está en alojamiento compartido, la sesión ni siquiera tiene que ser hash.

joe

1

depende de qué tan seguro que quieres ser ..

vulnerabilidades de cross-site: permite decir otro sitio dirige el navegador para enviar un formulario a su sitio que hace algo así como la publicación de correo no deseado (o peor) si eso el usuario ya inició sesión, el envío del formulario funcionará. Deberá verificar el referer y un formID oculto generado para cada formulario para protegerlo completamente.

Segundo: Si tiene un tráfico alto o mediano, los ID de sesión pueden repetirse o incluso adivinarse, verificaría contra un ID generado de segunda mano que está almacenado en las cookies de los usuarios.

1

El esquema parece innecesariamente complejo en algunos aspectos, en el sentido de que la complejidad adicional no gana nada en funcionalidad o seguridad.

  1. Todos los datos enviados por el navegador (por ejemplo, cookies, agente de usuario) son falsificables. La comprobación de User-agent solo ayudará cuando el atacante esté detrás de la misma NAT que el usuario falso y el atacante esté utilizando un navegador diferente, pero no piense en cambiar el User-agent.
  2. Las sesiones almacenan la identificación de sesión del lado del cliente utilizando cookies o un parámetro de consulta URL. Si desea extender la duración de una sesión, use session_set_cookie_params para mantener la cookie de sesión por más tiempo.

El agente de usuario no es información secreta, por lo que no es necesario hacerlo.

Los ataques que la cookie de sesión + comprobación de IP remota no cogerá son:

  1. el atacante está detrás de la misma NAT como el usuario
  2. ataques de inyección ciegos, donde el atacante SPOOFS IP del usuario. A pesar de ser solo de escritura, estos aún pueden causar algún daño.
  3. ataques que hacen uso del propio navegador del usuario, como cross-site request forgery (CSRF).

2) podría evitarse si puede encontrar una forma de enviar un desafío al navegador del usuario, que debe responder antes de completar la solicitud, pero esto es complicado cuando no escribió el cliente. Con AJAX se puede hacer. 3) (según lo observado por MindStalker) puede evitarse marcando el encabezado Referer, que funciona porque los ataques CSRF no tienen la capacidad de afectar los encabezados arbitrarios, y XMLHttpRequest no debe permitir que se establezca el encabezado Referer (según el W3C standard , aunque las implementaciones pueden no ser compatibles). Con los iframes, es posible sortear una verificación Referer. Además, el encabezado del Referer podría estar bloqueado en el lado del cliente.

2

Almacenar la cookie en la base de datos es una idea HORRILBE. Significa que si un atacante tiene una vulnerabilidad de inyección sql, podría obtener acceso de inmediato sin tener que descifrar una contraseña hash.

Hablando de lo cual necesitas usar sha256 para contraseñas, si usas md5() eres técnicamente vulnerable a los ataques y podrías recibir un número CVE.

NUNCA genere sus propios id. De sesión, use session_start() y el $ _SESSION super global.

Esta es una forma segura de redirigir a las personas. Si no muere después de cabecera() el resto del código php se ejecuta TODAVÍA aunque no es representada por los navegadores normales (hackers todavía lo ven :)

header("location: index.php"); 
die(); 

para ser honesto si la seguridad se confunde, don escribe sistemas de seguridad Las personas han escrito más de 1,000 sistemas de inicio de sesión solo para PHP y la mayoría son vulnerables. Este proyecto tiene un sistema de autenticación segura: http://code.google.com/p/michael-the-messenger/downloads/list

+0

En su primer punto: No quiero decir que tomará la cookie del usuario y la almacenará en la base de datos; eso sería tonto! Quiero decir que se crean un token y un identificador y luego una copia se coloca en la cookie y la otra en la base de datos. Ningún dato de la cookie pasa a la base de datos, por lo que no se puede inyectar de esa manera. Gracias por la cosa sobre el encabezado(), nunca lo supe. –

+0

Exactamente, eso es un error enorme. Al almacenar el valor de la cookie en la base de datos, usted hace que la inyección de sql en su sistema sea mucho más valiosa. Debe suponer que su sistema se dividirá, y debe tener un plan de acción para hacer frente a la violación. Es por eso que las contraseñas se almacenan como hashes. Además, más php viene con un manejador de sesión, si vuelves a inventar el wheal te aseguro que será menos seguro. – rook

+0

No se preocupe: ¡no tengo planes de crear mi propio controlador de sesión! –

1

La mayoría de los sitios solo usan la sesión de PHP; los datos de la sesión ($ _SESSION) están en a file en su servidor. Todo lo que se envía al navegador es una ID de sesión. Asegúrese de regenerar la sesión en cada solicitud (session_regenerate_id). No necesita enviar dos cookies ni nada.

Esto es menos vulnerable al secuestro de sesión ya que cada solicitud es una nueva ID, por lo que una antigua interceptada por un atacante es inútil.

La mejor solución, obviamente, sería usar SSL durante toda la sesión.

0

En mi humilde opinión también es importante que la información de la sesión se modifique después de un inicio de sesión exitoso. Para guardar la información de la sesión en una base de datos no se guarda debido a las inyecciones.

0

-uso sha1 con sal -por supuesto, debe definir que cada forma no es segura, por lo que se utiliza token para cada forma. Que crees cada entrada de formulario y lo desinfecte usando preg_match. Un proceso llamado saneamiento.

Cuestiones relacionadas