Безопасность файловой системы
PHP является одним из важных моментов в вопросе безопасности сервера,
поскольку PHP-скрипты могут манипулировать файлами и каталогами
на диске. В связи с этим существуют конфигурационные настройки,
указывающие, какие файлы могут быть доступны и какие операции с ними можно
выполнять. Необходимо проявлять осторожность, поскольку любой из файлов,
с полными правами чтения ("world readable") может быть прочитан
каждым, кто имеет доступ к файловой системе.
Поскольку в PHP изначально предполагался полноправный пользовательский
доступ к файловой системе, можно написать PHP-скрипт,
который позволит читать системные файлы, такие как /etc/passwd,
управлять сетевыми соединениями, отправлять задания принтеру, и
так далее. Как следствие, вы всегда должны быть уверены в том, что
файлы, которые вы читаете или модифицируете, являются именно теми,
которые вы подразумевали.
Рассмотрим следующий пример, в котором пользователь создал скрипт, удаляющий
файл из его домашней директории. Предполагается ситуация, когда веб-интерфейс,
написанный на PHP, регулярно используется для
работы с файлами, и настройки безопасности позволяют удалять
файлы в домашнем каталоге.
Недостаточная проверка внешних данных ведёт к...
]]>
Поскольку переменные вводятся в пользовательской форме, существует
возможность удалить файлы, принадлежащие кому-либо другому, введя
соответствующие значения. В этом случае может понадобиться авторизация.
Посмотрим, что произойдёт, если будут отправлены значения
"../etc/" и "passwd". Скрипт выполнит следующие действия:
... атаке на файловую систему
]]>
Существуют две важные меры, которые можно предпринять для предотвращения
описанной проблемы.
Ограничить доступ пользователя, с правами которого работает веб-сервер
с PHP.
Проверять все данные, вводимые пользователем.
Вот улучшенный вариант кода:
Более безопасная проверка имени файла
]]>
Однако и такая проверка не учитывает все возможные ситуации. Если
система авторизации позволяет пользователям выбирать произвольные логины,
взломщик может создать учётную запись вида "../etc/" и система опять
окажется уязвимой. Исходя из этого, вам может понадобиться более строгая проверка:
Более строгая проверка имени файла
]]>
В зависимости от используемой вами операционной системы необходимо
предусматривать возможность атаки на разнообразные файлы, включая
системные файлы устройств (/dev/ или COM1), конфигурационные файлы
(например /etc/ или файлы с расширением .ini), хорошо известные
области хранения данных (/home/, My Documents), и так далее.
Исходя из этого, как правило, легче реализовать такую политику
безопасности, в которой запрещено все, исключая то, что явно
разрешено.
Проблемы безопасности, связанные с нулевым байтом
Так как для работы с файловой системой PHP
использует нижележащие C-функции, то в этом случае возможна
крайне неожиданная обработка нулевого байта.
Так как нулевой байт означает конец строки в C, то строки, содержащие
такой байт, не будут трактоваться полностью, а только до той
позиции, в которой находится этот байт.
Следующий пример содержит уязвимый код, демонстрирующий эту проблему:
Скрипт, уязвимый к нулевому байту
]]>
Таким образом, любая испорченная строка, используемая в операциях
с файловой системой должна быть соответствующим образом проверена.
Вот улучшенная версия предыдущего примера:
Корректная проверка входных данных
]]>