¿Cuál es la mejor manera de evitar el secuestro de sesión?

Específicamente, se trata de utilizar una cookie de sesión de cliente para identificar una sesión en el servidor.

¿Es la mejor respuesta para usar el cifrado SSL / HTTPS para todo el sitio web, y usted tiene la mejor garantía de que ningún hombre en los ataques intermedios podrá oler una cookie de sesión de cliente existente?

¿Y tal vez lo mejor es utilizar algún tipo de cifrado en el valor de la sesión en sí mismo que está almacenado en su cookie de sesión?

Si un usuario malintencionado tiene acceso físico a una máquina, aún puede ver el sistema de archivos para recuperar una cookie de sesión válida y usarla para secuestrar una sesión.

Encriptar el valor de la sesión tendrá cero efecto. La cookie de sesión ya es un valor arbitrario, cifrarlo generará otro valor arbitrario que puede ser olido.

La única solución real es HTTPS. Si no desea hacer SSL en todo su sitio (tal vez tenga problemas de rendimiento), es posible que pueda salirse con la suya únicamente con SSL que protege las áreas sensibles. Para hacer eso, primero asegúrese de que su página de inicio de sesión sea HTTPS. Cuando un usuario inicia sesión, configure una cookie segura (lo que significa que el navegador solo la transmitirá a través de un enlace SSL) además de la cookie de sesión normal. Luego, cuando un usuario visite una de sus áreas “sensibles”, redirijalas a HTTPS y verifique la presencia de esa cookie segura. Un usuario real lo tendrá, un secuestrador de sesión no lo tendrá.

EDITAR : Esta respuesta se escribió originalmente en 2008. Es 2016 ahora, y no hay ninguna razón para no tener SSL en todo su sitio. ¡No más texto simple HTTP!

El SSL solo ayuda con los ataques de olfateo. Si un atacante tiene acceso a su máquina, supongo que también pueden copiar su cookie segura.

Por lo menos, asegúrese de que las cookies antiguas pierdan su valor después de un tiempo. Incluso un ataque exitoso de secuestro se verá frustrado cuando la cookie deje de funcionar. Si el usuario tiene una cookie de una sesión que inició sesión hace más de un mes, haga que vuelva a ingresar su contraseña. Asegúrese de que cada vez que un usuario haga clic en el enlace de “cierre de sesión” de su sitio, el UUID de sesión anterior nunca pueda volver a utilizarse.

No estoy seguro de si esta idea funcionará, pero aquí va: Agregue un número de serie a su cookie de sesión, tal vez una cadena como esta:

SessionUUID, número de serie, fecha / hora actual

Encripta esta cadena y úsala como tu cookie de sesión. Cambie regularmente el número de serie, tal vez cuando la cookie tiene 5 minutos y luego vuelva a emitir la cookie. Incluso podría volver a emitirlo en cada vista de página si quisiera. En el lado del servidor, mantenga un registro del último número de serie que ha emitido para esa sesión. Si alguna vez alguien envía una cookie con el número de serie equivocado, significa que un atacante puede estar utilizando una cookie que interceptaron anteriormente, así que invalide el UUID de la sesión y solicite al usuario que vuelva a ingresar su contraseña y luego vuelva a emitir una nueva cookie.

Recuerde que su usuario puede tener más de una computadora para que tenga más de una sesión activa. No haga algo que los obligue a volver a iniciar sesión cada vez que cambian de computadora.

¿Has considerado leer un libro sobre seguridad PHP? Muy recomendable.

He tenido mucho éxito con el siguiente método para sitios sin certificación SSL.

  1. Deshabilite varias sesiones con la misma cuenta, asegurándose de que no esté verificando esto únicamente por la dirección IP. En su lugar, compruebe el token generado al iniciar sesión, que se almacena con la sesión de los usuarios en la base de datos, así como la dirección IP, HTTP_USER_AGENT, etc.

  2. Uso de hipervínculos basados ​​en relaciones Genera un enlace (ej. http://example.com/secure.php?token=2349df98sdf98a9asdf8fas98df8 ) El enlace se agrega con una cadena MD5 salada aleatoria x-BYTE (tamaño preferido), al redireccionar la página al azar generado token corresponde a una página solicitada.

    • Al volver a cargar, se realizan varios controles.
    • Dirección IP de origen
    • HTTP_USER_AGENT
    • Token de sesión
    • tú entiendes.
  3. Corta cookie de autenticación de sesión de Life-span. como se publicó anteriormente, una cookie que contiene una cadena segura, que es una de las referencias directas a la validez de las sesiones, es una buena idea. Haga que caduque cada x Minutos, vuelva a emitir ese token y vuelva a sincronizar la sesión con los nuevos Datos. Si hay coincidencias incorrectas en los datos, inicie sesión al usuario o haga que vuelvan a autenticar su sesión.

No soy de ninguna manera un experto en el tema, tuve un poco de experiencia en este tema en particular, espero que algo de esto ayude a cualquiera por ahí.

// Collect this information on every request $aip = $_SERVER['REMOTE_ADDR']; $bip = $_SERVER['HTTP_X_FORWARDED_FOR']; $agent = $_SERVER['HTTP_USER_AGENT']; session_start(); // Do this each time the user successfully logs in. $_SESSION['ident'] = hash("sha256", $aip . $bip . $agent); // Do this every time the client makes a request to the server, after authenticating $ident = hash("sha256", $aip . $bip . $agent); if ($ident != $_SESSION['ident']) { end_session(); header("Location: login.php"); // add some fancy pants GET/POST var headers for login.php, that lets you // know in the login page to notify the user of why they're being challenged // for login again, etc. } 

Lo que hace es capturar información ‘contextual’ sobre la sesión del usuario, información que no debe cambiar durante la vida de una sola sesión. Un usuario no va a estar en una computadora en los Estados Unidos y en China al mismo tiempo, ¿verdad? Por lo tanto, si la dirección IP cambia repentinamente en la misma sesión que implica un bash de secuestro de la sesión, para asegurar la sesión finalice la sesión y obligue al usuario a volver a autenticarse. Esto frustra el bash de pirateo, el atacante también se ve obligado a iniciar sesión en lugar de tener acceso a la sesión. Notifique al usuario del bash (ajaxelo un poco), y vola, usuario ligeramente molesto + informado y su sesión / información está protegida.

Lanzamos User Agent y X-FORWARDED-FOR para hacer nuestro mejor esfuerzo para capturar la exclusividad de una sesión para sistemas detrás de proxies / redes. Es posible que pueda usar más información que eso, siéntase libre de ser creativo.

No es 100%, pero es bastante efectivo.

Hay más cosas que puede hacer para proteger las sesiones, caducarlas, cuando un usuario abandona un sitio web y vuelve forzándolas a volver a iniciar sesión, tal vez. Puede detectar a un usuario que sale y vuelve capturando un HTTP_REFERER en blanco (el dominio fue escrito en la barra de URL), o verifica si el valor en el HTTP_REFERER es igual a su dominio o no (el usuario hizo clic en un enlace externo / diseñado para llegar a su sitio).

Caduque las sesiones, no permita que sigan siendo válidas indefinidamente.

No confíes en las cookies, pueden ser robados, es uno de los vectores de ataque para el secuestro de la sesión.

Pruebe el protocolo Secure Cookie descrito en este documento por Liu, Kovacs, Huang y Gouda:

Como se indica en el documento:

Un protocolo de cookies seguro que se ejecuta entre un cliente y un servidor debe proporcionar los siguientes cuatro servicios: autenticación, confidencialidad, integridad y anti-reproducción.

En cuanto a la facilidad de implementación:

En términos de eficiencia, nuestro protocolo no implica ninguna búsqueda de base de datos o criptografía de clave pública. En términos de capacidad de despliegue, nuestro protocolo puede implementarse fácilmente en un servidor web existente y no requiere ningún cambio en la especificación de cookies de Internet.

En resumen: es seguro, liviano, funciona para mí simplemente genial.

No hay forma de evitar el secuestro de la sesión al 100%, pero con algún enfoque podemos reducir el tiempo para que un atacante secuestre la sesión.

Método para evitar el secuestro de la sesión:

1 – siempre use la sesión con el certificado ssl;

2 – envíe la cookie de sesión solo con httponly establecido en verdadero (evite que javascript tenga acceso a la cookie de sesión)

2 – use la sesión regenerate id al iniciar y cerrar sesión (nota: no use la sesión regenerar en cada solicitud porque si tiene una solicitud ajax consecutiva, entonces tiene la posibilidad de crear varias sesiones).

3 – establecer un tiempo de espera de sesión

Agente de usuario de navegador de 4 tiendas en una variable $ _SESSION y compare con $ _SERVER [‘HTTP_USER_AGENT’] en cada solicitud

5 – configure una cookie de token y establezca el tiempo de caducidad de esa cookie en 0 (hasta que se cierre el navegador). Vuelva a generar el valor de la cookie para cada solicitud. (Para la solicitud ajax no regenere la cookie token). EX:

  //set a token cookie if one not exist if(!isset($_COOKIE['user_token'])){ //generate a random string for cookie value $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM)); //set a session variable with that random string $_SESSION['user_token'] = $cookie_token; //set cookie with rand value setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true); } //set a sesison variable with request of www.example.com if(!isset($_SESSION['request'])){ $_SESSION['request'] = -1; } //increment $_SESSION['request'] with 1 for each request at www.example.com $_SESSION['request']++; //verify if $_SESSION['user_token'] it's equal with $_COOKIE['user_token'] only for $_SESSION['request'] > 0 if($_SESSION['request'] > 0){ // if it's equal then regenerete value of token cookie if not then destroy_session if($_SESSION['user_token'] === $_COOKIE['user_token']){ $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM)); $_SESSION['user_token'] = $cookie_token; setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true); }else{ //code for session_destroy } } //prevent session hijaking with browser user agent if(!isset($_SESSION['user_agent'])){ $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT']; } if($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']){ die('session hijaking - user agent'); } 

Nota: no regenere la cookie token con la nota de solicitud ajax: el código de arriba es un ejemplo. Nota: si los usuarios se desconectan, se debe destruir el token de la cookie y la sesión.

6 – no es un buen enfoque utilizar el IP del usuario para evitar el secuestro de la sesión porque algunos usuarios IP cambian con cada solicitud. QUE AFECTA A LOS USUARIOS VÁLIDOS

7 – Personalmente almaceno los datos de la sesión en la base de datos, depende de usted el método que adopte

Si encuentra un error en mi enfoque, por favor corrígeme. Si tiene más formas de evitar la sesión de hyjaking, por favor dígame.

Asegúrese de no utilizar números enteros incrementales para ID de sesión. Es mucho mejor usar un GUID u otra cadena larga de caracteres generada aleatoriamente.

Hay muchas formas de crear protección contra el secuestro de sesión, sin embargo, todas reducen la satisfacción del usuario o no son seguras.

  • Controles IP y / o X-FORWARDED-FOR. Estos funcionan, y son bastante seguros … pero imagina el dolor de los usuarios. Llegan a una oficina con WiFi, obtienen una nueva dirección IP y pierden la sesión. Tengo que iniciar sesión de nuevo.

  • Agente de usuario comprueba. Igual que el anterior, la nueva versión del navegador está fuera y usted pierde una sesión. Además, estos son realmente fáciles de “piratear”. Es trivial para los hackers enviar cadenas de UA falsas.

  • token LocalStorage. Al iniciar sesión, genere un token, almacénelo en el almacenamiento del navegador y guárdelo en una cookie cifrada (encriptada en el lado del servidor). Esto no tiene efectos secundarios para el usuario (localStorage persiste a través de las actualizaciones del navegador). No es tan seguro, ya que es solo seguridad a través de la oscuridad. Además, podría agregar un poco de lógica (cifrado / descifrado) a JS para oscurecerlo aún más.

  • Reedición de cookies. Esta es probablemente la forma correcta de hacerlo. El truco es permitir que solo un cliente use una cookie a la vez. Por lo tanto, el usuario activo volverá a emitir las cookies cada hora o menos. La cookie antigua se invalida si se emite una nueva. Los piratas aún son posibles, pero mucho más difíciles de hacer, ya sea un pirata informático o un usuario válido que se rechace el acceso.

Consideremos que durante la fase de inicio de sesión, el cliente y el servidor pueden acordar un valor secreto de sal. A partir de entonces, el servidor proporciona un valor de recuento con cada actualización y espera que el cliente responda con el hash del (recuento secreto de sal +). El posible secuestrador no tiene ninguna forma de obtener este valor de sal secreta y, por lo tanto, no puede generar el siguiente hash.

AFAIK no se puede acceder al objeto de sesión en el cliente, ya que está almacenado en el servidor web. Sin embargo, la identificación de la sesión se almacena como una Cookie y permite que el servidor web rastree la sesión del usuario.

Para evitar el secuestro de sesión utilizando la identificación de la sesión, puede almacenar una cadena hash dentro del objeto de sesión, creada mediante una combinación de dos atributos, un directorio remoto y un puerto remoto, al que se puede acceder en el servidor web dentro del objeto de solicitud. Estos atributos vinculan la sesión del usuario con el navegador donde el usuario inició sesión.

Si el usuario inicia sesión desde otro navegador o un modo incógnito en el mismo sistema, el addr de IP seguirá siendo el mismo, pero el puerto será diferente. Por lo tanto, cuando se accede a la aplicación, el servidor web le asigna una identificación de sesión diferente.

A continuación se muestra el código que he implementado y probado al copiar la identificación de la sesión de una sesión a otra. Funciona bastante bien. Si hay una laguna, hágame saber cómo lo simuló.

 @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); String sessionKey = (String) session.getAttribute("sessionkey"); String remoteAddr = request.getRemoteAddr(); int remotePort = request.getRemotePort(); String sha256Hex = DigestUtils.sha256Hex(remoteAddr + remotePort); if (sessionKey == null || sessionKey.isEmpty()) { session.setAttribute("sessionkey", sha256Hex); // save mapping to memory to track which user attempted Application.userSessionMap.put(sha256Hex, remoteAddr + remotePort); } else if (!sha256Hex.equals(sessionKey)) { session.invalidate(); response.getWriter().append(Application.userSessionMap.get(sessionKey)); response.getWriter().append(" attempted to hijack session id ").append(request.getRequestedSessionId()); response.getWriter().append("of user ").append(Application.userSessionMap.get(sha256Hex)); return; } response.getWriter().append("Valid Session\n"); } 

Usé el algoritmo SHA-2 para calcular el valor usando el ejemplo dado en SHA-256 Hashing at baeldung

Esperamos sus comentarios.

Para reducir el riesgo, también puede asociar la IP de origen con la sesión. De esta forma, un atacante debe estar dentro de la misma red privada para poder usar la sesión.

La comprobación de los encabezados de referencia también puede ser una opción, pero es más fácil suplantar.

Proteger por:

 $ip=$_SERVER['REMOTE_ADDER']; $_SESSEION['ip']=$ip;