È una funzione sicura per verificare se un utente non ha rubato un cookie di sessione?

1

Come esercizio per la classe, sto creando una classe che gestisce le sessioni utente.

I dettagli della sessione sono memorizzati in un database e c'è anche una variabile $_SESSION[user_id] da trasportare tra le pagine.

L'idea è che sarebbe difficile per un utente malintenzionato rubare il cookie E l'indirizzo IP E l'agente utente E per mantenere la sessione aggiornata, dato che ho messo un limite di 15 minuti.

Quando l'utente esegue il login, l'oggetto del database viene creato, quindi la sua esistenza viene verificata in ogni pagina visitata.

<?php
//Recojo parametros de formulario de logeo
$username = $_POST['username'];
$password = $_POST['password'];

//abro conexion base de datos
$mysqli = new mysqli("localhost", "root", "unir_2014", "wordpress");
if ($mysqli->connect_errno) {
    printf("La conexion ha fallado! El servidor responde: %s\n", $mysqli->connect_error);
    exit();
}
//----------------------------------------------------------------------------------------//       
//----------------------------------------------------------------------------------------//     //EXPIRAR         
            $comienzo = time(); // Momento al logearse
            // Le damos un tiempo de expiracion de 1 minuto
            $expirar = $comienzo + (15 * 60);
//----------------------------------------------------------------------------------------//     //IP ADDRESS  
              if (isset($_SERVER)) {
                  if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]) && ip2long($_SERVER["HTTP_X_FORWARDED_FOR"]) !== false) {
                      $ipadres = $_SERVER["HTTP_X_FORWARDED_FOR"];
                  } elseif (isset($_SERVER["HTTP_CLIENT_IP"])  && ip2long($_SERVER["HTTP_CLIENT_IP"]) !== false) {
                      $ipadres = $_SERVER["HTTP_CLIENT_IP"];
                  } else {
                      $ipadres = $_SERVER["REMOTE_ADDR"];
                  }
              } else {
                  if (getenv('HTTP_X_FORWARDED_FOR') && ip2long(getenv('HTTP_X_FORWARDED_FOR')) !== false) {
                      $ipadres = getenv('HTTP_X_FORWARDED_FOR');
                  } elseif (getenv('HTTP_CLIENT_IP') && ip2long(getenv('HTTP_CLIENT_IP')) !== false) {
                      $ipadres = getenv('HTTP_CLIENT_IP');
                  } else {
                      $ipadres = getenv('REMOTE_ADDR');
                  }
              }
//----------------------------------------------------------------------------------------//      $version_cliente = $_SERVER['HTTP_USER_AGENT'];
//----------------------------------------------------------------------------------------//$query = "SELECT * FROM sesiones WHERE name ='" .$username."'";
if ($result = $mysqli->query($query)) {
    while($row = mysqli_fetch_array($result)) {
        $salt = $row['salt'];
        $passcheck = $row['password'];
        $id_usuario = $row['id_usuario'];
        $passwordin = md5($password.$salt);
        $direccion_ip = $ipadres;
    }
    //compruebo si la contraseña coincide con el hash almacenado en la base de datos
         if( $passcheck === $passwordin){

                echo '<script> window.location = "privatecontent.php" </script>';
                //if the user has javascript

                $url = 'privatecontent.php';
                echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$url.'">';
                //if the user doesnt have javascript*
//----------------------------------------------------------------------------------------//    //INTRODUCIMOS OBJETO SESSION EN LA BASE DE DATOS 
    //mysqli_query($connection, "INSERT INTO 'wordpress'.'session_log' ('id_sesion', 'id_usuario', 'direccion_ip', 'version_cliente', 'expirar') VALUES ('', '".$id_usuario."', '".$direccion_ip."', '".$version_cliente."', '".$expirar."');");
    mysqli_query($mysqli, "INSERT INTO 'wordpress'.'session_log' ('id_sesion', 'id_usuario', 'direccion_ip', 'version_cliente', 'expirar') VALUES ('', '".$id_usuario."', '".$direccion_ip."', '".$version_cliente."', '".$expirar."');"); 
    //la variable de sesion solo almacena la id de usuario en uso, para asociarlo a la sesion de la base de datos
    session_start();
    $_SESSION['user_id'] = $id_usuario;
    }
}
else{    
                 echo '<div id="wrong" class="wrong"> "Nombre de usuario o contraseña incorrectos! <br>';
                 echo "Haz click<a href='FORMULARIO DE REGISTRO!!!'>aqui</a> para registrarte...</div>";  
            }

Quello sarebbe il gestore di login, ora, la classe check_login:

<?php
// TODAS LAS PAGINAS DEBEN INCLUIR ESTE ARCHIVO!
//abro conexion base de datos
$mysqli = new mysqli("localhost", "root", "unir_2014", "wordpress");
if ($mysqli->connect_errno) {
    printf("La conexion ha fallado! El servidor responde: %s\n", $mysqli->connect_error);
    exit();
}

//buscamos el id del usuario activo.
//recibimo de $_SESSION (o sea la cookie del cliente) solo el id del usuario. que usuario dice ser
//si la cookie ha sido robada, lo mas probable es que la ip y el user agent hayan cambiado, asi que la session FALLARA
//robar una cookie antigua tampoco ayudara, pues solo duran 15 minutos
session_start();
$id_usuario = $_SESSION['user_id'];

