 Очень часто админ, при установке CMS Joomla! видит сообщение об увязимости сайта в связи с установленым параметром register_globals=on. Эта статья поможет много чего прояснить.
Что представляет собой register_globals?
Это опция в php.ini, которая указывает на необходимость регистрации переменных
полученные методом POST или GET в глобальный массив $GLOBALS.
Для ясности приведеи пример при register_globals=on.
Есть файл «index.php» с содержимом:
echo $asd.'
- локальная переменная ';
echo $GLOBALS['asd'].'
- ссылка в глобальном массиве $GLOBALS ';
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
И все, теперь некоторые вопросы безопасности решены:)
|