You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP实际场景中如何修复I/O函数存在的路径注入攻击漏洞

漏洞修复方案

你的代码存在路径遍历高危漏洞,攻击者可通过传入带../的文件名向服务器任意路径写入文件,即使是内部使用场景也存在被恶意利用的风险。此外你原有代码中strlen($$_GET["output_file"])存在笔误,多写了一个$形成可变变量,本身也会产生额外安全风险。

一、白名单校验修复方案(符合SonarQube要求)

核心原则

  • 固定存储根目录,完全禁止用户控制文件存储的路径部分
  • 仅对文件名做白名单字符校验,严格限制允许的字符和后缀
  • 最终路径二次校验,确保不会跳出指定存储目录

修复后代码示例

// 1. 定义固定的PDF存储根目录(必须用绝对路径,提前给程序开放写入权限)
define('PDF_STORAGE_PATH', '/data/app/internal_pdf_output/');

// 2. 修正原有参数校验的笔误,去掉多余的$
if(!empty($_GET["output_file"]) && is_string($_GET["output_file"]) && strlen($_GET["output_file"]) > 0 ) {
    $input_filename = rawurldecode($_GET["output_file"]);
    // 3. 只取文件名部分,过滤掉所有路径分隔符和上层目录标识
    $input_filename = basename($input_filename);
    // 4. 白名单校验:仅允许中文、大小写字母、数字、下划线、中划线、点,且后缀必须为.pdf
    if (!preg_match('/^[\x{4e00}-\x{9fa5}a-zA-Z0-9_\-\.]+\.pdf$/u', $input_filename)) {
        die("文件名不合法,仅允许中文、字母、数字、下划线、中划线,且必须为pdf后缀");
    }
    // 5. 拼接完整存储路径
    $outfile = PDF_STORAGE_PATH . $input_filename;
    // 6. 二次校验最终路径是否在指定存储目录下,防止编码绕过
    $real_outpath = realpath(dirname($outfile));
    if ($real_outpath !== rtrim(PDF_STORAGE_PATH, DIRECTORY_SEPARATOR)) {
        die("非法路径请求");
    }
    // 7. 写入文件
    file_put_contents($outfile, $dompdf->output());
}

二、兼顾自定义文件名需求的更安全方案

如果希望进一步降低风险,同时完全满足用户自定义文件名的需求,可以采用「服务器存储名+下载映射」的方案:

  • 服务器侧存储的文件名使用完全可控的规则生成,比如用户ID_时间戳_随机6位字符串.pdf,完全避免用户输入影响存储路径
  • 在数据库中记录用户ID、自定义文件名、服务器存储路径的映射关系
  • 用户下载文件时,通过Content-Disposition响应头将文件名设置为用户自定义的名称,用户感知完全不受影响

示例下载逻辑:

// 从数据库查询对应的自定义文件名和存储路径
$custom_name = $file_info['user_custom_name'];
$storage_path = $file_info['storage_path'];
header('Content-Type: application/pdf');
header('Content-Disposition: attachment;filename="' . rawurlencode($custom_name) . '"');
readfile($storage_path);

该方案完全规避了用户输入对存储路径的影响,安全性更高,同时完全满足用户自定义文件名的需求。

内容的提问来源于stack exchange,提问作者mahen3d

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 03:30:02