Руководство по PHP
Пред. |  | След.

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

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

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

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

Пример 26-1. Недостаточная проверка внешних данных.

`<?php // Удаление файла из домашней директории пользователя $username = $_POST['user_submitted_name']; $homedir = "/home/$username"; $file_to_delete = "$userfile"; unlink ("$homedir/$userfile"); echo "$file_to_delete has been deleted!"; ?>`

Поскольку переменные вводятся в пользовательской форме, существует возможность удалить файлы, принадлежащие кому-либо другому, введя соответствующие значения. В этом случае может понадобиться авторизация. Посмотрим, что произойдет, если будут отправлены значения "../etc/" и "passwd". Скрипт выполнит следующие действия:

Пример 26-2. Атака на файловую систему

`<?php // Удаление любого файла, доступного из PHP-скрипта. // В случае, если PHP работает с правами пользователя root: $username = "../etc/"; $homedir = "/home/../etc/"; $file_to_delete = "passwd"; unlink ("/home/../etc/passwd"); echo "/home/../etc/passwd has been deleted!"; ?>`

Cуществуют два решения описанной проблемы.

- Ограничить доступ пользователя, с правами которого работает веб-сервер.

- Проверять все данные, вводимые пользователем.

Вот улучшеный вариант кода:

Пример 26-3. Более безопасная проверка имени файла

`<?php
// Удаление любого файла, доступного из PHP-скрипта.
$username = $_SERVER['REMOTE_USER']; // использование авторизации
$homedir = "/home/$username";
$file_to_delete = basename("$userfile"); // усечение пути
unlink ($homedir/$file_to_delete);
$fp = fopen("/home/logging/filedelete.log","+a"); //логируем удаление
$logstring = "$username $homedir $file_to_delete";
fwrite ($fp, $logstring);
fclose($fp);
echo "$file_to_delete has been deleted!";
?>`

Однако и такая проверка не учитывает все возможные ситуации. Если система авторизации позволяет пользователям выбирать произвольные логины, вломщик может создать учетную запись вида "../etc/" и система опять окажется уязвимой. Исходя из этого, вам может понадобиться более строгая проверка:

Пример 26-4. Более строгая проверка имени файла

`<?php $username = $_SERVER['REMOTE_USER']; // использование авторизации $homedir = "/home/$username"; if (!ereg('^[^./][^/]*$', $userfile)) die('bad filename'); //завершение работы if (!ereg('^[^./][^/]*$', $username)) die('bad username'); //завершение работы //etc... ?>`

В зависимости от используемой вами операционной системы необходимо предусматривать возможность атаки на разнообразные файлы, включая системные файлы устройств (/dev/ или COM1), конфигурационные файлы (например /etc/ или файлы с расширением .ini), хорошо известные области хранения данных (/home/, My Documents), и так далее. Исходя из этого, как правило, легче реализовать такую политику безопасности, в которой запрещено все, исключая то, что явно разрешено.

Пред. | Начало | След.
Если PHP установлен как модуль Apache | Уровень выше | Безопасность баз данных