The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Об опасности включения register_globals в PHP. (php security)


<< Предыдущая ИНДЕКС Правка src / Печать Следующая >>
Ключевые слова: php, security,  (найти похожие документы)
From: Creator <proit@yandex.ru.> Newsgroups: email Date: Mon, 11 Jan 2006 14:31:37 +0000 (UTC) Subject: Об опасности включения register_globals в PHP. 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 по умолчанию. Но пока этого нет, вы знаете как с этим бороться;-) Если у вас возникли вопросы, вы можете задать их на нашем форуме: http://www.internet-technologies.ru/forums/ или лично мне http://www.internet-technologies.ru/feedback.html Удачи вам! Источник: http://www.internet-technologies.ru (Веб-мастеру в помощь)

<< Предыдущая ИНДЕКС Правка src / Печать Следующая >>

Обсуждение [ RSS ]
  • 1.1, playnet (?), 13:53, 04/07/2007 [ответить]  
  • +/
    Статья неплохая.. Но аффтара на мыло за грамматику.
    "как мне нравиться". Про проверочные слова слышал? "Что делаТЬ? нравиТЬся". А у тебя "что делаЕТ". А теперь прочитай эти слова в контексте "что делать".. сам поймешь, как нелепо это звучит.
     
  • 1.2, иб адм (?), 01:47, 12/08/2007 [ответить]  
  • +/
    ты дурачек совсем? причем тут грамматика. Автор молодец, открыл мне глаза.
     
  • 1.3, olehv (?), 15:09, 25/09/2007 [ответить]  
  • +/
    просто и понятно...
    Спасибо!!!
     
  • 1.4, Владислав (??), 22:04, 20/01/2008 [ответить]  
  • +/
    Великолепная статья, а главное - нужная.
    Вопрос безопасности меня интересует.
    Спасибо!
     
  • 1.5, Андрей Webmaster (?), 18:21, 14/10/2008 [ответить]  
  • +/
    Всегда использую ON, 9 лет опыта в php. Есть опыт написания баннерной сети, разработка CMS и скрипты специального назначения, которые должны отвечать высокой безопасности.
    Главная причина использования ON - частое использование переменных из url.

    По поводу примеров...

    При появлении новой переменной присваиваю ей значение:

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

    $asd может ведь вначале содержать значение "0".
    Всё зависит от задачи. Лучше присвоить ей нужное значение и забыть про неё.

    Далее... страшное слово "инъекции" - товарищи, это называется раздолбайством программиста!
    Проверяйте каждую используемую переменную перед  sql запросом и всё будет замечательно!
    Элементарно:

    if ($id+0 > 0 ) { ....ок..... }
    if (ereg('^[a-z0-1]+$', $name)) { ....ок..... }

    И ещё я обязательно "обучаю" скрипт ругаться матом, если какая-то переменная содержит левые значения.

    Допускаю привычку писать так или иначе. Главное - результат и степень безопасности.
    Удачи!

     
  • 1.6, аленка (?), 14:25, 11/11/2009 [ответить]  
  • +/
    да, спасибо за статью..
    автор первого коммента - точно дурачек:) лучше его на мыло)
     

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру