2007-04-21

Что я знаю о register_globals

Постоянно сталкиваюсь с серверами, где по умолчанию register_globals = On. Да, мне ничто не мешает взять .htaccess и отключить: php_value register_globals Off или написать письмо администратору сервера. Однако, иногда и сам забываешь о той угрозе, которую несёт в себе register_globals = On.

Для того, что-бы воспользоваться чем-то, что даёт вам register_globals = On, нужно либо иметь на руках исходники скрипта, либо быть очень счастливым с…м сыном (ну ещё есть шанс, что ошибки, выбрасываемые PHP вам помогут). Естественно, речь идёт о Global Scope.

На днях я перебирал один маленький сайтик, где PHP используется только для того, что бы можно было удобно и быстро подключить хедер и футер, меню и для страниц легко менять тайтл и мета данные. Такой классический сайт из учебника, плюс несколько наворотов, которые позволяют кешировать сайт на стороне клиента так, как будто это статически HTML. Теоретически, если отключить expose_php и сделать ServerSignature Off, а ServerTokens Prod мало кто догадается, что это PHP.
И нашёл я там одну переменную, которая отвечала за подключение отдельного CSS для страницы. Она была задекларированна не во всех файлах, а толxко там, где требовался дополнительный CSS файл. Именно в тех файлах, где эта переменная не была установлена, её можно было установить при помощи GET, POST или COOKIE (ведь мы помним о variables_order). Плюс никакой фильтрации. Идеальное место для XSS type1 атаки. Но для такой атаки имя переменной нужно знать.

Есть ещё такой стиль программирования, когда массивы никто не декларирует, а сразу к ним обращается. Я имею ввиду, что некоторые программисты не пользуются таким выражением: $arr = array ();, а сразу выполнят присваивание: $arr[] = ’some value’;. Опять же через GET, POST или COOKIE в таком случае можно передать первые ключи для массива $arr. И тогда сколько таких переменных есть у них, которые можно поменять, зная их имена?

Вроде и нет ничего страшного, действует только на Global Scope, надо знать название переменной, но вы не можете гарантировать, что копия сайта е попала в руки мальчишам-плохишам. Так, однажды, получив исходники одной CMS, можно досконально изучить её код, найти уязвимые места, а потом вскрыть этак сайтов 10-15 с одной и той-же ошибкой. Именно так однажды случилось с CMS моего знакомого: CMS решал, человек залоглен или нет, опираясь на онду переменную $admin_id. Стоило сделать запрос admin.php?admin_id=1 и коробочка раскрылась и даже не смотря на то, что этот $admin_id должен был придти из сессии - н там не был установлен (я взял новую сессию) и скрипт пощитал, что всё впорядке и можно пользоваться.

Короткое резюме: пишите свои проекты с учётом register_globals = Off; если вы уверены, что вами написанный проект отлично работает с register_globals = Off, а на сервере register_globals = On - отключите register_globals, так как в редких случаях это может вызвать неадекватное поведения вашего проекта; если вам приходиться работать со скриптами, которые требуют register_globals = On (только в том случае, если это необходимо), будьте предельно бдительны, не сделайте глупых ошибок, связанных со свойством register_globals = On, а также проведите аудит скрипта на возможные ошибки - вы последний, кто его редактировал и все бочки посыпятся на вас.

PHP, Security, Web — Сергей Куракин @ 14:45
Уже комментировало (4) »
  1. Комментиров(ал|ала), lonelysoulNo Gravatar — 2007-08-23 @ 00:30

    Абсолютно согласен с автором. Глобальные переменные несут больше вреда, чем пользы. Пользуйтесь суперглобальными массивами.

    Вопрос Автору: не совсем понял, как в примере с admin_id могла переменная, передающаяся через сессию, быть инициализирована через строку admin.php?admin_id=1?
    По идее, если проверка на существование переменной проходила через _SESSION['admin_id'], то вышенаписанная строка никак на это не могла повлиять даже при включенных глобальных переменных!

    Еще вопрос: как советуете лучше отключить глобальные переменные - самому с помощью .htaccess(в корне?) или письмом админам?

  2. Комментиров(ал|ала), Сергей КуракинNo Gravatar — 2007-08-23 @ 10:30

    Проверка там была $admin_id, а если у вас в начале скрипта нет её декларации и в сессии его нет, то она будет декларирована из GPC переменных.

    Если у вас shared hosting и включены .htaccess - делайте через .htaccess; всё равно Apache будет их искать.
    Если у вас CGI/FastCGI то через php.ini (если я не ошибаюсь) - тут лучше посоветоваться с админами.

    Во всех других случаях - пишите админам.

  3. Комментиров(ал|ала), wws53No Gravatar — 2008-06-03 @ 01:56

    Попытка установить register_globals = off через .htaccess приводит к потере доступа к странице (500 Internal Server Error). Как и куда вставлять директиву для .htaccess?

  4. Комментиров(ал|ала), Сергей КуракинNo Gravatar — 2008-06-03 @ 09:01

    Посмотрите в phpinfo() как установлен PHP. Внимательно смотрите на ключ “Server API” в первой таблице.

    Если там написано Apache, то вам нужно в .htaccess писать php_value register_globals Off.

    Если там написано CGI/FastCGI то попробуйте рядом с файлом положить php.ini и в нём написать register_globals = off.

    Если не помогло, попробуйте тогда прмо в файле написать ini_alter(’register_globals’, ‘Off’);

    Вообще, странно, что у вас register_globals по умолчанию включены.

RSS комментариев. TrackBack URI

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