From da62e70c02a969e038496d0716dda66c6b62673a Mon Sep 17 00:00:00 2001 From: Ryan Date: Fri, 4 Apr 2025 18:02:21 -0400 Subject: [PATCH] mitigate path traversal vulnerability by validating folder and file inputs --- download.php | 60 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/download.php b/download.php index b6452cd..2ec11cf 100644 --- a/download.php +++ b/download.php @@ -1,8 +1,6 @@ "Server misconfiguration."]); + exit; } -$filePath = $directory . $file; +// Determine the directory. +if ($folder === 'root') { + $directory = $uploadDirReal; +} else { + // Prevent path traversal in folder parameter. + if (strpos($folder, '..') !== false) { + http_response_code(400); + echo json_encode(["error" => "Invalid folder name."]); + exit; + } + + $directoryPath = rtrim(UPLOAD_DIR, '/\\') . DIRECTORY_SEPARATOR . $folder; + $directory = realpath($directoryPath); + + // Ensure that the resolved directory exists and is within the allowed UPLOAD_DIR. + if ($directory === false || strpos($directory, $uploadDirReal) !== 0) { + http_response_code(400); + echo json_encode(["error" => "Invalid folder path."]); + exit; + } +} -if (!file_exists($filePath)) { +// Build the file path. +$filePath = $directory . DIRECTORY_SEPARATOR . $file; +$realFilePath = realpath($filePath); + +// Validate that the real file path exists and is within the allowed directory. +if ($realFilePath === false || strpos($realFilePath, $uploadDirReal) !== 0) { + http_response_code(403); + echo json_encode(["error" => "Access forbidden."]); + exit; +} + +if (!file_exists($realFilePath)) { http_response_code(404); echo json_encode(["error" => "File not found."]); exit; } // Serve the file. -$mimeType = mime_content_type($filePath); +$mimeType = mime_content_type($realFilePath); header("Content-Type: " . $mimeType); // For images, serve inline; for other types, force download. -$ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); +$ext = strtolower(pathinfo($realFilePath, PATHINFO_EXTENSION)); if (in_array($ext, ['jpg','jpeg','png','gif','bmp','webp','svg','ico'])) { - header('Content-Disposition: inline; filename="' . basename($filePath) . '"'); + header('Content-Disposition: inline; filename="' . basename($realFilePath) . '"'); } else { - header('Content-Disposition: attachment; filename="' . basename($filePath) . '"'); + header('Content-Disposition: attachment; filename="' . basename($realFilePath) . '"'); } -header('Content-Length: ' . filesize($filePath)); +header('Content-Length: ' . filesize($realFilePath)); // Disable caching. header('Cache-Control: no-store, no-cache, must-revalidate'); header('Pragma: no-cache'); -readfile($filePath); +readfile($realFilePath); exit; ?> \ No newline at end of file