//busco en la tabla SESIONES si existe un numbre de usuario como ese
$query = "SELECT * FROM session_log WHERE id_usuario ='".$id_usuario."'";

//si existe, saco sus datos
if ($result = $mysqli->query($query)) {
    while($row = mysqli_fetch_array($result)) {
        $ip_check = $row['direccion_ip'];
        $expirar = $row['expirar'];
        $cliente_check = $row['version_cliente'];
        $id_sesion = $row['id_sesion'];
    }
}



//comprobamos que el usuario esta logeado, tiene buen user_agent, la misma direccion ip y no se ha pasado de tiempo

    //COMPROBAR SI LA SESION HA EXPIRADO
        $now = time(); 
        if ($now > $expirar) {
            $url = 'NO_SESSION.php';
            echo '<script> window.location = "'.$url.'" </script>';
            echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$url.'">';
        }

    //COMPROBAR QUE VIENE DE LA MISMA IP   
            if (isset($_SERVER)) {
                  if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]) && ip2long($_SERVER["HTTP_X_FORWARDED_FOR"]) !== false) {
                      $ipadres = $_SERVER["HTTP_X_FORWARDED_FOR"];
                  } elseif (isset($_SERVER["HTTP_CLIENT_IP"])  && ip2long($_SERVER["HTTP_CLIENT_IP"]) !== false) {
                      $ipadres = $_SERVER["HTTP_CLIENT_IP"];
                  } else {
                      $ipadres = $_SERVER["REMOTE_ADDR"];
                  }
              } else {
                  if (getenv('HTTP_X_FORWARDED_FOR') && ip2long(getenv('HTTP_X_FORWARDED_FOR')) !== false) {
                      $ipadres = getenv('HTTP_X_FORWARDED_FOR');
                  } elseif (getenv('HTTP_CLIENT_IP') && ip2long(getenv('HTTP_CLIENT_IP')) !== false) {
                      $ipadres = getenv('HTTP_CLIENT_IP');
                  } else {
                      $ipadres = getenv('REMOTE_ADDR');
                  }
              }    


        if ($ip_check !== $ipadres){ 
            $url = 'NO_SESSION.php';
            echo '<script> window.location = "'.$url.'" </script>';
            echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$url.'">';
        }



    //COMPROBAR QUE TIENE EL MISMO USER AGENT   
    $version_cliente = $_SERVER['HTTP_USER_AGENT'];    
        if ($cliente_check != $version_cliente){
            $url = 'NO_SESSION.php';
            echo '<script> window.location = "'.$url.'" </script>';
            echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$url.'">';
        }




    //si ninguno de estos controles falla, llego hasta aqui
    //significa que el usuario ha visitado una pagina nueva y sigue con la misma session, asi que debo
    //actualizar el campo "expirar" para que la session dure mas

    $new_expirar =  time() + (15 * 60);
    mysqli_query($mysqli, "UPDATE 'wordpress'.'session_log' SET 'expirar' = '".$new_expirar."' WHERE 'session_log'.'id_sesion' =$id_sesion;");
    
posta user3453619 14.05.2014 - 13:24
fonte

3 risposte

1

Sì, è sicuro, ma ha il fallback, che i tuoi utenti non saranno in grado di cambiare i loro IPS. Ad esempio, se torno a casa con il mio telefono Android e passa da gprs a wifi, il tuo sito vedrà un cambiamento ip, anche se non ho nemmeno bisogno del riavvio del mio browser.

    
risposta data 14.05.2014 - 13:42
fonte
1

The idea is that it would be hard for an attacker to steal the cookie AND the ip address AND the user agent AND to keep the session refreshing,

Volevo solo notare che molti attacchi hanno luogo localmente, con la conseguenza che l'attaccante probabilmente condivide lo stesso indirizzo IP. Se riesci a ottenere la chiave di sessione, puoi anche ottenere l'agente utente del browser.

    
risposta data 14.05.2014 - 15:50
fonte
1

Per decidere se questo è un approccio valido o meno, devi considerare il caso d'uso dell'applicazione e quale attacco stai cercando di proteggere contro i tuoi utenti.

In questo caso, lo scenario di attacco al quale stai cercando di proteggere il tuo utente è rubare il cookie di sessione e riutilizzarlo da un altro computer. La conseguenza della difesa che stai proponendo è che è necessario che gli utenti effettuino di nuovo l'accesso ogni volta che cambiano gli indirizzi IP.

Valutare se i vantaggi della soluzione valgono o meno gli inconvenienti che crea dipende molto dal contesto. Ad esempio, se i dati dell'applicazione sono di alto valore e vengono generalmente utilizzati per un periodo di tempo limitato tra cui si desidera che gli utenti effettuino l'autenticazione ogni volta (ad esempio un'interfaccia web banking), il compromesso sembra perfettamente accettabile.

Se, al contrario, accedi a dati di basso valore e desideri ridurre al minimo l'impatto sugli utenti (ad esempio un carrello web del sito di acquisti), probabilmente sarebbe meglio non limitare la sessione al stesso indirizzo IP.

    
risposta data 14.05.2014 - 16:07
fonte

Leggi altre domande sui tag