- Организация безопасности обработки форм в PHP

Разработчику. Сборник рецептов PHP
Задавайте вопросы

Организация безопасности обработки
форм в PHP

Вернуться назад

Задача

Необходимо обеспечить безопасную обработку входных переменных формы и не позволить какому-нибудь злоумышленнику изменить переменные в вашей программе.

Решение

Заблокируйте параметр конфигурации register_globals и обращайтесь только к переменным из массива $_REQUEST. Чтобы обеспечить еще более крепкую защиту, используйте массивы $_GET, $_POST и $_COOKIE для полной уверенности в том, откуда берутся переменные.

Чтобы выполнить это, убедитесь, что соответствующая строка в файле php.ini выглядит следующим образом:

egister_globals = Off

Что касается версии PHP 4.2, то в ней это значение устанавливается по умолчанию.

Обсуждение

Если параметр register_globals установлен в on, то внешние переменные, включая переменные из форм и cookies, импортируются прямо в глобальное пространство имен. Это очень удобно, но может привести к образованию брешей в безопасности, если вы не очень старательно проверяете переменные и место, где они определяются. Почему? Потому что может существовать переменная, с которой вы работаете внутри и не предполагаете ее использования снаружи, но ее значение было переписано без вашего ведома.

Ниже приведен простой пример. Есть страница, на которой вводится имя пользователя и пароль. Если они достоверны, то пользователю посылается его идентификационный номер и этот числовой идентификатор применяется для поиска и печати его персональной информации:

// предполагаем, что опция magic_quotes_gpc установлена в Off
$username = $dbh->quote($_GET['username']);
$password = $dbh->quote($_GET['password']);
$sth = $dbh->query("SELECT id FROM users WHERE username = $username AND
               password = $password");

if (1 == $sth >numRows()) {
     $row = $sth->fetchRow(DB_FETCHMODE_OBJECT);
     $id = $row->id;
} else {
     "Print bad username and password";

}

if (!empty($id)) {
     $sth = $dbh->query("SELECT * FROM profile WHERE id = $id");

}

Обычно $id устанавливается вашей программой и представляет собою проверенный результат поиска в базе данных. Тем не менее, если кто-то изменяет строку GET и передает значение $id, в то время как параметр register_globals установлен в on, то даже после отрицательного результата поиска имени пользователя и пароля ваш сценарий выполнит второй запрос в базу данных и возвратит результат. Если register_globals не установлен в on, то в $id не будет никакого значения, так как установлены только элементы $_REQUEST['id'] и $_GET['id'].

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

$sth = $dbh->query("SELECT id FROM users WHERE username = $username AND
          password = $password");

if (1 == $sth->numRows()) {
     $row = $sth->fetchRow(DB_FETCHMODE_OBJECT);
     $id = $row->id;
     if (!empty($id)) {
          $sth = $dbh->query("SELECT * FROM profile WHERE id = $id");

     }

} else {
     "Print bad username and password";

}

Теперь вы используете переменную $id, только если она явным образом установлена в результате запроса базы данных. Однако иногда это трудно сделать из-за структуры программы. Другое решение состоит в том, чтобы вручную сбросить переменную с помощью функции unset() или инициализировать все переменные в начале сценария:

unset($id);

Таким образом, неправильное значение переменной id удаляется до того, как оно сможет повлиять на вашу программу. Однако поскольку PHP не требует инициализировать переменную, можно забыть сделать это в одном месте; ошибка может вкрасться без предупреждения со стороны PHP.

См. также

Документацию по register_globals на http://www.php.net/security.registerglobals.php.

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования


Рейтинг Сайтов ДОСКИ.РУ