1.修复上传漏洞和SQL注入漏洞
This commit is contained in:
@@ -95,7 +95,12 @@ class Manage
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0755, true);
|
||||
}
|
||||
$saveName = 'temp' . DIRECTORY_SEPARATOR . date('YmdHis') . '_' . ($file->getUploadName() ?? 'module.zip');
|
||||
$originalName = $file->getUploadName() ?? 'module.zip';
|
||||
$baseName = basename(str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $originalName));
|
||||
if (!preg_match('/^[a-zA-Z0-9._-]+\.zip$/i', $baseName)) {
|
||||
throw new Exception('The uploaded file format is not allowed');
|
||||
}
|
||||
$saveName = 'temp' . DIRECTORY_SEPARATOR . date('YmdHis') . '_' . $baseName;
|
||||
$savePath = $uploadDir . $saveName;
|
||||
$saveDir = dirname($savePath);
|
||||
if (!is_dir($saveDir)) {
|
||||
@@ -155,10 +160,7 @@ class Manage
|
||||
*/
|
||||
public function doUpload(string $token, string $file): array
|
||||
{
|
||||
$file = Filesystem::fsFit(root_path() . 'public' . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $file));
|
||||
if (!is_file($file)) {
|
||||
throw new Exception('Zip file not found');
|
||||
}
|
||||
$file = self::resolvePublicStorageFile($file);
|
||||
|
||||
$copyTo = $this->installDir . 'uploadTemp' . date('YmdHis') . '.zip';
|
||||
copy($file, $copyTo);
|
||||
@@ -897,4 +899,52 @@ class Manage
|
||||
$this->modulesDir = $this->installDir . $uid . DIRECTORY_SEPARATOR;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析并校验模块包路径,仅允许 public/storage 下的 zip 文件,防止路径穿越
|
||||
* @throws Exception
|
||||
*/
|
||||
protected static function resolvePublicStorageFile(string $file): string
|
||||
{
|
||||
if (preg_match('#^(https?:)?//#i', $file)) {
|
||||
$parsed = parse_url($file);
|
||||
$file = $parsed['path'] ?? '';
|
||||
}
|
||||
|
||||
$relative = ltrim(str_replace('\\', '/', $file), '/');
|
||||
if ($relative === '' || str_contains($relative, '..')) {
|
||||
throw new Exception('Invalid file path');
|
||||
}
|
||||
|
||||
$publicRoot = realpath(public_path());
|
||||
if ($publicRoot === false) {
|
||||
throw new Exception('Invalid file path');
|
||||
}
|
||||
|
||||
$candidate = Filesystem::fsFit($publicRoot . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relative));
|
||||
$fullPath = realpath($candidate);
|
||||
if ($fullPath === false || !is_file($fullPath)) {
|
||||
throw new Exception('Zip file not found');
|
||||
}
|
||||
|
||||
$publicPrefix = rtrim($publicRoot, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
if (!str_starts_with($fullPath, $publicPrefix)) {
|
||||
throw new Exception('Invalid file path');
|
||||
}
|
||||
|
||||
$storageRoot = realpath(public_path('storage'));
|
||||
if ($storageRoot === false) {
|
||||
throw new Exception('Invalid file path');
|
||||
}
|
||||
$storagePrefix = rtrim($storageRoot, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
if (!str_starts_with($fullPath, $storagePrefix)) {
|
||||
throw new Exception('Invalid file path');
|
||||
}
|
||||
|
||||
if (strtolower(pathinfo($fullPath, PATHINFO_EXTENSION)) !== 'zip') {
|
||||
throw new Exception('The uploaded file format is not allowed');
|
||||
}
|
||||
|
||||
return $fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user