В избранное    Домой   

Воскресение,  13 Oct 2024 г., 20:20
Если гнев начальника вспыхнет на тебя, то не оставляй места твоего; потому что кротость покрывает и большие проступки. /Екклесиаст/

 Логин:  

 Пароль: 




Анонсы:
=== Дата: 11/10/2011     Автор: Крис Ньюман ===

PHP. Урок 24 Безопасность при использовании PHP

Урок 24. Безопасность при использовании PHP

Несомненно, PHP является очень мощным языком написания сценариев для Web-сервера. Но с большими возможностями появляется большая ответственность. В этом уроке вы узнаете, как использовать безопасный режим PHP, чтобы отключить потенциально опасные возможности PHP.

Безопасный режим

Безопасный режим PHP позволяет реализовать базовую безопасность для общего окружения, когда несколько пользователей используют один Web-сервер с поддержкой PHP.

Если PHP работает в безопасном режиме, выполнение некоторых функций ограничивается, а некоторые отключаются вообще.

Ограничения, налагаемые безопасным режимом

Функции для работы с файловой системой имеют ряд ограничений в безопасном режиме. Процессы Web-сервера работают под одним пользовательским ID для всего Web-пространства и должны иметь права на чтение или изменение, чтобы получить доступ к файлу. Это требование операционной системы и не имеет никакого отношения к PHP.

В безопасном режиме при попытке прочитать или записать в локальный файл PHP проверяет, совпадает ли владелец файла и сценария. Если они отличаются, операция запрещается.

Права на запись. Кроме того, что безопасный режим в PHP запрещает различным владельцам использовать файлы, нужно обеспечить соответствующие права на уровне операционной системы, чтобы иметь возможность читать или записывать файлы. Нужно помнить, что пользователь с возможностью работы в командной оболочке на сервере сможет прочитать любой файл, который доступен для Web-сервера, и записать в любой файл, для которого установлены глобальные права на запись.

Следующие функции для работы с файловой системой ограничиваются этим правилом:

chdir			move_uploaded_file
chgrp			parse_ini_file
chown			rmdir
copy			rename
fopen			require
highlight_file		show_source
include			symlink
link			touch
mkdir			unlink

 

На функции, которые являются частью расширений PHP и работают с файловой системой, также налагаются эти ограничения.

Подгружаемые модули. Функция dl не работает в безопасном режиме, независимо от владельца файла расширения. Расширение нужно загружать при старте PHP с помощью соответствующей инструкции в php.ihi.

Функции, которые выполняют программы сервера, работают только для каталогов, перечисленных в директиве safe_mode_exec_dir. Подробнее о ней можно узнать ниже. Даже если установлено право на выполнение, все аргументы командной строки автоматически передаются функции escapeshellcmd.

Следующие функции, выполняющие системные программы, ограничиваются этим правилом:

exec 			shell_exec
passthru		system
popen

 

