Пользователи сессий / файлов cookie периодически выходят из системы - PullRequest
0 голосов
/ 25 мая 2019

Мои пользователи вышли из моего сайта. Это происходит, когда кто-то входит в систему с другого устройства. Я заглянул в него и заметил, что кто-то с удаленного IP-адреса смог войти на мой сайт как разные пользователи.

Я не знаю, намеренно ли я являюсь целью или это какая-то ошибка в моем коде. Я хотел бы знать, как правильно настроить сеансовые куки-файлы безопасным способом, чтобы этого не происходило.

  1. Мои файлы cookie - только HTTP

  2. Я также не верю, что это атака «человек посередине», поскольку несколько пользователей из разных областей выходят из системы . Мой сайт защищен SSL.

  3. Я не верю, что это атака грубой силой. Иногда, когда я вхожу, в течение 30 секунд, я снова выхожу из системы , а удаленный IP-адрес регистрируется.

  4. Я не верю, что у него есть доступ к каким-либо паролям. Все хешируется в базе данных , и единственное, что хранится на клиенте, это HTTP-токен сеанса HTTP ONLY.

Я очень застрял.

Вот мой скрипт входа в систему , который проверяет учетные данные пользователя и устанавливает сеанс:

//database connection is $db_connect

//Creates a random String
function generateRandomString() {
    $length = rand(25, 30);
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

//Grab email, password, IP address
$email_attempt=strtoupper(preg_replace('#[^a-z0-9\.\@\_\-\+]#i', '', $_POST['e']));
$password_attempt=$_POST["p"];
$user_IP = preg_replace('#[^0-9.\:]#', '', getenv('REMOTE_ADDR'));


//Call the database
$sql = "SELECT password, userID FROM user_data WHERE email='$email_attempt' LIMIT 1";
$query = mysqli_query($db_connect, $sql);
if(mysqli_num_rows($query)>0)
{

    //Get the ID and hashed password from database
    while($row = $query->fetch_assoc()) {
        $password_db=$row["password"];
        $userID_db=$row["userID"];
    }


    //Verify Login using password verify
    if(password_verify($password_attempt, $password_db)==true){

        //remove any previous sessions for the user
        $sql = "DELETE FROM user_sessions WHERE userID='$userID_db'";
        $query = mysqli_query($db_connect, $sql);


        //Clear any current cookies from client
        if(isset($_COOKIE["user"]) && isset($_COOKIE["token"])) {
            setcookie("user", '', strtotime( '-5 days' ), '/');
            setcookie("token", '', strtotime( '-5 days' ), '/');
        }
        session_destroy();


        // Set Session data to an empty array
        $_SESSION = array();


        //create a new token, set new session and cookies 
        $token=generateRandomString();
        $_SESSION['user'] = $userID_db;
        $_SESSION['token'] = $token;
        setcookie("user", $userID_db, strtotime( '+3 days' ), "/", "", "", TRUE);
        setcookie("token", $token, strtotime( '+3 days' ), "/", "", "", TRUE);


        //Hash the token to store in the database
        $token_hash=password_hash($token, PASSWORD_DEFAULT);

        //Store session into database
        $sql = "INSERT INTO user_sessions 
            (userID, session_token, IP, loginDate) 
            VALUES 
            ('$userID_db','$token_hash','$user_IP', '$current_date')";

        $query = mysqli_query($db_connect, $sql);

        header("Location: dashboard.php");
    }

    else
    {
        echo 'wrong_credentials';
    }
}

Вот мой код, чтобы оценить пользователя и посмотреть, вошли ли они в систему, изучив сеанс и файлы cookie;

//start session
session_start();

$user_ok = false;
$clientID = "";
$token = "";
$user_IP = preg_replace('#[^0-9.\:]#', '', getenv('REMOTE_ADDR'));

if(isset($_SESSION["user"]) && isset($_SESSION["token"])) {
    //Get session
    $clientID = preg_replace('#[^a-z0-9]#i', '', $_SESSION['user']);
    $token = preg_replace('#[^a-z0-9]#i', '', $_SESSION['token']);


    // Verify the user with session data
    $user_ok = checkUser($db_connect,$clientID,$token,$user_IP);



} else if(isset($_COOKIE["user"]) && isset($_COOKIE["token"])){

    //Set session from cookie
    $_SESSION['user'] = preg_replace('#[^a-z0-9]#i', '', $_COOKIE['user']);
    $_SESSION['token'] = preg_replace('#[^a-z0-9]#i', '', $_COOKIE['token']);


    //Get session data
    $clientID =  preg_replace('#[^a-z0-9]#i', '', $_SESSION['user']);;
    $token =  preg_replace('#[^a-z0-9]#i', '', $_SESSION['token']);

    // Verify the user
    $user_ok = checkUser($db_connect,$clientID,$token,$user_IP);
} 




// User Verify function
function checkUser($db_connect,$user,$token,$ip){

    //Grab the session
    $sql = "SELECT session_token FROM user_sessions WHERE userID='$user' AND ip='$ip' LIMIT 1";
    $query = mysqli_query($db_connect, $sql);
    if(mysqli_num_rows($query)>0){

        $row=mysqli_fetch_row($query);

        $token_hashed=$row[0];

        //compare token given and hashed token
        if(password_verify($token,$token_hashed)==true)
        {
            return true;
        }

        else
        {
            return false;
        }
    } 

    else
    {
        return false;
    }
}

Итак, мой вопрос: достаточно ли безопасен этот код?

Как я могу быть более безопасным?

Также, если у вас есть представление о том, что происходит в этой головоломке, пожалуйста, дайте мне знать, так как я получаю уничтожено . Заранее спасибо.

1 Ответ

1 голос
/ 25 мая 2019

После некоторых копаний я понял, что проблема заключается в попытке привязать сеанс к одному IP-адресу.

У нас работает CloudFlare, поэтому getenv('REMOTE_ADDR') иногда возвращает IP-адрес CloudFlare вместо этогоклиентского IP-адреса.Это приводило к выходу из системы.

Но я думал, что смогу ответить на свой вопрос, основываясь на комментариях.Чтобы сделать сценарий более безопасным и прекратить периодический выход из системы, я должен:

  1. Всегда использовать подготовленные операторы для защиты от внедрения SQL
  2. Непривязать сеансы к IP-адресам , потому что они могут измениться (особенно если на мобильном телефоне)

Бритва Оккама - это принцип решения проблем, который, по сути, утверждает, что более простые решения с большей вероятностью будут правильнымичем сложные.

...