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

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

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

register_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.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Защита от многократной отправки одной и той же формы
Использование элементов формы с несколькими вариантами значений
Кэширование запросов и результатов
Обработка внешних переменных с точками в именах
Обработка загруженных файлов

Вернуться в раздел: PHP / 9. Формы