Кроме того, отключен оператор апостроф (`).

Функция putenv не работает в безопасном режиме. Но если ее выполнить, сообщения об ошибке не выводятся. Другие функции, изменяющие окружение PHP, такие как set_time_limit и set_include_path, также игнорируются.

Активизация безопасного режима

безопасный режим включается с помощью директивы safe_mode в php.ini. Чтобы включить его для всех пользователей на общем Web-сервере, используется следующая инструкция:

safe_mode = On

Как рассказывалось выше, функции для работы с файловой системой проверяют владельца файла. По умолчанию проверяется соответствие пользовательских ID. Это можно заменить на проверку ID группы(GID) с помощью директивы safe_mode_gid.

Если в файловой системе есть общая библиотека, нужно использовать директиву safe_mode_include_dir. В ней задается список каталогов, которые не проверяются на соответствие UID/GID при операциях include или require.

Каталоги для подключения. Если нужно указать несколько каталогов в инструкции safe_mode_include_dir, можно разделить их с помощью двоеточия в Linux/Unix и точки с запятой для Windows системы. Это аналогично тому, что делается для директивы include_path.

Инструкция ниже разрешает подключать файлы из каталога /usr/local/include/php в безопасном режиме:

safe_mode_include_dir = /usr/local/include/php

Директива safe_mode_exec_dir задает места, из которых можно выполнять программы сервера.

Чтобы разрешить выполнение программ из /usr/local/php-bin в безопасном режиме, используется следующая директива:

safe_mode_exec_dir = /usr/local/php-bin

Возможность выполнения. Не нужно разрешать выполнение всех программ их каталога /usr/bin или другого системного каталога. Лучше создать новый и поместить туда копии или ссылки на необходимые программы.

Директива safe_mode_allowed_env_vars позволяет указать список переменных окружения, которые можно изменять. Заданные значения являются префиксами и по умолчанию это только переменные с PHP_ в начале. Несколько значений разделяются запятой.

В инструкции ниже добавляется разрешение изменять значение часового пояса TZ:

safe_mode_allowed_env_vars = PHP_,TZ

Другие возможности безопасности

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

Сокрытие PHP

C помощью инструкции expose_php в php.ihi можно запретить выводить версию PHP в заголовках Web-сервера:

expose_php = On

C помощью этой инструкции можно помешать автоматическим сценариям атаковать Web-сервер. Обычно в HTTP-заголовках содержится строка, которая выглядит примерно так:

Server: Apache/1.3.33 (Unix) PHP/5.0.3 mod_ssl/2.8.16

При активации expose_php версия PHP не включается в заголовок.

Конечно, расширение .php явно укажет посетителю, что на Web-сервере используется PHP. Если нужно полностью изменить расширение файлов, нужно найти следующую строку в httpd.conf:

AddType application/x/httpd .php

Теперь нужно поменять значение .php на любое другое. Можно задать несколько расширений через пробел. Чтобы PHP отрабатывал файлы .html и .htm и, таким образом, скрывал, какой язык используется на Web-сервере, применяется следующая инструкция:

AddType application/x-httpd .html .htm

Обработка HTML. Возможность обрабатывать HTML-файлы как PHP может быть очень удобной. Но это снижает производительность сервера, в случае статического файла, потому что Web-сервер запускает обработчик PHP. Чтобы этого избежать, для статических страниц нужно использовать другое расширение.

Безопасность файловой системы

Безопасный режим предоставляет доступ к файлу только владельцу. С помощью директивы open_basedir можно задать каталог, в котором должны находится файлы. Если это сделать, PHP отклоняет все попытки доступа к папке, которая не находится в заданном каталоге или подкаталоге. Инструкция open_basedir работает независимо от безопасного режима.

Чтобы ограничить доступ к файловой системе на Web-сервере только каталогом /tmp, используется следующая инструкция:

open_basedir = /tmp

Контроль доступа к функциям

С помощью директивы disable_functions можно задать список PHP-функций, разделенных запятой, которые нужно отключить.

Эта установка работает независимо от безопасного режима. Чтобы отключить функцию dl без включения безопасного режима, достаточно использовать инструкцию:

disable_functions = dl

Таким образом можно отключить доступ к классам с помощью инструкции disable_classes.

Безопасность базы данных

В уроке 18, "Выполнение программ на Web-сервере", показывалось, как злоумышленник может выполнить нужную команду на сервере; чтобы защититься от этого, следует использовать функцию escapeshellcmd.

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

$sql = "UPDATE mytable SET col1 = " . $_POST["value"] . "
        WHERE col2 = 'somevalue'";
$res = mysql_query($sq1, $db);

Ожидается, что $_POST["value"] будет содержать целое значение для столбца col1. Но злоумышленник может ввести точку с запятой и запрос, который нужно выполнить.

Например, в $_POST["value"] находится такое значение:

0; INSERT INTO admin_users (username,password)
VALUES ('me', 'mypassword');

Теперь выполняется такой SQL-запрос (для ясности он приводится в отдельных строках):

UPDATE mytable SET col1 = 0;
INSERT INTO admin_users (username, password)
VALUES ('me', 'mypassword');
WHERE col2 = 'samevalue';

Это очень неприятная ситуация. Первое выражение установит в ноль значение col1 для всех строк в mytable. Это плохо, но второе выражение делает еще хуже - пользователь получает возможность выполнить выражение INSERT, которое создает пользователя с правами администратора. Третье выражение неправильное, но когда анализатор SQL доберется до него, деструктивные действия уже выполнятся. Такой тип атаки называется SQL-подстановкой.

Конечно, для того чтобы нанести ущерб системе, пользователю нужно знать структуру базы данных. В этом примере злоумышленник знает, что в базе есть таблица admin_users с полями username и password, а также то, что пароль не шифруется.

Обычно посетители Web-сайта не знают такой информации о структуре базы, которая строится самостоятельно. Но если на сайте используются компоненты программ с открытым кодом, например бесплатный форум, часть структуры базы может быть известна другим пользователям.

Более того, если сценарий выводит ошибку при неправильном выполнении запроса, это может показать важные детали структуры базы данных. На рабочем Web-сайте нужно установить опцию display_errors в положение off и воспользоваться инструкцией log_errors, чтобы сохранять сообщения об ошибках в файл журнала.

Чтобы избежать SQL-подстановки, нужно убедиться в том, что данные, приходящие от пользователя и подставляющие в запрос, не могут оборвать SQL-выражение.

В предыдущем примере показывалось, как обновляется целое значение. Если это строка, заключенная в одинарные кавычки, злоумышленнику нужно отправить закрывающую кавычку перед точкой с запятой, а после нее вставить SQL-выражение.

Но при включении директивы magic_quotes_gpc кавычка, полученная из формы автоматически разделяется.

Права на базу данных. Очень важно подключаться к базе с правами пользователя, который имеет только необходимые для работы права.
Нельзя соединятся с базой данных через администраторскую учетную запись. Если это сделать, атакующий может получить полный доступ ко всем базам данных на сервере. Кроме того, атакующий может выполнить команды GRANT или CREATE USER и открыть себе полный доступ за приделами сценария.

Для защиты от SQL_подстановок из данных формы нужно также проверять соответствие формата полученных данных. Если в запросе ожидается числовое значение, нужно выполнить проверку с помощью функции is_numeric или использовать функцию settype, чтобы изменить строку на число. Это удаляет все символы, которые могут обмануть SQL.

Если работать с несколькими значениями формы в одном SQL-выражении, лучше использовать функцию sprintf. Это позволяет составить SQL-выражение при помощи символов, которые задают тип данных для каждого значения:

$sql = sprintf("UPDATE mytable SET col1 = %d
        WHERE col2 = '%s',
        $_POST["number"],
        mysql_escape_string($_POST["string"]))";

Пример выше написан для базы данных MySQL, поэтому строка передается функции mysql_escape_string. Для других баз данных нужно правильно разделить символ кавычки с помощью функции addslashes или другого подходящего способа.

Резюме

В этом уроке вы узнали, как обеспечить безопасность динамических страниц с использованием PHP. В следующем уроке вы узнаете о PEAR - базовом источнике библиотек от сторонних разработчиков.


<<назад

Погода в Рудне
(Волгоградcкая обл.)

Подробнее >>


Курс валют
на 13 Окт 2024 г.
704 - Вьетнамских донгов
- 1