Приветствую, я надеюсь сделать свою крошечную программу безопасной, чтобы потенциальные злонамеренные пользователи не могли просматривать конфиденциальные файлы на сервере.
$path = "/home/gsmcms/public_html/central/app/webroot/{$_GET['file']}"; if(file_exists($path)) { echo file_get_contents($path); } else { header('HTTP/1.1 404 Not Found'); }
С головы до ног я знаю, что ввод, такой как «../../../../../../etc/passwd», будет проблемой, но интересно, какие другие вредоносные входы я должен ожидать и как чтобы предотвратить их.
realpath () позволит вам преобразовать любой путь, который может содержать относительную информацию, в абсолютный путь … тогда вы можете убедиться, что путь находится под определенным подкаталогом, из которого вы хотите разрешить загрузку.
Используйте basename вместо того, чтобы пытаться предвидеть все небезопасные пути, которые пользователь мог бы предоставить.
Если вы можете, используйте белый список, как массив разрешенных файлов, и проверьте его на вход: если файл, заданный пользователем, отсутствует в этом списке, отклоните запрос.
Решение OP:
$baseDir = "/home/gsmcms/public_html/central/app/webroot/"; $path = realpath($baseDir . $_GET['file']); // if baseDir isn't at the front 0==strpos, most likely hacking attempt if(strpos($path, $baseDir) !== 0 || strpos($path, $baseDir) === false) { die('Invalid Path'); } elseif(file_exists($path)) { echo file_get_contents($path); } else { header('HTTP/1.1 404 Not Found'); echo "The requested file could not be found"; }
Здесь существует дополнительный и значительный риск для безопасности. Этот скрипт будет вставлять источник файла в выходной поток без обработки на стороне сервера. Это означает, что весь исходный код любых доступных файлов будет просочиться в Интернет.
Даже если вы используете realpath, вам все равно нужно снять все «..», прежде чем использовать его. В противном случае злоумышленник может прочитать всю структуру каталогов со всей грубой силой, например «valid_folder /../../ test_if_this_folder_name_exists / valid_folder» – если приложение принимает этот путь, злоумышленник знает, что папка существует.
Чтобы удалить все /. /..
/. /..
или \. \ .. и конвертировать во всю косую черту, потому что разные среды будут принимать косую черту. Это должно обеспечить достаточно безопасный фильтр для ввода пути. В вашем коде вы должны сравнивать его с родительскими каталогами, которые вам не нужны на всякий случай.
$path = realpath(implode('/', array_map(function($value) {return trim($value, '.');}, explode('/', str_replace('\\', '/', $path)))));