Основы PHP
  Что такое PHP?
  Возможности PHP
  Преимущества PHP
  История развития
  Что нового в PHP5?
  «Движок» PHP
  Переход на PHP 5.3
New Переход на PHP 5.6
  Введение в PHP
  Изучение PHP
  Основы CGI
  Синтаксис PHP
  Типы данных PHP
  Переменные в PHP
  Константы PHP
  Выражения PHP
  Операторы PHP
  Конструкции PHP
  Ссылки в PHP
  PHP и ООП
  Безопасность
  Функции PHP
  Функции по категориям
  Функции по алфавиту
  Стандартные функции
  Пользовательские
  PHP и HTTP
  Работа с формами
  PHP и Upload
  PHP и Cookies
  PHP и базы данных
  PHP и MySQL
  Документация MySQL
  Учебники
  Учебники по PHP
  Учебники по MySQL
  Другие учебники
  Уроки PHP
  Введение
  Самые основы
  Управление
  Функции
  Документация
  Математика
  Файлы
  Основы SQL
  Дата и время
  CURL
  Изображения
  Стили
  Безопасность
  Установка
  Проектирование БД
  Регулярные выражения
  Подготовка к работе
  Быстрый старт
  Установка PHP
  Установка MySQL
  Конфигурация PHP
  Download / Скачать
  Скачать Apache
  Скачать PHP
  Скачать PECL
  Скачать PEAR
  Скачать MySQL
  Редакторы PHP
  Полезные утилиты
  Документация
  PHP скрипты
  Скачать скрипты
  Инструменты
  PHP в примерах
  Новости портала
 Главная   »  Сборник статей
 
 

Безопасность и глобальные переменные в PHP

Автор: David Lechnyr
Источник: providerz.ru

Однажды мы с супругой решили покататься на лыжах. Чтобы забронировать необходимую экипировку, необходимо было подать заявку на сайте фирмы, дающей все необходимое на прокат, не позднее чем за сутки. Вся беда была в том, что эта идея пришла к нам в голову за 23 часа до нужного срока.

Поэтому мне пришлось крепко призадуматься и заняться исследованием сайта, который не позволял забронировать все что нам нужно менее чем за 24 часа до нужного срока. Когда я выбрал текущую дату, то заметил, что URL приобрел такой вид:

https://www.somewhere.com/reservations.php?date=01-23-01

Я понял, что меня ограничили при выборе минимальной даты, но при этом запрашиваемую дату они поместили в инструкцию GET, в конце адресной строки. Я вручную изменил адрес так, чтобы он указывал на требуемую мне дату -- "date=01-22-01" и в результате -- на следующее утро наши лыжи уже ждали нас!

Этот довольно невинный пример достаточно ярко демонстрирует одну из опасностей, о которых мы должны знать при создании программ на любом языке программирования. Данная опасность состоит в том, что программа может быть использована способами не предусмотренными заранее. А теперь, после столь краткого вступления, можно перейти к обсуждению суперглобальных массивов в PHP.

Формы

