如何修复Laravel代码中用户可控路径构造的安全漏洞?
修复Laravel中用户可控路径构造的安全漏洞
存在安全风险的原代码
public function exportRule(Request $request) { $checkRequest = DB::table('table')->where('id', $request->id)->count(); if (!$checkRequest) { return "unable to find requested id"; } $requestId = $request->id; $filename = "rules-" . date("mdyhis") . ".xlsx"; $dir = $this->exportUrl . $requestId; if (is_dir($dir)) { foreach (scandir($dir) as $file) { if ("." === $file || ".." === $file) { continue; } if (is_dir("$dir/$file")) { rmdir_recursive("$dir/$file"); } else { unlink("$dir/$file"); } } rmdir($dir); } Excel::store( new RulesExport(["request_id" => $requestId]), "$requestId/$filename", ExcelExcel::XLSX ); $encypfile = hash_file( "sha256", $this->exportUrl . $requestId . "/$filename" ); Storage::put("public/export/$requestId/$encypfile.txt", $encypfile); return Excel::download( new RulesExport(["request_id" => $requestId]), $filename, ExcelExcel::XLSX ); }
漏洞分析
这段代码的核心风险是用户可控的$request->id直接被用于构造文件系统路径,攻击者可构造含../等目录遍历字符的请求,实现对服务器任意文件的删除或访问:
- 用户传入恶意
id值(如../../../../etc/passwd) - 该值直接赋值给
$requestId,并被拼接进$dir、存储路径、哈希计算路径等多个位置 - 后续的
scandir、unlink、rmdir等文件系统操作会使用这些恶意路径,引发目录遍历攻击,可能删除服务器重要文件或访问敏感数据
修复后的代码
use Illuminate\Support\Facades\Storage; public function exportRule(Request $request) { // 1. 验证输入合法性,确保id为整数且存在于数据库 $validated = $request->validate([ 'id' => 'required|integer|exists:table,id' ]); // 2. 从数据库获取可信的记录ID,避免直接使用用户输入值 $record = DB::table('table')->find($validated['id']); $requestId = $record->id; $filename = "rules-" . date("mdyhis") . ".xlsx"; $disk = Storage::disk('public'); $exportBasePath = "export/$requestId"; // 3. 用Storage门面安全清理目录,替代手动文件系统操作 if ($disk->exists($exportBasePath)) { $disk->deleteDirectory($exportBasePath); } // 4. 安全存储Excel文件,依赖Storage处理路径 Excel::store( new RulesExport(["request_id" => $requestId]), "$exportBasePath/$filename", ExcelExcel::XLSX ); // 5. 通过Storage获取合法文件路径,避免手动拼接 $filePath = $disk->path("$exportBasePath/$filename"); $encypfile = hash_file("sha256", $filePath); // 6. 安全存储哈希文件 $disk->put("$exportBasePath/$encypfile.txt", $encypfile); return Excel::download( new RulesExport(["request_id" => $requestId]), $filename, ExcelExcel::XLSX ); }
修复关键点说明
- 输入验证过滤:用Laravel验证规则
required|integer|exists:table,id,直接拦截非法字符和不存在的ID - 使用可信ID值:从数据库查询获取记录ID,而非直接用用户输入值,彻底阻断恶意值注入路径
- 依赖Storage门面:所有文件操作通过Laravel Storage处理,它会自动处理路径安全,防止目录遍历
- 简化目录清理:用
deleteDirectory替代手动遍历删除,既简洁又避免路径拼接风险 - 安全获取路径:通过
disk->path()获取绝对路径,替代手动拼接字符串,消除路径注入可能
内容的提问来源于stack exchange,提问作者abhishek kashyap
相关产品推荐
相关产品推荐

