PHP session var достаточно для пользователя auth?

Сценарий:

  • После входа пользователя в систему установлена ​​переменная сеанса, подтверждающая их регистрацию.
  • В верхней части каждой страницы переменная сеанса входа подтверждена.
  • Если это не так, они загружаются.
  • Не используются постоянные файлы cookie, только session

Вопрос:

Является ли это достаточно сильной мерой безопасности самостоятельно или я должен

  • Задайте две переменные сеанса для проверки друг друга и/или
  • Реализация проверки базы данных/хэшей
  • ...

========

(Кстати, пока я изучал этот вопрос, эта вики является фантастическим чтением.)

Ответ 1

В сеансе достаточно хранить только пользовательский логин (или идентификатор пользователя).

Чтобы предотвратить фиксацию/захват сеанса, все, что вам нужно, это просто реализовать простой алгоритм (псевдокод):

if (!isset($_SESSION['hash']) {
    $_SESSION['hash'] = md5(!empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'no ua');
} else if ($_SESSION['hash'] != md5(!empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'no ua')) {
    session_regenerate_id();
    $_SESSION = array();
    $_SESSION['hash'] = md5(!empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'no ua');
}

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

Вот как я реализовал такую ​​защиту в классе сеанса kohana:

abstract class Session extends Kohana_Session
{
    public function read($id = null)
    {
        parent::read($id);

        $hash = $this->calculateHash();
        $sessionHash = $this->get('session_fixation');

        if (!$sessionHash) {
            $this->set('session_fixation', $hash);
        } elseif ($sessionHash != $hash) {
            $this->regenerate();
            $_SESSION = array();
            $this->set('session_fixation', $hash);
        }
    }

    private function calculateHash()
    {
        $ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1';
        $ua = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'no ua';
        $charset = !empty($_SERVER['HTTP_ACCEPT_CHARSET']) ? $_SERVER['HTTP_ACCEPT_CHARSET'] : 'no charset';
        $ip = substr($ip, 0, strrpos($ip, '.') - 1);
        return md5($ua . $ip . $charset);
    }
}

Ответ 2

Не пытайтесь написать свою собственную схему сеанса, PHP сделает это лучше.

да, вы можете добавить дополнительную информацию в свою $_SESSION, чтобы предотвратить захват сеанса

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

$_SESSION['fingerprint'] = md5('somethingSecret' . $_SERVER['HTTP_USER_AGENT']. session_id());

то вы должны проверить сеанс как

$check_print = md5('somethingSecret' . $_SERVER['HTTP_USER_AGENT']. session_id());

if($check_print != $_SESSION['fingerprint'] || $_SESSION['authenticated']){ 
    //invalid session
}

Ответ 3

Вы ничего не можете сделать, кроме использования HTTPS.

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

Если вы собираетесь заставить пользователя использовать единый UA на протяжении всей своей просьбы, это может помочь: вам не нужен какой-либо специальный бизнес хэширования, потому что вы хешируете его в $_SESSION, который ни один пользователь или угонщик могут получить доступ напрямую, так зачем беспокоиться о его хэшировании? Также можно просто сохранить $_SESSION["reportedUA"] = $_SERVER["HTTP_USER_AGENT"] при входе в систему, а затем проверить reportedUA на каждый запрос.

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

Что дальше? Айпи адрес? Захват сеанса может происходить из-за NAT, и в этом случае вы будете ввернуты. Ваши пользователи могут использовать dial-up, и в этом случае они завинчиваются.

У этой проблемы нет решения: нет способа. Не могло быть способа. Если хакер может видеть ваши сеансовые куки, то они могут вас повредить, потому что нет никакой дополнительной информации или проблем, связанных с чем-то, что только пользователь знает (то есть пароль), который отправляется с каждым запросом.

Единственный способ сделать сеанс безопасным - это защитить весь сеанс.

Ответ 4

По состоянию на 15 ноября два ответа, которые я получил, не затрагивают мой вопрос, который был

"Является ли это [единственной переменной сеанса] достаточно сильной мерой безопасности?"

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

1) Одной переменной сеанса недостаточно безопасности, поскольку сеанс может быть легко захвачен.

2) Так как это может произойти, сеанс не является действительно безопасным, но его можно сделать безопаснее с добавлением отпечатка пальца. Это гарантирует уникальную повторяющуюся проверку каждый раз, когда сессия требует проверки. @zerkms рекомендует хэш User-Agent и несколько других (см. его код).

3) Соление отпечатка пальца в основном бесполезно, поскольку оно затушевывает данные, но реплицируется на каждом клиентском компьютере, поэтому теряется его уникальность.

4) Решение базы данных бесполезно, так как это проблема на стороне клиента.

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

Чтение, которое помогло/смутило меня дальше:

Захват сеанса и PHP

Является ли HTTPS единственной защитой от захвата сеанса в открытой сети?

Ответ 5

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

Задайте две переменные сеанса для проверки eachother и/или
Реализовать проверку базы данных/хэшей

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

Как и многие люди, SSL является единственным способом предотвратить этот тип evesdropping.

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

Эй, как насчет этого:

Создайте единый GUID и произвольную соль и зашифруйте его с помощью общего пароля с помощью PHP - это отправляется как идентификатор сеанса или файл cookie.

Клиент получает файл cookie, расшифровывает его с помощью общего пароля с помощью javascript (есть много доступных утилит enc/dec)

Установите текущий файл cookie или идентификатор сеанса в GUID.

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

SSL кажется намного проще и безопаснее.

EDIT: Хорошо, это было сделано - nevermind; -)