Для того, чтобы понять почему так важны суперглобальные массивы (Superglobals) в PHP нам необходимо разобраться с тем, как передаются данные от одной web-страницы к другой. Определенно, вы уже должны знать, по крайней мере, о двух способах передачи данных, известных как GET и POST. Так же вы, скорее всего, уже должны быть знакомы с тегом <FORM> языка разметки HTML (загляните на http://www.w3.org/TR/html401/interact/forms.html).

Вероятно вы уже видели нечто подобное и раньше:

<form name="form1" method="post" action="process.php">
<p>Please enter your name:</p>
<p><input type="text" name="yourname" /></p>
<p><input type="button" name="Submit" value="Submit" /></p>
</form>

Это обычный код формы HTML, не представляющий из себя ничего необычного. Он запрашивает некоторые сведения у пользователя и затем передает полученные данные файлу (сценарию на языке PHP) "process.php" . Критическая точка здесь -- это объявление метода, которым будут переданы данные:

Если кто-то из читателей застал эпоху появления HTML на свет, тот наверняка вспомнит, что в те времена формы в HTML отсутствовали, а для того, чтобы запросить данные, приходилось вставлять тег <ISINDEX> в разделе <HEAD>. По мере развития, в HTML появился новый тег -- <FORM>, которому в атрибуте METHOD стало возможным указать метод передачи GET, POST или PUT. Теперь познакомимся с этими методами поближе.

GET

Метод GET, передает имена переменных и их значения через заголовок URL (адреса), добавляя их в конец URL. Такой метод передачи данных ограничен максимально возможной длиной строки URL, которая составляет 8192 символа. Если объем данных превышает это значение, то все что находится за пределами верхней границы будет попросту потеряно. Более того, даже на SSL соединениях данные не шифруются, поскольку они являются частью web-адреса.

Ниже приводится пример формы, которая могла бы быть размещена на web-страничке:

<form name="form1" method="get" action="process.php">
<p>Пожалуйста, укажите Ваше имя, адрес электронной почты, и примечания:</p>
<p><input type="text" name="yourname" /></p>
<p><input type="text" name="email" /></p>
<p><input type="text" name="comment" /></p>
<p><input type="button" name="Submit" value="Отправить" /></p>
</form>

Когда пользователь щелкает по кнопке Отправить, то браузер забирает значения из полей формы и отправляет их по адресу:

http://www.fluffygerbil.com/process.php?yourname=fred+smith&email=fred@nowhere.com&comment=I+have+no+comment

Заметили как значения, введенные в форму, стали частью адреса? В этом и состоит суть метода GET.

Для любопытных ниже приводится содержимое HTTP-запроса:

GET /process.php?yourname=fred+smith&email=fred@nowhere.com&comment=I+have+no+comment HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, */*
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)
Host: www.fluffygerbils.com
Connection: keep-alive

POST

Метод POST, передает имена переменных и их значения в теле запроса URL, а не в заголовке. Преимущества такого способа передачи данных состоят в том, что снимаются ограничения на объем передаваемых данных, поскольку они располагаются в теле запроса HTTP, а не в заголовке. Дополнительно, если вами используется SSL соединение, то данные проходят по сети в зашифрованном виде. Ниже приводится пример формы, использующей метод POST для передачи данных:

<form name="form1" method="post" action="process.php">
<p>Пожалуйста, укажите Ваше имя, адрес электронной почты, и примечания:</p>
<p><input type="text" name="yourname" /></p>
<p><input type="text" name="email" /></p>
<p><input type="text" name="comment" /></p>
<p><input type="button" name="Submit" value="Отправить" /></p>
</form>

Когда пользователь щелкает по кнопке Отправить, то браузер забирает значения из полей формы и отправляет их по адресу:

http://www.fluffygerbil.com/process.php

Заметили, что теперь данные уже не являются частью адреса? В этом и состоит суть метода POST.

Для любопытных ниже приводится содержимое HTTP-запроса:

POST /process.php HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, */*
Accept-Language: en-us
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)
Host: www.fluffygerbils.com
Content-Length: 94
Pragma: no-cache
Connection: keep-alive

yourname=fred+smith
email=fred@nowhere.com
comment=I+have+no+comment

Что дальше?

Итак, какая же нам польза от этих сведений? Возможно вы уже обращали внимание на появляющееся во время установки PHP такое вот сообщение:

    +--------------------------------------------------------------------+
                               *** NOTE ***                               
                 The default for register_globals is now OFF!             
                                                                          
      If your application relies on register_globals being ON, you        
      should explicitly set it to on in your php.ini file.                
      Note that you are strongly encouraged to read                       
      http://www.php.net/manual/en/security.registerglobals.php           
      about the implications of having register_globals set to on, and    
      avoid using it if possible.                                         
    +--------------------------------------------------------------------+
  
    +--------------------------------------------------------------------+
                             *** ВНИМАНИЕ ***                             
               Теперь, по-умолчанию register_globals отключены!           
                                                                          
      Если ваши приложения требуют наличия этой возможности, то вы        
      должны явно включить ее в вашем файле php.ini.                      
      Настоятельно рекомендуем вам прочитать                              
      http://www.php.net/manual/en/security.registerglobals.php           
      о назначении register_globals и избегать их использования           
      настолько, насколько это возможно.                                  
    +--------------------------------------------------------------------+

Это говорит о том, что PHP проявляет крайне параноидальную озабоченность по поводу сохранности передаваемых ему данных и требует, чтобы вы точно определили метод передачи данных. Кроме того вы должны знать, что кроме GET и POST существуют и другие методы передачи данных web-страничкам:


1

Суперглобальные массивы в PHP (Superglobals)

Суперглобальные массивы -- это относительно новая идея в PHP. Внимательно рассмотрите диаграмму, представленную выше. Представьте, к примеру, что вы работаете с переменной $yourname, а теперь скажите -- можете ли вы быть абсолютно уверены в том, что в ходе исполнения сценария эта переменная не была переопределена одним из приведенных шести способов, кем либо, пытающимся взломать сценарий? Например, вообразите себе, что некто сумел закачать на ваш WEB-сервер со следующим содержанием:

<?php
setcookie("test","../../../../../../etc/passwd");
echo "cookie inserted";
?>

Было бы великолепно иметь возможность изолировать переменные, исходя из того, каким методом они могут быть изменены. Суперглобальные массивы позволят точно определить каким способом переменная может получить свое значение.

