Pregunta

Específicamente, esto se refiere al uso de una cookie de sesión de cliente para identificar una sesión en el servidor.

¿La mejor respuesta es utilizar el cifrado SSL/HTTPS para todo el sitio web y tener la mejor garantía de que ningún intermediario podrá detectar una cookie de sesión de cliente existente?

¿Y quizás la segunda mejor opción es utilizar algún tipo de cifrado en el valor de la sesión que se almacena en la cookie de la sesión?

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

¿Fue útil?

Solución

Cifrar el valor de la sesión no tendrá ningún efecto.La cookie de sesión ya es un valor arbitrario; cifrarla simplemente generará otro valor arbitrario que se puede detectar.

La única solución real es HTTPS.Si no desea utilizar SSL en todo su sitio (tal vez tenga problemas de rendimiento), es posible que pueda salirse con la suya protegiendo solo SSL las áreas confidenciales.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", rediríjalo a HTTPS y verifique la presencia de esa cookie segura.Un usuario real lo tendrá, un secuestrador de sesión no.

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

Otros consejos

El SSL sólo ayuda con los ataques de rastreo.Si un atacante tiene acceso a su máquina, asumiré que también puede copiar su cookie segura.

Como mínimo, asegúrese de que las cookies antiguas pierdan su valor después de un tiempo.Incluso un ataque de secuestro exitoso 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, pídale que vuelva a ingresar su contraseña.Asegúrese de que cada vez que un usuario haga clic en el enlace "cerrar sesión" de su sitio, el UUID de sesión anterior nunca pueda volver a usarse.

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:

UUID de sesión, número de serie, fecha/hora actual

Cifre esta cadena y utilícela como cookie de sesión.Cambie periódicamente el número de serie, tal vez cuando la cookie tenga 5 minutos y luego vuelva a emitirla.Incluso podrías volver a publicarlo en cada vista de página si así lo deseas.En el lado del servidor, mantenga un registro del último número de serie que haya emitido para esa sesión.Si alguien alguna vez envía una cookie con el número de serie incorrecto, significa que un atacante puede estar usando una cookie que interceptó anteriormente, por lo tanto, 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 por lo que puede tener más de una sesión activa.No hagas algo que los obligue a iniciar sesión nuevamente 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. No permita múltiples sesiones bajo la misma cuenta, asegurándose de no verificar esto únicamente por dirección IP.En lugar de eso, verifique el token generado al iniciar sesión, que se almacena con la sesión del usuario en la base de datos, así como la dirección IP, HTTP_USER_AGENT, etc.

  2. El uso de hipervínculos basados ​​en relaciones genera un enlace (por ejemplo. http://example.com/secure.php?token=2349df98sdf98a9asdf8fas98df8 ) El enlace se adjunta con una cadena MD5 salada X-byte (tamaño preferido), tras la redirección de la página, el token generado aleatoriamente corresponde a una página solicitada.

    • Al recargar, se realizan varias comprobaciones.
    • Dirección IP de origen
    • HTTP_USER_AGENT
    • Token de sesión
    • tú entiendes.
  3. Cookie de autenticación de sesión de corta duración.Como se publicó anteriormente, una cookie que contenga 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 alguna discrepancia en los datos, cierre la sesión del usuario o pídale que vuelva a autenticar su sesión.

De ninguna manera soy un experto en el tema, he tenido un poco de experiencia en este tema en particular, espero que algo de esto ayude a alguien.

// 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 esto hace es capturar información "contextual" sobre la sesión del usuario, información que no debería cambiar durante la vida de una sola sesión.Un usuario no va a estar frente a una computadora en EE. UU. y en China al mismo tiempo, ¿verdad?Entonces, si la dirección IP cambia repentinamente dentro de la misma sesión, eso implica fuertemente un intento de secuestro de sesión, entonces usted asegura la sesión finalizándola y obligando al usuario a volver a autenticarse.Esto frustra el intento de pirateo y el atacante también se ve obligado a iniciar sesión en lugar de obtener acceso a la sesión.Notifique al usuario del intento (acelere un poco) y vola, usuario ligeramente molesto + informado y su sesión/información está protegida.

Agregamos User Agent y X-FORWARDED-FOR para hacer nuestro mejor esfuerzo para capturar la unicidad de una sesión para sistemas detrás de servidores proxy/redes.Es posible que puedas utilizar más información, siéntete libre de ser creativo.

No es 100%, pero es bastante efectivo.

Hay más que puede hacer para proteger las sesiones, expirarlas, cuando un usuario abandona un sitio web y regresa, tal vez lo obligue a iniciar sesión nuevamente.Puede detectar que un usuario sale y regresa capturando un HTTP_REFERER en blanco (el dominio se escribió en la barra de URL), o verificar si el valor en HTTP_REFERER es igual a su dominio o no (el usuario hizo clic en un enlace externo/diseñado para llegar a su sitio).

Caducar las sesiones, no dejes que sigan siendo válidas indefinidamente.

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

Pruebe el protocolo Secure Cookie descrito en este artículo de 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-repetición.

En cuanto a la facilidad de implementación:

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

En breve:Es seguro, liviano y me funciona genial.

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

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

1 - utilice siempre la sesión con certificado ssl;

2: envíe la cookie de sesión solo con httponly configurado en verdadero (evite que javascript acceda a la cookie de sesión)

2 - use la identificación de regeneración de sesión al iniciar y cerrar sesión (nota:no utilice la regeneración de sesión en cada solicitud porque si tiene una solicitud ajax consecutiva, tiene la posibilidad de crear varias sesiones).

3 - establecer un tiempo de espera de sesión

4: almacene el agente de usuario del navegador en una variable $_SESSION y compárelo con $_SERVER['HTTP_USER_AGENT'] en cada solicitud

5: configure una cookie simbólica y establezca el tiempo de vencimiento de esa cookie en 0 (hasta que se cierre el navegador).Regenere el valor de la cookie para cada solicitud (para solicitudes 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 solicitud de solicitud de AJAX:El código anterior es un ejemplo.nota:Si los usuarios cierran sesión, el token de cookie debe destruirse, así como la sesión.

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

7 - personalmente almaceno los datos de la sesión en la base de datos, depende de usted qué método adopte

Si encuentra un error en mi enfoque, corríjame.Si tienes más formas de evitar el hyjaking en la sesión, dímelo.

Asegúrese de no utilizar números enteros crecientes para los ID de sesión.Es mucho mejor utilizar un GUID o alguna otra cadena de caracteres larga generada aleatoriamente.

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

  • Comprobaciones de 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 nuevamente.

  • Comprobaciones del agente de usuario.Igual que arriba, la nueva versión del navegador está disponible y usted pierde una sesión.Además, son realmente fáciles de "piratear".Es trivial para los piratas informáticos enviar cadenas UA falsas.

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

  • Reemisión de cookies.Probablemente esta sea la forma correcta de hacerlo.El truco consiste en permitir que sólo un cliente utilice una cookie a la vez.Por lo tanto, al usuario activo se le volverá a emitir una cookie cada hora o menos.La cookie antigua se invalida si se emite una nueva.Los hacks todavía son posibles, pero mucho más difíciles de realizar: se rechazará el acceso al hacker o al usuario válido.

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

AFAIK, el objeto de sesión no es accesible 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 al servidor web rastrear 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 utilizando una combinación de dos atributos, dirección remota y puerto remoto, a los 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 en modo incógnito en el mismo sistema, la dirección IP seguirá siendo la misma, pero el puerto será diferente.Por lo tanto, cuando se accede a la aplicación, el servidor web asignará al usuario una identificación de sesión diferente.

A continuación se muestra el código que implementé y probé copiando la identificación de la sesión de una sesión a otra.Funciona bastante bien.Si hay una laguna jurídica, déjame saber cómo la simulaste.

@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");
}

Utilicé el algoritmo SHA-2 para codificar el valor usando el ejemplo dado en Hash SHA-256 en baeldung

Esperamos sus comentarios.

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

Verificar los encabezados de referencia también puede ser una opción, pero son más fáciles de falsificar.

Proteger por:

$ip=$_SERVER['REMOTE_ADDER'];
$_SESSEION['ip']=$ip;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top