В настоящий момент ни одно серьёзное Web-приложение не
обходится без использования механизма сессий. Наиболее распрастранено
использование сессий для разграничения доступа пользователей к личным ресурсам.
Рассмотрим типичный процесс авторизации с использованием сессии.
У пользователя запрашивается логин и пароль.
Если авторизация
проходит успешно, то создается новая сессия, со значением "успешной
авторизации".
Пользователю назначается уникальный идентификатор (SID),
который заранее невозможно предсказать, а, значит, и подобрать :).
SID
записывается либо в cookies браузера, либо передается через адресную строку
браузера (если cookies отключены).
В результате успешной авторизации
скрипту становится доступными значения переменных из суперглобального массива
$_SESSION, по наличию которых скрипт предоставляет доступ к некоторому ресурсу,
например, вход на панель администрирования сайта.
Проблема заключается в
том, что если злоумышленник каким-либо образом узнает SID другого пользователя,
он сможет подставить его в свои cookies, или адресную строку браузера и войти на
сайт с правами данного пользователя. Замечание
Цитата:
Несколько лет назад имело место несколько скандалов, когда в
системах удалённого управления банковским счётом уникальный номер (SID)
генерировался просто прибавлением единицы к последнему использованному значению.
Быстрая авторизация приводила к выдачи двух значений SID, допустим 40346 и
40348. Подстановка номера 40347 позволяла получить доступ к чужому счёту
:).
В настоящее время SID
представляет уникальную последовательность цифр и букв, не привязанную к
счётчику. Но как же злоумышленик узнает чужой SID?
Существуют два самых
распространенных варианта:
1. Например, владелец сессии сам показал ее,
неосторожно оставив ссылку такого типа где-нибудь на форуме или гостевой книге.
Переход по этому адресу, автоматически наделяет
злоумышленника правами пользователя для которого выделена сессия с
идентификатором 01c1739de76ed46e639cd23d33698121. Конечно, сессия
пользователя уничтожается при отсутствии активности через некоторое время. И
поэтому злоумышленнику следует поторопиться :). С другой стороны тотальная
распространённость пауков (спайдеров) позволяет организовать целеноправленный
автоматический поиск таких ссылок.
2. Если даже сессия не указана явно в
строке браузера, а хранится в Куках. У злоумышленика все равно есть возможность
завладеть идентификатором. Рассмотрим небольшой скрипт простейшей гостевой
книги.
Содержимое обработчика
addmsg.php представлено ниже
Код:
<?php if(!empty($_POST['text'])) { $line =
str_replace("/ ? /s", " ", $_POST['text']); //запись в базу или в
файл } else { exit("Ошибка"); } ?>
Обратите внимание - в скрипте
явно пропущен вызов функции htmlspecialchars(), которая преобразует символы <
в < и > в > в результате чего, злоумышленник может вставить в
текст любые HTML-теги и скрипты JavaScript.
И
что мы получаем? Маленькая оплошность (казалось бы пропустили всего лишь
какой-то htmlspecialchars() перед выводом сообщения в браузер), которая
позволяет загружать в новом окне страницу злоумышленика, передавая ей значения
из cookies. Для борьбы с уязвимостями такого рода лучше всего бороться
"устойчивыми" методами, действуя по принципу "всё что не разрешено - запрещено".
Не следует скрывать SID и подвергать текст многоэтапным проверкам - вероятность
создания ошибок в этом случае только возрастает. Более надёжным в этом случае
является метод привязки SID к IP-адресу, пользователя владеющего сессией. Такой
способ широко распространен во многих известных форумах, например phpBB.
Скрипт авторизации
Код:
<?php if (логин и пароль верные) {
$_SESSION['authorized'] = true; $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
} ?>
Тогда скрипт,
который предоставляет доступ к определенному ресурсу, может содержать следующий
код
Код:
<?php if (!empty($_SESSION['authorized']) &&
$_SESSION['ip'] == $_SERVER['REMOTE_ADDR']) { //
Доступ к ресурсу открыт. } else die("Доступ закрыт.");
?>
Т.е. теперь с данной
сессией может работать только тот пользователь, IP-адрес которого совпадает с
IP-адресом, переданным серверу при авторизации. Если злоумышленик перехватит
сессию, IP-адрес то у него другой :) - поэтому в доступе ему будет отказано.
Данный метод не является универсальным и у него тоже есть слабые места.
Если пользователь и злоумышленик выходят в Интернет через общий
прокси-сервер, то они будут иметь один общий IP-адрес (это характерно для сетей
университетов, заводов и других крупных учреждений), т.е. каждый может украсть
SID соседа, хотя бы вышеуказанными методами.
Если пользователь
использует модем, и произойдет обрыв связи, то после восстановления связи, ему
скорее всего будет назначен другой IP-адрес. Пользователь может быть неприятно
удивлён, если он будет огульно зачислен в ряды злоумышленников (поэтому писать
угрозы и призывы к совести в системах защиты не стоит - в таких системах тоже
бывают ошибки). Последний недостаток имеет место на форумах, посетители которых
имеют привычку при наборе длинного ответа отключать Интернет и работать offline.
Нажатие на кнопку "Ответить" приводит к тому, что вся набраная информация
теряется, так как никто не заботится о том, что бы сохранять текст набранный
злоумышлеником :))).
Выход: (вернее полу выход) Проверять на
идентичность только первые 3 цифры IP адреса, кража SID по-прежднему
статистически маловероятна, однако это в большинстве случаев, позволяет более
мягко отнестись к разрыву соединения, так как провайдерам обычно выделяют
неразрывный диапазон IP-адресов, в котором меняется только последняя цифра.