Суперглобальные массивы -- это попытка PHP помочь вам определить -- каким образом переменная получила свое значение. Если вы ничего ранее не слышали об этой новой особенности PHP, которая появилась в версии 4.1.0, то теперь вы наверняка захотите использовать ее. Большая часть руководств по языку PHP совершенно не касается этой темы, поэтому вам необходимо знать о том, как перейти к использованию superglobals. В общем, вам надо открыть ваш файл /usr/local/lib/php.ini и внести следующие изменения:

register_globals = Off

Это предотвратит возможность изменения переменных сценария со стороны пользователя и тем самым ограничить возможности вероятных злоумышленников. Они будут вынуждены потратить значительное время, чтобы попытаться изобрести что-то новое, в то время как ваши внутренние переменные будут надежно изолированы от данных, поступающих извне. Если пользователь заполнит форму (упоминавшуюся выше), то сервер запомнит введенные данные не в глобальных переменных $name, $email или $comment, а в хэш-массиве:

$_POST['name']
$_POST['email']
$_POST['comment']

Основные суперглобальные массивы:

  1. $_GET['variable'] - Переменные, переданные сценарию через HTTP GET. Аналогичен массиву $HTTP_GET_VARS
  2. $_POST['variable'] - Переменные, переданные сценарию через HTTP POST. Аналогичен массиву $HTTP_POST_VARS

Другие суперглобальные массивы:

  1. $_COOKIE['variable'] - Переменные, переданные сценарию через HTTP cookies. Аналогичен массиву $HTTP_COOKIE_VARS
  2. $_REQUEST['variable'] - Переменные, переданные сценарию в результате ответа пользователя на запрос (GET, POST, COOKIE) и которым, поэтому, не следует доверять.
  3. $_GLOBALS['variable'] - Содержит ссылки на все переменные, которые в настоящий момент доступны в глобальной области видимости сценария. Ключами этого массива являются имена глобальных переменных.
  4. $_SERVER['variable'] - Переменные, установленные web-сервером или чем-то другим, напрямую связанным со средой исполнения сценария. Аналогичен массиву $HTTP_SERVER_VARS
  5. $_FILES['variable'] - Переменные, переданные сценарию путем передачи файла через HTTP. Аналогичен массиву $HTTP_POST_FILES
  6. $_ENV['variable'] - Переменные, переданные сценарию через окружение. Аналогичен массиву $HTTP_ENV_VARS
  7. $_SESSION['variable'] - Переменные, которые определены в текущей сессии сценария. Аналогичен массиву $HTTP_SESSION_VARS

Дополнительные сведения вы найдете в http://www.php.su/learnphp/vars/?reserved.

Таким образом, вместо переменной $name, в которую записано, к примеру, имя "John", вы получите или $_GET['name'] = "John" или $_POST['name'] = "John", в зависимости от того, каким способом была передана эта переменная. Преимущество состоит в том, что:

  1. Переменная $name никогда не сможет быть изменена внешним пользователем; если сценарий записал туда некое значение, то оно там и останется!
  2. Массивы $_GET и $_POST помогут вам отделить данные, пришедшие от формы методом POST (в теле запроса) от данных, добавленных кем-либо, пытающимся имитировать передачу данных методом GET, в конец адресной строки. И это здорово...
  3. Суперглобальные массивы позволят вам не только изолировать значения переменных, но и разнести их по категориям, в зависимости от способа доставки на сервер. А кое-кому значительно усложнят взлом вашего сервера.

Заключение

Еще не так давно программирование на PHP могло доставить огорчения. Меры безопасности препятствуют возможности подмены значений переменных. Провайдеры услуг в Интернет (ISP), предоставляющие в распоряжение пользователей возможности PHP, обычно не учитывают уровень подготовки своей аудитории и озадачивают новичков в PHP такими понятиями, как GET, POST, Superglobals и так далее. Однако, недостаток знаний может сподвигнуть на долгий путь и я надеюсь, что эта статья помогла вам в ваших поисках.

Этот документ был написан, основываясь на PHP 4.3.0.

David работает сетевым администратором в отделе Человеческих Ресурсов, в университете штата Орегон. Он обладает степенью Магистра в сфере социальных проблем, а также имеет сертификаты MCSE+I, CNE и CCNA. С ОС Linux работает на протяжении последних шести лет, занимаясь в основном проблемами безопасности, обслуживанием сети, и интеграцией PHP/MySQL.

 
 » Обсудить эту статью на форуме

 
 Сборник статей 
 Содержание раздела 
Есть еще вопросы или что-то непонятно - добро пожаловать на наш  форум портала PHP.SU 
 

 
Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS