<?xml version="1.0" encoding="utf-8"?>
<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
<stylesheet type="text/css">
.body{font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
}
.p{margin:0.5em 0 0 0.3em; padding:0.2em; text-align:justify;
}
</stylesheet>
<description>
<title-info>
<genre>sf_history</genre>
<author>
<first-name>Имя автора</first-name>
<last-name>Фамилия автора</last-name>
</author>
<book-title>Название книги</book-title>
<annotation></annotation>
<date>Дата</date>
<lang>ru</lang>
</title-info>
<document-info>
<author><nickname></nickname>
</author>
<program-used>Lib converter jcms</program-used>
<date value=""></date>
<src-url>http://johncms.com</src-url>
<id></id>
<version>1.0</version>
<history><p>book</p></history>
</document-info>
</description>
<body>
<title><p>Register_globals=oN? Вы в опасности!</p>
</title>
<section><p>Здравствуйте уважаемые веб-мастера, статья повествует о том, почему опасно оставлять опцию register_globals включенной. Вы, возможно, слышали, что использование её может привести к небезопасной работе вашей программы (скрипта). Но давайте разберемся, как эту опцию могут использовать в противоправных целях и как от этого защититься. </p>
<p></p>
<p>Что представляет собой register_globals? </p>
<p>Это опция в php.ini, которая указывает на необходимость регистрации переменных полученные методом POST или GET в глобальный массив $GLOBALS.</p>
<p></p>
<p>Для ясности приведу пример при register_globals=on. </p>
<p>Есть файл «index.php» с содержимом:</p>
<p></p>
<p><?</p>
<p>echo $asd.' - локальная переменная<br>';</p>
<p>echo $GLOBALS['asd'].' - ссылка в глобальном массиве $GLOBALS<br>';</p>
<p>echo $_GET['asd'].' - $_GET["asd"]';</p>
<p>?> </p>
<p></p>
<p>В адресной строке напишем: index.php?asd=123</p>
<p></p>
<p>Получим: </p>
<p></p>
<p>123 - локальная переменная</p>
<p>123 - ссылка в глобальном массиве $GLOBALS</p>
<p>123 - $_GET['asd']</p>
<p></p>
<p>Как мы видим, создались 2 переменные: одна локальная (+ ссылка в $GLOBALS), другая в массиве $_GET. Многие не используют массив $_GET вообще, они продолжают обрабатывать переменную «$asd» после получения ее извне. </p>
<p>Но давайте вдумаемся, зачем нам «загрязнять» массив $GLOBALS? Для этого у нас есть специальные массивы, хранящие данные, переданные методами GET (массив $_GET) и POST (массив $_POST).</p>
<p></p>
<p>Тот же самый пример, но при register_globals=off :</p>
<p></p>
<p>- глобальная переменная</p>
<p>- ссылка в глобальном массиве $GLOBALS</p>
<p>123 - $_GET['asd']</p>
<p></p>
<p>Т.о. не была создана локальная переменная и для манипулирования с «$asd» мы должны использовать массив $_GET.</p>
<p></p>
<p>Возможно, уже сейчас вы изменили свое мнение о register_globals.</p>
<p>Вероятно, вам придется, что-то переписать в своих программах, но оно того стоит. </p>
<p></p>
<p>А теперь я расскажу вам, как взломщик может воспользоваться этой опцией в своих целях, т.е. при register_globals=on </p>
<p>Начну от простого к сложному. </p>
<p></p>
<p>Часто мы видим предупреждения:</p>
<p></p>
<p>Notice: Undefined variable: asd(название переменной) in ****</p>
<p></p>
<p>Что это значит? Это значит, что переменная «$asd» не была определена явно. </p>
<p>Например, некоторые люди балуются подобным: </p>
<p></p>
<p><?</p>
<p>for($i=0;$i<10;$i++)</p>
<p>{</p>
<p>@$asd.=$i;</p>
<p>}</p>
<p></p>
<p>echo $asd</p>
<p>?> </p>
<p></p>
<p>Т.е. не определив переменную, сразу начинают ее использовать. Приведенный код по идее не страшен, но задумайтесь, а вдруг эта самая переменная «$asd», в последствие записывается в файл? Например, напишем следующее в строке адреса: «index.php?asd=LUSER+» и получим: «LUSER 0123456789». Ну разве приятно будет увидеть такое? Не думаю.</p>
<p></p>
<p>Предположим мы пишем систему аутентификации пользователя:</p>
<p></p>
<p><?</p>
<p>if($_POST['login']=='login'&&$_POST['pass']=='pass')</p>
<p>{</p>
<p>    $valid_user=TRUE; // Юзер корректный</p>
<p>}</p>
<p></p>
<p>if($valid_user)</p>
<p>{</p>
<p>   echo 'Здравствуйте, пользователь';</p>
<p>}</p>
<p>else echo 'В доступе отказано'</p>
<p>?> </p>
<p></p>
<p>Привел я заведомо дырявую систему, стоит нам только написать в адресной строке «index.php?valid_user=1» и мы получим надпись «Здравствуйте, пользователь»</p>
<p></p>
<p>Этого бы не случилось, если бы мы написали так:</p>
<p></p>
<p><?</p>
<p>if($_POST['login']=='login'&&$_POST['pass']=='pass')</p>
<p>{</p>
<p>    $valid_user=TRUE; // Юзер корректный</p>
<p>}</p>
<p>else $valid_user=FALSE;</p>
<p></p>
<p>if($valid_user)</p>
<p>{</p>
<p>   echo 'Здравствуйте, пользователь';</p>
<p>}</p>
<p>else echo 'В доступе отказано'</p>
<p>?> </p>
<p></p>
<p>Т.е. сами определили переменную $valid_user, как FALSE в случае неудачи.</p>
<p></p>
<p>Продолжим далее…</p>
<p>Теперь использование функции IsSet() становиться небезопасно, т.к. любой может подменить переменную на угодную ему.</p>
<p></p>
<p>Приведу пример с sql-инъекцией:</p>
<p></p>
<p><?</p>
<p>if(@$some_conditions) // некоторые условия</p>
<p>{</p>
<p>    $where='id=3';</p>
<p>}</p>
<p></p>
<p>echo $query='SELECT id, title, description FROM table '</p>
<p>.'WHERE '.(IsSet($where)?$where:'id=4')</p>
<p>?> </p>
<p></p>
<p>В адресной строке напишем: «index.php?where=id=0+UNION+ALL+SELECT+login,+password,+null+FROM+admin+where+login='admin'» получим sql-инъекцию:</p>
<p></p>
<p>SELECT id, title, description FROM table WHERE id=0 </p>
<p>UNION ALL SELECT login, password, null FROM admin where login='admin'</p>
<p></p>
<p>И взломщик получает ваши явки и пароли:(</p>
<p></p>
<p>Как вы видите все примеры, имеют дыры в защите, которые можно эксплуатировать через включенный register_globals.</p>
<p></p>
<p>Справиться с подобным можно, если всегда определять переменную вне зависимости от условий. Или же использовать инкапсуляцию переменных в функциях, т.е. когда вы определяете функцию, то переменные, что внутри нее будут закрыты извне, например:</p>
<p></p>
<p><?</p>
<p>function asd()</p>
<p>{</p>
<p>// Какие то действия</p>
<p></p>
<p>if(IsSet($where))</p>
<p>{</p>
<p>    echo $where;</p>
<p>}</p>
<p>else echo '$where не существует';</p>
<p>}</p>
<p>asd();</p>
<p>?> </p>
<p></p>
<p>Теперь, если мы напишем в адресной строке: «index.php?where=123»</p>
<p>Даст: «$where не существует»</p>
<p>Но это при условии, что вы не устанавливаете переменную $where как глобальную, т.е. «global $where»</p>
<p></p>
<p>Я могу придумать еще очень много примеров, но думаю, что приведенных мною вам будет достаточно для понимания.</p>
<p>Хочу сказать, что все эти проблемы канут в лета, когда вы установите опцию register_globals=off и попробуете заново все приведенные выше примеры.</p>
<p></p>
<p>Это можно сделать как в php.ini, но большинство хостинг провайдеров вам это не позволят, потому придется воспользоваться файлом «.htaccess»</p>
<p></p>
<p>Создаем файл с названием: .htaccess</p>
<p>Запишем в него: </p>
<p></p>
<p>php_flag register_globals off</p>
<p></p>
<p>И все, теперь некоторые вопросы безопасности решены:) </p>
<p></p>
<p>Немного о причине написания мной этой статьи:</p>
<p>Лично я никогда не использовал register_globals = on, т.к. мне казалось это нелогичным. Так же я знал, что это еще один «+» к защите. Но в полной мере я не осознавал насколько это может быть опасно. Случилось это когда я решил написать GSMgen – Google SiteMap generator, который должен был работать безопасно и при включенном register_globals. Когда же я начал его тестировать, у меня был шок…так как мне нравиться использовать функцию IsSet() я нашел в ней непосредственную уязвимость, и в процессе мне пришлось от этого отказаться:( Что поделаешь…</p>
<p></p>
<p>Я очень надеюсь, что эта статья изменит ваше мнение относительно register_globals. Думаю, что со временем все хостинг провайдеры будут ставить register_globals = off по умолчанию. Но пока этого нет, вы знаете как с этим бороться</p>
</section>
</body>
</FictionBook>