register_globals=oN? Вы в опасности!

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

Что представляет собой register_globals?

Это опция в php.ini, которая указывает на необходимость регистрации переменных полученные методом POST или GET в глобальный массив $GLOBALS.

Для ясности приведу пример при register_globals=on.
Есть файл «index.php» с содержимом:

<?
echo $asd.' - локальная переменная<br>';
echo $GLOBALS['asd'].' - ссылка в глобальном массиве $GLOBALS<br>';
echo $_GET['asd'].' - $_GET["asd"]';
?>

В адресной строке напишем: index.php?asd=123

Получим:

123 - локальная переменная
123 - ссылка в глобальном массиве $GLOBALS
123 - $_GET['asd']


Как мы видим, создались 2 переменные: одна локальная (+ ссылка в $GLOBALS), другая в массиве $_GET. Многие не используют массив $_GET вообще, они продолжают обрабатывать переменную «$asd» после получения ее извне.
Но давайте вдумаемся, зачем нам «загрязнять» массив $GLOBALS? Для этого у нас есть специальные массивы, хранящие данные, переданные методами GET (массив $_GET) и POST (массив $_POST).

Тот же самый пример, но при register_globals=off :

- глобальная переменная
- ссылка в глобальном массиве $GLOBALS
123 - $_GET['asd']


Т.о. не была создана локальная переменная и для манипулирования с «$asd» мы должны использовать массив $_GET.

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

А теперь я расскажу вам, как взломщик может воспользоваться этой опцией в своих целях, т.е. при register_globals=on
Начну от простого к сложному.

Часто мы видим предупреждения:

Notice: Undefined variable: asd(название переменной) in ****


Что это значит? Это значит, что переменная «$asd» не была определена явно.
Например, некоторые люди балуются подобным:

<?
for($i=0;$i<10;$i++)
{
 @$asd.=$i;
}

echo $asd
?>

Т.е. не определив переменную, сразу начинают ее использовать. Приведенный код по идее не страшен, но задумайтесь, а вдруг эта самая переменная «$asd», в последствие записывается в файл? Например, напишем следующее в строке адреса: «index.php?asd=LUSER+» и получим: «LUSER 0123456789». Ну, разве приятно будет увидеть такое? Не думаю.

Предположим мы пишем систему аутентификации пользователя:

<?
if($_POST['login']=='login'&&$_POST['pass']=='pass')
{
 $valid_user=TRUE; // Юзер корректный
}

if($valid_user)
{
 echo 'Здравствуйте, пользователь';
}
else echo 'В доступе отказано'
?>

Привел я заведомо дырявую систему, стоит нам только написать в адресной строке «index.php?valid_user=1» и мы получим надпись «Здравствуйте, пользователь»

Этого бы не случилось, если бы мы написали так:

<?
if($_POST['login']=='login'&&$_POST['pass']=='pass')
{
 $valid_user=TRUE; // Юзер корректный
}
else $valid_user=FALSE;

if($valid_user)
{
 echo 'Здравствуйте, пользователь';
}
else echo 'В доступе отказано'
?>

Т.е. сами определили переменную $valid_user, как FALSE в случае неудачи.

Теперь использование функции IsSet() становится небезопасно, т.к. любой может подменить переменную на угодную ему.

Приведу пример с sql-инъекцией:

<?
if(@$some_conditions) // некоторые условия
{
 $where='id=3';
}

echo $query='SELECT id, title, description FROM table '
.'WHERE '.(IsSet($where)?$where:'id=4')
?>

В адресной строке напишем: «index.php?where=id=0+UNION+ALL+SELECT+login,+password, +null+FROM+admin+where+ login='admin'» получим sql-инъекцию:

SELECT id, title, description FROM table WHERE id=0
UNION ALL SELECT login, password, null FROM admin where login='admin'

