 | PHP это субъект системы безопасности, встроенной в
большинство серверных систем, с учётом разрешений на доступ к файлам и на базе
директорий. Это позволяет управлять тем, какие файлы можно читать в файловой системе.
Нужно проявлять осторожность при чтении любых файлов, чтобы гарантировать безопасность
при чтении любыми пользователями, имеющими доступ к данной файловой системе. Поскольку
PHP был разработан так, чтобы дать пользовательский доступ к файловой системе,
можно создать PHP-скрипт, который позволит вам читать такие системные файлы как
/etc/passwd, модифицировать внутрисетевые соединения, отправлять задания принтеру
etc. Это, очевидно, подразумевает, что вы должны быть уверены, что файлы, которые
вы читаете и записываете, являются соответствующими файлами. Рассмотрим
следующий скрипт, где пользователь указывает, что он хотел бы удалить файл в своей
home-директории. Это предполагает ситуацию, когда web-интерфейс РНР регулярно
используется для работы с файлами, как в случае, когда пользователь сервера Apache
может удалять файлы в своих домашних директориях.
Пример 4-1. Плохая проверка переменных ведёт к ...<?php
// удалить файлы из домашней директории пользователя $username = $_POST['user_submitted_name'];
$homedir = "/home/$username"; $file_to_delete = "$userfile"; unlink ($homedir/$userfile);
echo "$file_to_delete has been deleted!"; ?> |
|
Поскольку
username отправляется из пользовательской формы методом post, можно отправлять
username и файл, принадлежащие кому-либо ещё, и удалять файлы. В этом случае может
понадобиться использование какой-нибудь иной формы аутентификации. Посмотрим,
что произойдёт, если будут отправлены переменные "../etc/" и "passwd". Код тогда
сможет эффективно читать:
Пример 4-2. ... атака на файловую систему
<?php // Удалить файл с жёсткого диске, доступ к которому имеет пользователь
РНР. // Если РНР имеет root-доступ: $username = "../etc/"; $homedir = "/home/../etc/";
$file_to_delete = "passwd"; unlink ("/home/../etc/passwd"); echo "/home/../etc/passwd
has been deleted!"; ?> |
|
Есть два
средства, которые вы должны использовать для предотвращения такого поведения.
Давать web-пользователю только ограниченный доступ к экзешнику PHP. Проверять
все переменные, которые отправляются из формы. Вот улучшенный скрипт:
Пример 4-3. Более безопасная проверка имени файла
<?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");
//log удаление $logstring = "$username $homedir $file_to_delete"; fputs ($fp,
$logstring); fclose($fp); echo "$file_to_delete has been deleted!"; ?> | |
Однако
и здесь не без недостатков. Если ваша система аутентификации разрешает пользователям
создавать свои собственные пользовательские login'ы и пользователь выберет логин
"../etc/", система снова станет открытой. Исходя из этого, вам может понадобиться
более специализированная проверка:
Пример 4-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),
etc. Поэтому обычно легче реализовать такую политику, когда вы запрещаете
всё, за исключением того, что явно разрешено. |  |