Ответ 1
realpath() позволит вам конвертировать любой путь, который может содержать относительную информацию, в абсолютный путь... тогда вы можете убедиться, что путь под определенным подкаталогом, из которого вы хотите разрешить загрузку.
Привет, Я надеюсь сделать свою крошечную программу безопасной, чтобы потенциальные злонамеренные пользователи не могли просматривать конфиденциальные файлы на сервере.
$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";
}
Здесь существует дополнительный и значительный риск для безопасности. Этот script будет вставлять источник файла в выходной поток без обработки на стороне сервера. Это означает, что весь исходный код любых доступных файлов будет просочиться в Интернет.
Даже если вы используете 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)))));