Каков наилучший способ предотвратить угон сеанса? - PullRequest
118 голосов
/ 22 августа 2008

В частности, это касается использования файла cookie клиентского сеанса для идентификации сеанса на сервере.

Является ли лучшим ответом использование шифрования SSL / HTTPS для всего веб-сайта, и у вас есть лучшая гарантия того, что ни один из атакующих в середине не сможет прослушать существующий файл cookie сеанса клиента?

И, возможно, лучше всего использовать какое-либо шифрование для самого значения сеанса, которое хранится в вашем файле cookie сеанса?

Если злонамеренный пользователь имеет физический доступ к машине, он все равно может посмотреть на файловую систему, чтобы получить действительный файл cookie сеанса и использовать его для кражи сеанса?

Ответы [ 12 ]

123 голосов
/ 22 августа 2008

Шифрование значения сеанса будет иметь нулевой эффект. Сеансовый cookie уже является произвольным значением, шифрование его просто создаст другое произвольное значение, которое можно прослушать.

Единственное реальное решение - HTTPS. Если вы не хотите использовать SSL на всем сайте (возможно, у вас есть проблемы с производительностью), вы можете обойтись только с помощью SSL, защищающего конфиденциальные области. Для этого сначала убедитесь, что ваша страница входа в систему HTTPS. Когда пользователь входит в систему, установите безопасный cookie (то есть браузер будет передавать его только по ссылке SSL) в дополнение к обычному cookie сеанса. Затем, когда пользователь посещает одну из ваших «конфиденциальных» областей, перенаправьте их на HTTPS и проверьте наличие этого безопасного cookie. Это будет у реального пользователя, у угонщика сессии - нет.

РЕДАКТИРОВАТЬ : Этот ответ был изначально написан в 2008 году. Сейчас 2016, и нет никаких причин не использовать SSL на всем вашем сайте. Нет больше открытого текста HTTP!

41 голосов
/ 23 августа 2008

SSL помогает только при атаках со стороны. Если у злоумышленника есть доступ к вашему компьютеру, я предполагаю, что он также может скопировать ваш безопасный cookie.

Как минимум, убедитесь, что старые куки через некоторое время теряют свою ценность. Даже успешная атака хиджаком будет остановлена, когда куки перестанет работать. Если у пользователя есть файл cookie из сеанса, который вошел в систему более месяца назад, заставьте его повторно ввести свой пароль. Удостоверьтесь, что всякий раз, когда пользователь нажимает на ссылку «выйти из системы» на вашем сайте, старый UUID сеанса больше никогда не будет использоваться.

Я не уверен, сработает ли эта идея, но здесь идет речь: Добавьте серийный номер в файл cookie вашего сеанса, возможно, строку, подобную этой:

SessionUUID, серийный номер, текущая дата / время

Зашифруйте эту строку и используйте ее в качестве файла cookie сеанса. Регулярно меняйте серийный номер - возможно, когда cookie-файлу 5 минут, а затем переиздайте cookie-файл. Вы можете даже переиздать его на каждом просмотре страницы, если хотите. На стороне сервера сохраняйте запись последнего серийного номера, который вы выпустили для этого сеанса. Если кто-то отправляет файл cookie с неправильным серийным номером, это означает, что злоумышленник может использовать файл cookie, который он перехватил ранее, поэтому аннулируйте UUID сеанса и попросите пользователя повторно ввести свой пароль, а затем повторно введите новый файл cookie.

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

21 голосов
/ 04 июля 2011

Рассматривали ли вы чтение книги по безопасности PHP? Настоятельно рекомендуется.

У меня был большой успех при использовании следующего метода для сайтов, не сертифицированных по SSL.

  1. Отключить несколько сеансов под одной учетной записью, убедившись, что вы проверяете это не только по IP-адресу. Скорее проверьте по токену, сгенерированному при входе в систему, который хранится вместе с сеансом пользователя в базе данных, а также по IP-адресу, HTTP_USER_AGENT и т. Д.

  2. Использование гиперссылок на основе отношений Создает ссылку (например, http://example.com/secure.php?token=2349df98sdf98a9asdf8fas98df8) К ссылке добавляется строка MD5 со случайным солью x-BYTE (предпочтительный размер), при перенаправлении страницы случайно сгенерированный токен соответствует запрашиваемой странице.

    • После перезагрузки выполняется несколько проверок.
    • Исходящий IP-адрес
    • HTTP_USER_AGENT
    • Токен сессии
    • вы получите точку.
  3. Файл cookie аутентификации сеанса Short Life-span. как было сказано выше, хорошей идеей является файл cookie, содержащий защищенную строку, которая является одной из прямых ссылок на достоверность сеансов. Сделайте так, чтобы срок действия истекал каждые x минут, переиздав этот токен и повторно синхронизировав сеанс с новыми данными. Если какие-либо несоответствия в данных, либо выйдите из системы, либо попросите их повторно аутентифицировать свой сеанс.

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

20 голосов
/ 04 декабря 2013
// 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.
}

Это захватывает «контекстную» информацию о сеансе пользователя, фрагменты информации, которая не должна изменяться в течение жизни одного сеанса. Пользователь не будет одновременно за компьютером в США и в Китае, верно? Таким образом, если IP-адрес внезапно изменяется в одном и том же сеансе, что влечет за собой попытку перехвата сеанса, вы защищаете сеанс, заканчивая сеанс и заставляя пользователя выполнить повторную аутентификацию. Это препятствует попытке взлома, злоумышленник также вынужден войти в систему вместо получения доступа к сеансу. Оповестите пользователя о попытке (слегка подправьте его), и vola, Слегка раздраженный + информированный пользователь, и его сеанс / информация защищены.

Мы добавляем User Agent и X-FORWARDED-FOR, чтобы сделать все возможное для захвата уникальности сеанса для систем за прокси / сетями. Вы можете использовать больше информации, не стесняйтесь быть креативным.

Это не 100%, но это чертовски эффективно.

Существует еще многое, что вы можете сделать для защиты сеансов, истечения срока их действия, когда пользователь покидает веб-сайт и возвращается, возможно, заставит его снова войти в систему. Вы можете обнаружить, что пользователь покидает и возвращается, захватив пустой HTTP_REFERER (домен был введен в строке URL), или проверьте, соответствует ли значение в HTTP_REFERER вашему домену или нет (пользователь щелкнул внешнюю / созданную ссылку, чтобы перейти к вашему сайт).

Срок действия сессий, не позволяйте им оставаться в силе бесконечно.

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

9 голосов
/ 24 ноября 2008

Попробуйте протокол Secure Cookie, описанный в этой статье Лю, Ковача, Хуана и Гауды:

Как указано в документе:

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

Что касается простоты развертывания:

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

Короче говоря: он безопасный, легкий, отлично работает для меня.

8 голосов
/ 01 ноября 2013

Нет способа предотвратить перехват сеанса на 100%, но при некотором подходе мы можем сократить время, в течение которого злоумышленник может перехватить сеанс.

Способ предотвращения перехвата сеанса:

1 - всегда использовать сеанс с ssl-сертификатом;

2 - отправлять сеансовый cookie только с установленным значением trueponly (запретить JavaScript доступ к сеансовому cookie)

2 - использовать идентификатор регенерации сеанса при входе в систему и выходе из системы (примечание: не используйте регенерацию сеанса при каждом запросе, потому что если у вас есть последовательный запрос ajax, у вас есть шанс создать несколько сеансов.)

3 - установить время ожидания сеанса

4 - хранить пользовательский агент браузера в переменной $ _SESSION и сравнивать с $ _SERVER ['HTTP_USER_AGENT'] при каждом запросе

5 - установить токен cookie и установить время истечения срока действия этого куки до 0 (пока браузер не закроется). Регенерируйте значение cookie для каждого запроса. (Для ajax-запроса не создавайте заново токен cookie). 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');
    }

примечание: не восстанавливать cookie-токен с помощью запроса ajax примечание: приведенный выше код является примером. примечание: если пользователи выходят из системы, токен cookie должен быть уничтожен так же, как и сеанс

6 - нецелесообразно использовать ip пользователя для предотвращения перехвата сеанса, поскольку некоторые пользователи меняют ip с каждым запросом. ЭТО ВЛИЯЕТ НА ДЕЙСТВИТЕЛЬНЫХ ПОЛЬЗОВАТЕЛЕЙ

7 - лично я храню данные сеанса в базе данных, вам решать, какой метод вы выберете

Если вы обнаружите ошибку в моем подходе, пожалуйста, исправьте меня. Если у вас есть больше способов предотвратить сессионный хиджак, сообщите мне.

4 голосов
/ 23 августа 2008

Убедитесь, что вы не используете приращения целых чисел для идентификаторов сеансов. Гораздо лучше использовать GUID или другую длинную произвольно генерируемую строку символов.

3 голосов
/ 17 августа 2015

Существует много способов создать защиту от перехвата сеанса, однако все они либо снижают удовлетворенность пользователей, либо не являются безопасными.

  • Проверка IP и / или X-FORWARDED-FOR. Они работают и довольно безопасны ... но представьте боль пользователей. Они приходят в офис с WiFi, получают новый IP-адрес и теряют сеанс. Нужно войти снова.

  • Проверки агента пользователя. То же, что и выше, новая версия браузера вышла, и вы теряете сеанс. Кроме того, их действительно легко взломать. Хакерам легко отправлять поддельные строки UA.

  • токен localStorage. При входе в систему сгенерируйте токен, сохраните его в хранилище браузера и сохраните в зашифрованном файле cookie (зашифрованном на стороне сервера). Это не имеет побочных эффектов для пользователя (localStorage сохраняется при обновлении браузера). Это не так безопасно, как просто безопасность через неизвестность. Кроме того, вы можете добавить некоторую логику (шифрование / дешифрование) в JS, чтобы еще больше ее скрыть.

  • Переиздание печенья. Это, вероятно, правильный способ сделать это. Хитрость заключается в том, чтобы позволить только одному клиенту использовать cookie одновременно. Таким образом, активный пользователь будет переиздавать cookie каждый час или реже. Старый файл cookie становится недействительным, если выдается новый файл. Взломы все еще возможны, но сделать это гораздо сложнее - либо хакер, либо действительный пользователь получит отказ в доступе.

1 голос
/ 10 февраля 2018

AFAIK объект сеанса недоступен на клиенте, так как он хранится на веб-сервере. Однако идентификатор сеанса сохраняется в виде файла cookie, и он позволяет веб-серверу отслеживать сеанс пользователя.

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

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

Ниже приведен код, который я реализовал и протестировал путем копирования идентификатора сеанса из одного сеанса в другой. Это работает довольно хорошо. Если есть лазейка, дайте мне знать, как вы ее симулировали.

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

Я использовал алгоритм SHA-2 для хэширования значения, используя пример, приведенный в SHA-256 Хеширование в baeldung

Ждем ваших комментариев.

1 голос
/ 14 февраля 2014

Давайте рассмотрим, что на этапе входа в систему клиент и сервер могут договориться о секретном солт-значении. После этого сервер предоставляет значение счетчика с каждым обновлением и ожидает, что клиент ответит хешем (секретная соль + счетчик). Потенциальный угонщик не имеет никакого способа получить это секретное значение соли и, следовательно, не может генерировать следующий хеш.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...