И взломщик получает ваши явки и пароли:(

Как вы видите все примеры, имеют дыры в защите, которые можно эксплуатировать через включенный register_globals.

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

<?
function asd()
{
 // Какие то действия

 if(IsSet($where))
 {
 echo $where;
 }
 else echo '$where не существует';
}
asd();
?>

Теперь, если мы напишем в адресной строке: «index.php?where=123»
Даст: «$where не существует»
Но это при условии, что вы не устанавливаете переменную $where как глобальную, т.е. «global $where»

Я могу придумать еще очень много примеров, но думаю, что приведенных мною вам будет достаточно для понимания.
Хочу сказать, что все эти проблемы канут в лета, когда вы установите опцию register_globals=off и попробуете заново все приведенные выше примеры.

Это можно сделать как в php.ini, но большинство хостинг провайдеров вам это не позволят, потому придется воспользоваться файлом «.htaccess»

Создаем файл с названием: .htaccess

Запишем в него:

php_flag register_globals off


И все, теперь некоторые вопросы безопасности решены:)

Немного о причине написания мной этой статьи

Лично я никогда не использовал register_globals = on, т.к. мне казалось это нелогичным. Так же я знал, что это еще один «+» к защите. Но в полной мере я не осознавал насколько это может быть опасно. Случилось это когда я решил написать GSMgen – Google SiteMap generator, который должен был работать безопасно и при включенном register_globals. Когда же я начал его тестировать, у меня был шок…так как мне нравится использовать функцию IsSet() я нашел в ней непосредственную уязвимость, и в процессе мне пришлось от этого отказаться:( Что поделаешь…

Я очень надеюсь, что эта статья изменит ваше мнение относительно register_globals. Думаю, что со временем все хостинг провайдеры будут ставить register_globals = off по умолчанию. Но пока этого нет, вы знаете, как с этим бороться;-)

Удачи вам!

Комментарии

Оставьте свой комментарий
C
Creator

Совершенно верно - это было описано в статье.
К тому же, достаточно только "php_flag register_globals Off", но и "php_value register_globals off" будет работать.

В
Виктор

Как отключить register_globals ???

Создаешь htaccess.txt на рабочем столе и пишешь в нем:

php_flag register_globals off
php_value register_globals Off
сохраняешь и закачиваешь файл на сервер и переименовываешь его в .htaccess расширение .txt тоже убираем. Все готово теперь он откючен.

C
Creator

Реальный пример бреши, возникшей в результате register_global=on. Об этом написал вот здесь: michael.m-team.ru/articles/aboutburatino
Одно из другого вытекает;) Еще одно "за" для отключения данной опции.

M
Michael

Реальный пример бреши, возникшей в результате register_global=on. Об этом написал вот здесь: michael.m-team.ru/articles/aboutburatino

C
Creator

Если register_global=on, то, для обеспечения безопасности (чтобы не получилось sql-injection) нужно переменные в скрипте переопределять...
Да, именно так или же использовать другие методы, например инкапсуляцию переменных с помощью ф-ий...
Но все равно это бывает в некоторых случаях не удобно или же просто же нету ни времени, ни желания, почему бы просто не установить опцию как off и спать спокойно? Суть статьи как раз в этом, что бы не "парясь", улучшить уровень безопасности;)

M
Makswell

Если register_global=on, то, для обеспечения безопасности (чтобы не получилось sql-injection) нужно переменные в скрипте переопределять...

C
Creator

"Тырим все подряд не указывая откуда ?"

А теперь поясните в каком смысле, что именно стырено и какие ваши факты?
Данная статья была написана с "0" на основе моих размышлений и опыта.

N
Necto

Тырим все подряд не указывая откуда ?

C
Creator

2medwoodu: Нда, вы не смогли усвоить основную суть статьи:(
Предопредение не всегда бывает выгодным это может привести к издержкам в производительности.
Вообще примеров море, то что я привел это лишь малая часть, но этого должно было хватить для отключения register_globals.
Отключив эту опцию веб-мастер повысит безопасность своего сайта т.д.
По поводу акцента на безопасное программирование уже много написано, а вообще это с опытом приходит.

2mr. M: если захочешь почитать книги, то зайди в нашу библиотеку;)

M
medwoodu

mr. M, а Вы читали что нибудь типа Котерова?
Creator, а не проще все-таки предопредлять все переменные и опять-таки не раздувать таких псевдопроблем и переместить АКЦЕНТЫ на безопасное написание кода. А если на хостинге нет возможности отключить регистр глобалс? У человека который использует ТАКИЕ заплатки скорее всего еще дофига на сайте уязвимостей 🙂

Загрузить еще