Безличный index php register. Почему опасно включать параметр PHP register_globals? Вы уже зарегистрированы

  • 20.06.2020

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

В большинстве случаев, применяют более упрощенную систему регистрации, которая написана на php в одном файле register.php .

Итак, мы немного отвлеклись, а сейчас рассмотрим более подробно файл регистрации.

Файл register.php

Для того, чтобы у вас это не отняло массу времени создадим систему, которая будет собирать пользователей, принимая от них минимальную контактную информацию. В данном случае все будем заносить в базу данных mysql. Для наибольшей скорости работы базы, будем создавать таблицу users в формате MyISAM и в кодировке utf-8.

Обратите внимание! Писать все скрипты нужно всегда в одной кодировке. Все файлы сайта и база данных MySql должны быть в единой кодировке. Самые распространенные кодировки UTF-8 и Windows-1251.

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

Как будет работать сам скрипт?

Мы хотим все упростить и получить быстрый результат. Поэтому будем получать от пользователей только логин, email и его пароль. А для защиты от спам-роботов, установим небольшую капчу. Иначе какой-нибудь мальчик из Лондона напишет небольшой робот-парсер, который заполнит всю базу липовыми пользователями за несколько минут, и будет радоваться своей гениальности и безнаказанности.

Вот сам скрипт. Все записано в одном файле register.php :

