Фиксация сессий PHP / угон - PullRequest
       30

Фиксация сессий PHP / угон

144 голосов
/ 22 февраля 2011

Я пытаюсь понять больше о PHP Фиксация сессии & угон и как предотвратить эти проблемы. Я читал следующие две статьи на сайте Криса Шифлетта:

Однако я не уверен, что правильно понимаю вещи.

Чтобы помочь предотвратить фиксацию сеанса, достаточно вызвать session_regenerate_id (true); после успешного входа в систему? Мне кажется, я правильно понимаю.

Он также говорит об использовании токенов, передаваемых в URL через $ _GET, для предотвращения перехвата сеанса. Как бы это было сделано? Я предполагаю, что когда кто-то входит в систему, вы генерируете свой токен и сохраняете его в переменной сеанса, а затем на каждой странице вы сравниваете эту переменную сеанса со значением переменной $ _GET?

Нужно ли менять этот токен только один раз за сеанс или при каждой загрузке страницы?

Также это хороший способ предотвратить угон без необходимости передавать значение в URL-адресах? это было бы намного проще.

Ответы [ 5 ]

212 голосов
/ 22 февраля 2011

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

Фиксация сеанса

Здесь злоумышленник явно устанавливает идентификатор сеанса сеанса для пользователя.Как правило, в PHP это делается с помощью URL-адреса типа http://www.example.com/index...?session_name=sessionid.После того, как злоумышленник передаст URL-адрес клиенту, атака аналогична атаке захвата сеанса.

Существует несколько способов предотвратить фиксацию сеанса (сделать все из них):

  • Установите session.use_trans_sid = 0 в вашем файле php.ini.Это скажет PHP не включать идентификатор в URL и не читать URL для идентификаторов.

  • Установить session.use_only_cookies = 1 в вашем файле php.ini,Это скажет PHP никогда не использовать URL с идентификаторами сеанса.

  • Регенерация идентификатора сеанса каждый раз, когда изменяется статус сеанса.Это означает любое из следующего:

    • Аутентификация пользователя
    • Хранение конфиденциальной информации в сеансе
    • Изменение чего-либо в сеансе
    • и т. Д..

Перехват сеанса

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

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

  • Используйте сильный идентификатор хеша сеанса: session.hash_function в php.ini.Если PHP <5.3, установите его <code>session.hash_function = 1 для SHA1.Если PHP> = 5.3, задайте для него session.hash_function = sha256 или session.hash_function = sha512.

  • Отправьте сильный хэш: session.hash_bits_per_character in php.ini.Установите для этого session.hash_bits_per_character = 5.Хотя это не делает взломать труднее , это имеет значение, когда атакующий пытается угадать идентификатор сеанса.Идентификатор будет короче, но будет содержать больше символов.

  • Установите дополнительную энтропию с помощью session.entropy_file и session.entropy_length в вашем php.ini файл.Установите для первого значение session.entropy_file = /dev/urandom, а для второго - количество байтов, которые будут считаны из файла энтропии, например session.entropy_length = 256.

  • Измените имя сеанса с PHPSESSID по умолчанию.Это достигается путем вызова session_name() с вашим собственным идентификатором в качестве первого параметра перед вызовом session_start.

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

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

  • Включите пользовательский агент из$_SERVER['HTTP_USER_AGENT'] в сессии.Обычно, когда начинается сеанс, сохраняйте его как $_SESSION['user_agent'].Затем при каждом последующем запросе проверяйте, соответствует ли он.Обратите внимание, что это может быть подделано, так что это не на 100% надежно, но лучше, чем нет.

  • Включите IP-адрес пользователя из $_SERVER['REMOTE_ADDR'] в сеанс.Как правило, когда начинается сеанс, сохраните его как $_SESSION['remote_ip'].Это может быть проблематично для некоторых интернет-провайдеров, которые используют несколько IP-адресов для своих пользователей (например, AOL раньше).Но если вы используете его, это будет гораздо безопаснее.Для злоумышленника единственный способ подделать IP-адрес - это скомпрометировать сеть в какой-то момент между реальным пользователем и вами.И если они скомпрометируют сеть, они могут сделать намного хуже, чем угон (например, атаки MITM и т. Д.).

  • Включите токен в сеанс и на стороне браузера, который вы увеличиваете и часто сравниваете.Как правило, для каждого запроса выполняйте $_SESSION['counter']++ на стороне сервера.Также сделайте что-нибудь в JS на стороне браузера, чтобы сделать то же самое (используя локальное хранилище).Затем, когда вы отправляете запрос, просто возьмите одноразовый номер токена и убедитесь, что на сервере совпадает одноразовый номер.Сделав это, вы сможете обнаружить захваченный сеанс, поскольку у злоумышленника не будет точного счетчика, или, если он это сделает, у вас будет 2 системы, передающие одинаковое количество, и они могут сказать, что одна из них подделана.Это не будет работать для всех приложений, но является одним из способов борьбы с этой проблемой.

Примечание по двум

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

Регенерация идентификатора сеанса

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

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

Уничтожение сеанса

Если вы собираетесь уничтожить сеанс (например, при выходе из системы), обязательно полностью его уничтожите.Это включает в себя удаление куки.Использование session_destroy:

function destroySession() {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
    session_destroy();
}
37 голосов
/ 22 февраля 2011

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

  • В Фиксация сеанса Атака злоумышленник уже имеет доступ к действительному сеансу и пытается форсироватьжертва использует этот конкретный сеанс.

  • В перехват сеанса атака злоумышленник пытается получить идентификатор сеанса жертвы дляиспользуйте его / ее сеанс.

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

Общее правило защиты конфиденциальных данных с использованием HTTPS также применимо и в этом случае.,Кроме того, вы должны сделать следующее:

Чтобы предотвратить фиксацию сеанса атак, убедитесь, что:

  • идентификатор сеанса принимается только из файла cookie (установите session.use_only_cookies на true) и сделайте его только для HTTPS, если это возможно (установите session.cookie_secure на true);Вы можете сделать оба с session_set_cookie_params.

Чтобы предотвратить Session Hijacking атаки, убедитесь, что:

Чтобы предотвратить обе сеансовые атаки, убедитесь, что:

  • , чтобы принимать только сеансы, инициированные вашим приложением.Вы можете сделать это, сняв отпечатки пальцев в сеансе при инициации с конкретной клиентской информацией.Вы можете использовать User-Agent ID, но не использовать удаленный IP-адрес или любую другую информацию, которая может меняться между запросами.
  • для изменения идентификатора сеанса с помощью session_regenerate_id(true) после попытки аутентификации (true только в случае успеха) или смены привилегий и уничтожения старого сеанса.(Обязательно сохраните все изменения $_SESSION, используя session_write_close до , сгенерировав идентификатор, если вы хотите сохранить сеанс, связанный со старым идентификатором; в противном случае будет затронут только сеанс с новым идентификаторомэти изменения.)
  • , чтобы использовать правильную реализацию истечения сеанса (см. Как мне истечь сеанс PHP через 30 минут? ).
6 голосов
/ 22 февраля 2011

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

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

window 'A' loads first and gets nonce 'P'
window 'B' loads second and gets nonce 'Q'

Если у вас нет возможности отслеживать несколько окон, у вас будет только один одноразовый номер - это окно B /Q.Когда пользователь затем отправляет свой пост из окна A и передает его в nonce 'P', система отклонит сообщение как P != Q.

2 голосов
/ 22 февраля 2011

Я не читал статью Шифлетта, но, думаю, вы что-то не так поняли.

По умолчанию PHP передает маркер сеанса в URL всякий раз, когда клиент не принимает куки. В противном случае в наиболее распространенном случае токен сеанса сохраняется в виде файла cookie.

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

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

0 голосов
/ 22 февраля 2011

Да, вы можете предотвратить фиксацию сеанса, заново создав идентификатор сеанса при входе в систему.Таким образом, если злоумышленник не узнает значение cookie для нового сеанса, прошедшего проверку подлинности.Другой подход, который полностью останавливает проблему, установлен session.use_only_cookies=True в вашей конфигурации времени выполнения.Злоумышленник не может установить значение файла cookie в контексте другого домена.Фиксация сеанса основана на отправке значения cookie в виде GET или POST.

...