×
Закрытие
×

Дополнительные материалы бесплатно предоставляются только зарегистрированным пользователям.

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

Для тех кто не зарегистрирован, можно это сделать на вкладке Регистрация.

  • Создаем сайт для работы в Интернете

    1. Причины создания пошаговой инструкции по разработке самописного сайта
    2. Тема создаваемого сайта
    3. В чем будет заключаться монетизация
    4. Функционал
    5. Этапы создания
    6. Текущее состояние создаваемого сайта

    Здравствуйте уважаемый посетитель!

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

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

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

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

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

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

Самописный сайт своими руками!

Текущее состояние создаваемого сайта

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

Где в дополнительных материалах можно бесплатно скачать исходные файлы сайта с таблицами MySQL.

Вы здесь: Главная → Сборник статей → Авторизация  → Повышаем уровень безопасности сессии с помощью HTTP-заголовка User-Agent


Автор: / Дата:

Повышаем уровень безопасности сессии с помощью HTTP-заголовка User-Agent

Здравствуйте уважаемый посетитель!

В предыдущей статье мы создали систему авторизации пользователей с применением определенных мер по защите конфиденциальности сессии. Где использовали следующие методы защиты:

  • запрет доступа через скриптовые языки (JavaScript) к cookies, хранящим идентификатор сессии и одноразовый ключ;
  • установку определенного времени жизни, как для сессии, так и для относящихся к ней cookies;
  • настройку PHP на работы только с сессиями из cookies;
  • использование одноразового ключа, предназначенного для дополнительной проверки подлинности пользователя;

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

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

Поэтому при рассмотрении авторизации уделим вопросу безопасности сессий отдельное внимание. И в дальнейшем рассмотрим еще ряд мер, направленных на повышение уровня безопасности сессий, таких как:

  • проверку подлинности пользователя по HTTP-заголовку User-Agent;
  • привязку по IP-адресу.

Кроме того, рассмотрим также некоторые варианты дополнений к работе механизма удаления устаревших сессий. Так как стандартное решение по удалению сессий из хранилища, так называемым "сборщиком мусора", имеет определенные недостатки (рассматривалось в предыдущей статье). И посмотрим, как можно изменить его работу, используя для этого:

  • временные метки сессий через переменную $_SESSION;
  • отдельный скрипт, который проверяет время последней сборки мусора и удаляет сессии с истекшим сроком жизни.

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

Содержание


  • Привязка пользователя к HTTP-заголовку User-Agent
  • Проверяем работоспособность проверки на 'подпись' браузера
  • Исходные файлы сайта

Привязка пользователя к HTTP-заголовку User-Agent


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

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

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

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

В PHP получить значение HTTP-заголовка User-Agent можно через элемент суперглобального массива $_SERVER['HTTP_USER_AGENT']. Ниже показана строка PHP-кода, выполняющая получение и запись заголовка User-Agent в переменную сессии.

Данный фрагмент кода следует добавить в созданный в предыдущей статье файл "auth.php", в котором обработчик формы авторизации при успешной аутентификации пользователя производит формирование всех необходимых элементов сессии. И в этом случае к ранее созданным переменным сессии и cookies добавляется еще одна переменная $_SESSION['agent'] с данными об агенте пользователя.

  1. <?php

  2. $_SESSION["agent"] = $_SESSION["HTTP_USER_AGENT"]; //Записываем данные по HTTP-заголовку User-Agent в переменную сессии

  3. ?>

Рис.1 Получение и запись в переменную сессии данных об агенте (добавлено в файл auth.php)

Для того, чтобы посмотреть полученный в запросе от пользователя HTTP-заголовок User-Agent воспользуемся конструкцией языка echo, временно вставив соответствующую строку во фрагмент кода шаблона главной страницы, в котором в предыдущей статье для вывода сообщения об ошибке мы подключили файл "alert.php" (добавленная строка выделена светлым фоном).

  1. . . .

  2. <body>

  3. <?php

  4. echo nl2br("\nДанные HTTP-заголовка User-Agent: " . "\n" . $_SESSION['agent'] . \n\n);

  5. if (!empty($GLOBALSE['alert'])) { //При наличии сообщения об ошибке

  6. require_once"alert.php"; //Подключаем файл alert.php для вывода сообщения на экран браузера

  7. $GLOBALSE['alert'] = ""; //Очищаем сообщение

  8. }

  9. ?>

  10. <div "wrapper">

  11. . . .

Рис.2 Вывод на страницу данных об агенте (добавлено в файл index.php)

А теперь для наглядности выполним авторизацию на сайте в разных браузерах, и посмотрим на полученные данные (для авторизации будем использовать ранее созданный аккаунт с логином Audi387357 и паролем Z5nC89).

Ниже показаны несколько примеров значения HTTP-заголовка User-Agent для разных браузеров, установленных на моем компьютере.

HTTP-заголовок User-Agent для браузера Яндекс

Рис.3 HTTP-заголовок User-Agent для браузера Яндекс

HTTP-заголовок User-Agent для браузера Google Chrome

Рис.4 HTTP-заголовок User-Agent для браузера Google Chrome

HTTP-заголовок User-Agent для браузера Mozilla Firefox

Рис.5 HTTP-заголовок User-Agent для браузера Mozilla Firefox

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

А именно, будем сравнивать значение агента, полученное при аутентификации пользователя и сохраненное в переменной сессии $_SESSION['agent'] с теми данными, которые сервер получает от клиента в запросе при очередной авторизации.

Для этого добавим в файл "auth_check.php", в котором производится оценка достоверности пользователя, дополнительную проверку на соответствие HTTP-заголовка User-Agent (добавленные строки выделены светлым фоном).

  1. <?php

  2. $session_check = 0; //Устанавливаем запрещающий флаг авторизации

  3. if (isset($_COOKIE['alert'])) { //При наличии cookie 'alert' с сообщением об ошибке

  4. $GLOBALS['alert'] = $_COOKIE['alert']; //Для вывода в диалоговое окно браузера записываем в глобальную переменную $GLOBALS['alert'] ообщения об ошибке

  5. setcookie ("alert", "", time()-60*60*24, "/", $_SERVER['SERVER_NAME']); //Удаляем cookie 'alert'

  6. }

  7. else {

  8. if (!empty($_COOKIE[ini_get('session.name')])) { //Если существует активная сессия

  9. session_start(); //Возобновляем сессию

  10. if (isset($_SESSION['key1'])) $session_key1 = $_SESSION['key1']; //Если переменная "key1" в сессии существует, то PHP-переменной $session_key1 присваивается ее значение

  11. else //Если нет

  12. $session_key1 = ""; //Переменной $session_key1 присваивается пустое значение

  13. if (isset($_COOKIE['key1'])) $cookie_key1 = $_COOKIE['key1']; //Если cookie "key1" существует, то PHP-переменной $cookie_key1 присваивается ее значение

  14. else //Если нет

  15. $cookie_key1 = ""; //Переменной $cookie_key1 присваивается пустое значение

  16. if ($session_key1 != "" && $cookie_key1 != "" && $session_key1 == $cookie_key1) { //Если одноразовый ключ сессии и cookie совпадают (подтверждение подлинности пользователя)

  17. $key1_hash = hash('sha256', microtime()); //Формируем одноразовый хеш-ключ

  18. setcookie ("key1", $key1_hash, time()+900, "/", $_SERVER['SERVER_NAME'], 0, 1); //Отправляем на сторону клиента cookie со вновь созданным одноразовым ключем

  19. $_SESSION["key1"] = $key1_hash; //Записываем данные ключа в переменную сессии с именем "key1"

  20. if (isset($_SESSION['agent'])) { //Проверяем, определена ли переменная сессии, содержащая данные HTTP-заголовка User-Agent

  21. $agent = $_SERVER['HTTP_USER_AGENT']; //Получаем данные об агенте из запроса

  22. if ($_SESSION['agent'] == $agent) { //Если данные об агенте совпадают с данными сессии

  23. $session_check = 1; //Устанавливаем разрешающий флаг авторизации

  24. }

  25. else { //Если данные об агенте не совпадают с данными сессии

  26. $error_auth = 'Подпись пользователя не подтверждена. В целях безопасности текущая сессия закрыта!\nДля получения прав доступа необходимо вновь авторизоваться через соответствующую форму.'; //Сообщение об ошибке

  27. sessionDelete($error_auth); //Вызываем функцию уничтожения сессии

  28. }

  29. }

  30. else { //Если переменная сессии, содержащая данные HTTP-заголовка User-Agent не определена

  31. $error_auth = 'Отсутствует подпись пользователя. В целях безопасности текущая сессия закрыта!\nДля получения прав доступа необходимо вновь авторизоваться через соответствующую форму.'; //Сообщение об ошибке

  32. sessionDelete($error_auth); //Вызываем функцию уничтожения сессии

  33. }

  34. }

  35. else { //При не подтверждении подлинности пользователя

  36. setcookie(session_name(), session_id(), time()-60*60*24, '/'); //Удаляем сессионную cookie

  37. setcookie("key1", "", time()-60*60*24, "/", $_SERVER['SERVER_NAME'], 0, 1); //Удаляем cookie с одноразовым ключем

  38. session_unset(); //Удаляем данные из переменных сессии

  39. session_destroy(); //Уничтожаем сессию

  40. $GLOBALS['alert'] = 'Достоверность пользователя не подтверждена. В целях безопасности текущая сессия закрыта!\nДля получения прав доступа необходимо вновь авторизоваться через соответствующую форму.'; //Записываем в глобальную переменную $GLOBALS['alert'] для вывода в диалоговое окно браузера сообщение об ошибке

  41. }

  42. }

  43. }

  44. ?>

Рис.6 Добавление проверки на соответствие HTTP-заголовка User-Agent (файл auth_check.php)

Добавленный код довольно прост. Основу его составляет проверка переменной сессии $_SESSION['agent']. И в случае, если она определена и совпадает с полученным в новом запросе значением агента, то устанавливается разрешающий флаг авторизации (поз.23). В противном случае сессия уничтожается с выводом соответствующего сообщения.

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

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

  1. <?php

  2. //----Функция уничтожения сессии -----

  3. function sessionDelete($error_auth) {

  4. setcookie(session_name(), session_id(), time()-60*60*24, '/'); //Удаляем сессионную cookie

  5. if (isset($_COOKIE['key1'])) setcookie("key1", "", time()-60*60*24, "/", $_SERVER['SERVER_NAME'], 0, 1); //При наличии cookie с одноразовым ключем, удаляем ее

  6. session_unset(); //Удаляем данные из переменных сессии

  7. session_destroy(); //Уничтожаем сессию

  8. if (!empty($error_auth)) $GLOBALS['alert'] = $error_auth; //При наличии ошибки записываем ее текст в глобальную переменную $GLOBALS['alert'] для вывода в диалоговом окне браузера

  9. }

  10. ?>

Рис.7 Функция уничтожения сессии sessionDelete() (файл functions.php в папке php)

Можно заметить, что данная функция по существу имеет тот же самый код, который ранее использовался в файле "auth_check.php" для уничтожения сессии при не подтверждении подлинности пользователя (поз.36÷40, рис.6). За исключением лишь только того, что в функции запись текста ошибки в глобальную переменную $GLOBALS['alert'] происходит только при непустом ее аргументе $error_auth (поз.8, рис.7).

Поэтому, используя данную функцию можно оптимизировать указанный фрагмент (поз.36÷40, рис.6), аналогично тому, как мы это сделали при проверке данных об агенте (поз.26,27 и 31,32, рис.6). Что мы и выполним при следующих преобразованиях данного файла.

Таким образом мы сформировали все элементы проверки подлинности пользователя по данным HTTP-заголовка User-Agent. Осталось только проверить, как это все будет в действительности работать.

Проверяем работоспособность проверки на 'подпись' браузера


Для того, чтобы оценить работоспособность данного способа защиты с имитируем взлом сессии с другого браузера, подставив в него необходимые сессионные cookies с данными, соответствующими легальному пользователю.

А затем проверим возможность несанкционированного доступа для двух случаев - без проверки соответствия данных об HTTP-заголовка User-Agent (до вышеприведенных преобразований системы авторизации) и с включением всех рассмотренных здесь элементов проверки на подпись браузера.

При этом имитацию атаки сделаем следующим образом:

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

Что касается подстановки cookies, то для этого используем ввод через консоль браузера JavaScript-кода с применением свойства объекта document. Например, для используемой нами сессионной cookie с именем "SESSID", код для установки cookie будет иметь следующий вид: document.cookie = 'SESSID = 65psu51t2hqea8eha46nrb74nbhcuvfh;';. Где для имени cookie SESSID задано ее значение, в данном случае 65psu51t2hqea8eha46nrb74nbhcuvfh.

Возможно использовать и свойства cookies. Например для cookie с одноразовым ключом в коде указаны ее аргументы, которые соответствуют свойствам первоначальной cookie, а именно: document.cookie = 'key1=13398e4aa027223964aa1...; [expires=time()+900;][path=/;][domain="newsite.local";][secure=0;][httponly=1;]';

Ниже показан пример установки cookies через консоль в браузере Google Chrome.

Установка cookies через консоль в браузере Google Chrome

Рис.8 Установка cookies через консоль в браузере Google Chrome

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

Авторизация на сайте с подменой cookies без проверки подписи браузера

Рис.9 Авторизация на сайте с подменой cookies без проверки подписи браузера

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

Данные об агенте браузеров легального пользователя и злоумышленника

Рис.10 Данные об агенте браузеров легального пользователя и злоумышленника

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

И для того, чтобы этому противодействовать и применяется метод проверки соответствия HTTP-заголовков User-Agent.

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

Закрытие сессии при обнаружении несоответствия подписи браузера

Рис.11 Уничтожение сессии при обнаружении несоответствия подписи браузера

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

Поэтому, при желании на своем ресурсе повысить уровень безопасности сессий, вполне возможно использовать рассмотренный вариант защиты.

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


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

Исходные файлы сайта


Знак папкиИсходные файлы сайта с обновлениями, которые были сделаны в данной статье, можно скачать из прилагаемых дополнительных материалов:

  • Файлы каталога www
  • Таблицы базы данных MySQL

При этом, временно сформированные в данной статье PHP-скрипты, размещенные в файле "main.php" папки "articles" корневого каталога, закомментированы. Для проверки рассмотренных здесь примеров, следует раскомментировать соответствующие фрагменты кода.

Дополнительные материалы бесплатно предоставляются только зарегистрированным пользователям.

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

Для тех кто не зарегистрирован, можно это сделать на вкладке Регистрация.

С уважением, Николай Гришин


Комментарии


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

Буду Вам за это очень признателен!

comments powered by HyperComments