Как лучше всего предотвратить захват сеанса?

124

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

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

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

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

Адам
источник

Ответы:

140

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

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

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

Джош Хинман
источник
28
HTTPS предотвратит только сниффинг. Но если у вас есть XSS, или идентификаторы сеансов можно легко угадать, или вы уязвимы для фиксации сеанса, или ваше хранилище идентификаторов сеансов слабое (SQL-инъекция?), SSL вообще не будет улучшением.
Calimo
5
@Josh Если злоумышленник имеет физический доступ к машине, он все равно может посмотреть в файловую систему, чтобы получить действительный файл cookie сеанса и использовать его для взлома сеанса?
Pacerier
72
Если злоумышленник имеет физический доступ к файловой системе, ему не нужно захватывать сеанс.
Джош Хинман
25
@Josh. Неправда, иногда пользователь имеет ограниченный по времени физический доступ к файловой системе. Представьте себе ноутбук, оставленный разблокированным коллегой, спешащим в туалет, теперь все, что мне нужно сделать, это подойти к этому ноутбуку, установить плагин EditThisCookie, получить его файлы cookie на plus.google.com с помощью функции экспорта EditThisCookie, и теперь у меня есть его аккаунт . Затраченное время: 18 секунд.
Pacerier
1
Я почти уверен, что у Google будет какая-то встроенная функция безопасности, поскольку это, очевидно, первое, о чем вы думаете, когда говорите о захвате сеанса
xorinzor
42

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

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

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

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

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

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


источник
Я знаю, что это старый пост, но просто хотел добавить, что если бы злоумышленник захватил сеанс в окне, выделенном «серийным номером», то это не повлияло бы на него.
Crush
@crush, но тогда злоумышленник будет заблокирован после отведенного окна, верно? Так что, по крайней мере, окно атаки небольшое (э-э).
Johanneke
2
Проблема только в том, что если пользователь покидает ваш сайт на 5 минут, ему придется снова войти в систему
elipoultorak
21

Вы думали о том, чтобы прочитать книгу по безопасности 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 аутентификации сеанса с коротким сроком службы. как указано выше, рекомендуется использовать файл cookie, содержащий защищенную строку, которая является одной из прямых ссылок на действительность сеанса. Сделайте так, чтобы срок его действия истекал каждые x минут, повторно выпуская этот токен и повторно синхронизируя сеанс с новыми данными. Если какие-либо несоответствия в данных, либо выйдите из системы, либо попросите его повторно аутентифицировать свой сеанс.

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

Натан
источник
4
Какие книги вы бы порекомендовали?
Rikki
1
Особенно учитывая, что OP ничего конкретно не говорит о PHP, я бы сказал, что лучше взглянуть только на общую книгу по безопасности (тем более, что безопасность между разными языками отличается только деталями реализации, но концепции остаются теми же).
matts1
в 2017 году даже facebook / gmail и т. д. разрешает несколько сеансов под одной и той же учетной записью (особенно с мобильными устройствами), если вы не ненавидите своих пользователей, № 1 немного устарел.
Cowbert
20
// 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-адрес внезапно изменяется в рамках одного сеанса, что явно подразумевает попытку перехвата сеанса, вы защищаете сеанс, завершив сеанс и заставив пользователя повторно пройти аутентификацию. Это предотвращает попытку взлома, злоумышленник также вынужден войти в систему вместо получения доступа к сеансу. Сообщите пользователю о попытке (немного увеличьте его с помощью ajax), и vola, Слегка раздраженный + информированный пользователь, и его сеанс / информация защищены.

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

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

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

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

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

theironyis
источник
3
Раньше я сталкивался с ситуацией, когда определенный (довольно крупный, но технически отсталый) интернет-провайдер время от времени менял IP-адрес браузера пользователя на основе перенаправления соединений своих пользователей. Это заставило проверку REMOTE_ADDR возвращать нам ложноотрицательные результаты.
goofballLogic
Зачем вообще создавать хеш? $_SESSION['ident'] = $aip . $bip . $agent;будет так же безопасно.
Дэн Брэй
2
Если у вас есть мобильные пользователи, использующие ваш веб-сайт на ходу и переходящие с одной точки доступа на другую, их IP-адреса будут постоянно меняться, и они будут продолжать выходить из своей учетной записи.
Карим
А как насчет прокси и VPN? Любой, кто использует прокси TOR, будет постоянно выходить из своих учетных записей… фактически каждые несколько минут.
Брэдли
Даже если вы упустите это из виду, клиент может манипулировать IP-адресами, поэтому в любом случае это не поможет отговорить злоумышленника.
Брэдли
9

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

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

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

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

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

Вкратце: он безопасный, легкий, у меня работает просто отлично.

Хьюберт
источник
9
Ваша ссылка является спецификацией протокола - у вас есть ссылка на реализацию? Было бы здорово - спасибо.
Адам,
9

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

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

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

2 - отправлять cookie сеанса только с httponly, установленным в true (запретить javascript доступ к cookie сеанса)

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

3 - установить тайм-аут сеанса

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

5 - установите токен cookie и установите время истечения срока действия этого 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 - лично я храню данные сеанса в базе данных, выбор метода зависит от вас.

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

Александр
источник
привет, я пытаюсь предотвратить захват сеанса (в ASP.NET) и рассмотрел все предложенные вами шаги. Это примерно работает, но когда я использую режим браузера InPrivateBrowsing / инкогнито, сеанс захвачен. Не могли бы вы предложить какие-либо дополнительные вещи для добавления в строку sessionId?
Вишванат Мишра
4

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

Kibbee
источник
3

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

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

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

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

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

штриховка
источник
1

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

davej
источник
3
Но как вы хотите хранить эту соль на стороне клиента, чтобы ее никто не мог украсть?
Dcortez
1

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.

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

Jzf
источник
@zaph Извините, но я не добавил ответ, чтобы набрать репутацию. Дело и не в шифровании SHA-2. Но тот факт, что я смог обнаружить использование идентификатора сеанса другого пользователя Cookie в сеансе другого пользователя, то есть захват сеанса, как в исходном вопросе. Я протестировал свое решение и обнаружил, что оно работает. Но я не эксперт в этом вопросе, поэтому я хотел бы, чтобы сообщество проверило, достаточно ли хорош мой ответ. Может быть, вы увидите, что делает мой фрагмент кода, и решите, отвечает ли он на вопрос. Спасибо!
Jzf
@zaph Спасибо, что указали на ошибку. Я обновил свой ответ согласно вашему предложению. Удалите свой голос "против", если считаете, что ответ полезен.
Jzf
0

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

Проверка заголовков реферера также может быть вариантом, но их легче подделать.

Хулио Сезар
источник
7
нет, вы не можете использовать исходный IP-адрес, так как он может измениться - либо через динамические IP-адреса, изменяемые при временном отключении пользователя, либо посредством (неявного или явного) использования прокси-фермы. Кроме того, угонщики сеанса, приходящие от одного и того же провайдера, могут использовать тот же прокси и IP-адрес, что и законный пользователь ...
Олаф Кок
1
У PHP-Nuke есть хорошая страница об их подходе к сеансу, и они подробно рассказывают о том, как подключение его к IP не работает со всеми интернет-провайдерами phpnuke.org/…
Sembiance
4
Смена IP-адресов - обычное дело для мобильных интернет-провайдеров. С Vodafone мой IP меняется при КАЖДОМ запросе.
Blaise
1
В некотором роде старый пост, но в продолжение этого. IP, как уже упоминалось, плохая идея. Как уже упоминалось, мобильные пользователи обычно перемещаются по IP-адресам. У некоторых интернет-провайдеров в прошлом также были роуминговые IP-адреса (например, AOL), однако этот подход становится все более популярным сейчас из-за нехватки IP-адресов IPv4. К таким интернет-провайдерам относятся Plus net и BT
Питер,
-15

Защищать:

$ip=$_SERVER['REMOTE_ADDER'];
$_SESSEION['ip']=$ip;
Нима
источник
12
Я не понимаю, что вы здесь делаете.
samayo