! `; // красный вопросительный знак $sha=$sh."scripts/pro/"; //путь к основной папке $bg=` bgcolor="#E1FFEB"`; // фоновый цвет строк?> Пример скрипта регистрации register.php style.css" />

В данном случае скрипт обращается к самому себе. И является формой и обработчиком данных занесенных в форму. Обращаю ваше внимание, что файл сжат zip-архивом и содержит файл конфигурации config.php, дамп базы данных users, файл содержащий вспомогательные функции functions.php, файл стилей style.css и сам файл register.php. Также несколько файлов, которые отвечают за работу и генерацию символов капчи.

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

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

Если на сервере включена директива register_globals = On (в php.ini), то при передаче переменных через форму или через строку браузера, в скрипте, которому эти переменные предназначены, они будут созданы автоматически. Т.е. если у вас в строке браузера написано: www.server.ru/index.php?var=1, то в скрипте index.php будет автоматически создана переменная $var со значением равным 1.

Замечание

Указанная директива является одним из самых дискуссионных моментов в языке PHP. С одной стороны, ее использование действительно может породить реальные проблемы с защитой PHP-сценариев, при ненадлежащем учете возможных ошибочных ситуаций и многие разработчики справедливо отмечают, что написание скриптов без использования глобальных переменных на 90 % уменьшает уязвимость скриптов к различного рода атакам. С другой стороны, на заре возникновения PHP, не одна тысяча пользователей доверилась разработчикам языка (до версии PHP 4.3 эта директива была по умолчанию включена), в силу чего в настоящее время имеются миллионы реально функционирующих скриптов, написанных с использованием глобальных переменных (Стоит отметить, что в обучающих целях иногда совершенно нелишне писать скрипты с использованием глобальных переменных, поскольку из замена на суперглобальные массивы сильно ухудшает читабельность кода).

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

При отключенной директиве register_globals доступ к таким переменным возможен двумя способами:

  • через ассоциативные массивы HTTP_***_VARS (HTTP_POST_VARS и т.д.)
  • через суперглобальные массивы ($_ENV, $_GET, $_POST, $_SERVER, $_COOKIE, $_FILES и др.)

Суперглобальные массивы доступны в любой области видимости. Разработчики PHP рекомендуют отключать на сервере директиву register_globals и работать с переменными через суперглобальные массивы. Эта рекомендация связана с проблемами безопасности, которые могли возникнуть при включенной директиве register_globals.

Хотя до недавнего времени на хостингах директива register_globals оставалась включенной. Ситуация начала меняться с выходом PHP 5, где эта директива по умолчанию выключена и хостеры не спешат ее включать (может быть и правильно).

Итак, что же конкретно сделать чтобы получить переменные - нужно взять их из суперглобальных массивов. Например, для получения переменных, переданных через строку браузера, используют массив $_GET. Допустим, в строке браузера написано www.server.ru/index.php?var=1, Тогда для получения переменной var в index.php нужно написать:

$var=$_GET["var"];

А, например, для получения переменных переданных из формы методом POST в скрипте-обработчике формы нужно написать:

$var=$_POST["var"];

Не знаю почему… нет, почему нельзя включать директиву register_globals я знаю, а не знаю я почему в литературе, как правило, про это ничего не говорится.

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

О том, как это работает

В настройках PHP (файл php.ini) есть такая директива register_globals. Смысл её заключается в том, что если она включена (register_globals = on), то все переменные, переданные через GET и POST, будут зарегистрированы автоматически как глобальные. Что это значит?

К примеру, мы передаём сценарию index.php методом GET некоторое значение page: index.php?page=2. Переданное значение хранится в массиве GET и может быть использовано в сценарии как $_GET["page"]. Однако если у нас включена register_globals, то для переданного значения будет создана переменная $page, которая доступна в любой части сценария index.php.

Небольшой итог и дополнение. При включенном register_globals создаётся три копии переменной: в массиве GET, в массиве GLOBALS и просто сама переменная ($_GET["page"], $GLOBALS["page"], $page), в то время как при выключенном register_globals переданное значение может быть доступно только через массив GET ($_GET["page"]). Запомнили.

Опасность использования

Рассмотрим простой пример, чтобы понять, что нам светит (от 3 до 5 лет – прим.ред. ). Чтобы было проще, скажу сразу, что $login и $password – это переменные, переданные методом GET/POST.

Кратко о том, что делает сценарий:

    Строка 2. Делаем запрос к БД с целью вытащить настоящий пароль для введённого пользователем логина.

    Строка 3. Получаем этот пароль и присваиваем его переменной $real_pass.

    Строка 4. Сравниваем настоящий и введённый пароль и если они совпадут, то переменной $check будет присвоено true.

    Строки 5-8. Если $check равен true, то пишем, что авторизация проведена успешно и т.д.

Предложенный сценарий по определению самый дырявый на свете и сейчас я покажу Вам эти дыры. Условие – register_globals включен.

Допустим, передача идёт методом GET. Тогда url будет выглядить приблизительно следующим образом:
www.site.com/index.php?login =admin&password =qwerty
Понятное дело, что сразу же создаются глобальные переменные $login и $password. А теперь посмотрите сценарий. В нём есть переменная $check. А что если её передать через урл?

www.site.com/index.php?login =admin&password =qwerty&check =1
Тогда минуется проверка соотнесения паролей и пользователь получается сразу авторизованным (ведь Вы помните, что 1 – это true, а 0 – это false?). Тот же самый результат будет, если написать www. site. com/ index. php? check =1 . И даже если вы используете метод POST, всё равно все подобные махинации прокатят, так как при включённом register_globals не имеет значения какой у Вас метод - GET или POST.

Думаю, у кого-то возник вопрос, а откуда крякер узнает про переменную check, что она за всё отвечает? Если Вы никому не показывали сценарий, то он врядли это узнает. Однако не все используют свои сценарии, CMS и прочее, а пользуются тем, что есть в сети. В таких случаях крякер, к примеру, может изучить код CMS и делать атаки на сайты, созданные при его помощи.

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

Возьмём наш пример. Чтобы его защитить на случай, если register_globals включен, нужно после строки if ($ password==$ real_ pass) $ check = true; дописать следующее: else $ check = false; . В этом случае, даже если методом GET будет передана переменная check равная единице, то сценарий при неправильном пароле всё равно установит $check=false.

Да, ещё обращу Ваше внимание на то, что если выключить register_globals, то наш пример работать не будет. А чтобы он заработал, надо перед сценарием написать $login = $_POST["login"]; $password = $_POST["password"];

Подведём итоги…

и сделаем два основных вывода:

1) При включённом register_globals можно передавать различные переменные, значения для которых получать через GET или POST не рассчитывалось.

2) Не столько опасен сам register_globals, сколько криво написанный сценарий.

На сегодня всё! Буду очень рад Вашим комментариям, замечаниям, предложениям и просто отзывам. Посему пишите, не стесняйтесь!

С пожеланиями удачной недели,
Александр ШУйский

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

Позволяет регистрировать переменные, полученные из GET-запроса . Допустим, был такой запрос: index.php?a=15 . Таким образом, безусловно, создаётся переменная $_GET["a"] и переменная a . Вот создание переменной a и произошло в результате включённой директивы register_globals .

Теперь о том, почему данную директиву надо всегда держать отключённой. Предположим, что Вы делаете авторизацию пользователя, и Вы написали такой код:

if (($_POST["login"] == "Admin") && ($_POST["password"] == "123456")) $check_user = true;
if ($check_user) echo "Авторизация прошла успешно";
else echo "Ошибка авторизации";
?>

Теперь если файл называется, например, auth.php , то, обратившись к нему следующим образом: auth.php?check_user=1 , то получится успешная авторизация, независимо от того, какие логин и пароль были отправлены и были ли отправлены вообще.

Безусловно, данный пример является слегка мистическим, поскольку так никто не пишет (хотя бы из-за отсутствия else $check_user = false; ), однако, данный пример наглядно показывает, к чему может привести включённая директива register_globals .

Теперь о том, как же отключить директиву register_globals . Для этого надо добавить в файл .htaccess всего одну строчку:

Php_value register_globals 0

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