-
Необходимо обеспечить безопасную обработку входных переменных формы и не позволить какому-нибудь злоумышленнику изменить переменные в вашей программе.
Заблокируйте параметр конфигурации 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.