Не знаю почему… нет, почему нельзя включать директиву register_globals я знаю, а не знаю я почему в литературе, как правило, про это ничего не говорится.
Обычно напишут, что использовать его не рекомендуется (если вообще напишут – прим.ред.), и всё. В результате, само собой, начинающий программист просто не догадывается, к чему может привести использование 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.
$real_pass = mysql_fetch_array($get_pass);
if ($password==$real_pass) $check = true;
if ($check) {
echo 'Авторизация прошла успешно';
…
}
…
Кратко о том, что делает сценарий:
-
Строка 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, сколько криво написанный сценарий.
На сегодня всё! Буду очень рад Вашим комментариям, замечаниям, предложениям и просто отзывам. Посему пишите, не стесняйтесь!
С пожеланиями удачной недели,
Александр ШУйский
Похожие записи:
21/07/2010 at 10:51 Постоянная ссылка Цитировать
Почти везде по тексту идет “registry_globals” – надо бы подправить
21/07/2010 at 17:54 Постоянная ссылка Цитировать
ох ты, ёшкин кот, вот оно что значит писать посты на работе =)))
спасибо за замеченные опечатки!
10/08/2010 at 12:08 Постоянная ссылка Цитировать
спасибо за ценную инфу!
10/08/2010 at 15:46 Постоянная ссылка Цитировать
всегда пожалуйста =)
14/10/2010 at 19:04 Постоянная ссылка Цитировать
А про $_REQUEST забыл?
“три копии переменной: в массиве GET, в массиве GLOBALS и просто сама переменная”
не особо важно конечно, но не могу удержаться и пальцем не тыкнуть =)) Ы
14/10/2010 at 19:07 Постоянная ссылка Цитировать
ЗЫ. легче не заморачиваться и всегда выключать!
И твой код SQL инъекцией похакать можно – надо mysql_escape_string использовать.
14/10/2010 at 19:09 Постоянная ссылка Цитировать
ну, я говорил о влиянии вкл/выкл register_globals, посему как-то про риквест как-то даже и не вспоминал.
Но за комментарий и интерес отдельное спасибо =)
14/10/2010 at 19:15 Постоянная ссылка Цитировать
ЗЫ: согласен, лучше вырубать.
вообще надо обрабатыватьв се данные, передаваемые в БД. Самое безопасное strip_tags применить, а потом как раз таки заслэшить всё остальное, если таковое осталось.
09/11/2010 at 20:35 Постоянная ссылка Цитировать
большое спасибо!
10/11/2010 at 14:06 Постоянная ссылка Цитировать
Большое пожалуйста! =)
04/05/2012 at 16:30 Постоянная ссылка Цитировать
Советовали дубльстар или хуачуан, что скажете ?
04/05/2012 at 16:51 Постоянная ссылка Цитировать
Советую завязывать с этой шнягой
02/06/2013 at 18:21 Постоянная ссылка Цитировать
Здравствуйте! Я воспользовался вашим сценарием. Проблема в том, что когда я передаю false (check=0), то сценарий также пишет о том, что “авторизация прошла успешно”.
05/06/2013 at 10:55 Постоянная ссылка Цитировать
здравствуйте. не хочу расстраивать, но этот сценарий приведён не для применения, а для того, чтобы показать насколько он кривой и неудачный.