php文件上传需严格防护:一、服务端基于finfo_open校验mime白名单;二、丢弃原名,用uniqid+随机码重命名并强制安全扩展名;三、限制大小与数量,php.ini与脚本双控;四、上传目录置于web根外或禁用脚本执行;五、用getimagesize、专用库及clamav深度扫描恶意内容。

如果您在PHP应用中处理用户上传的文件,但未采取适当的安全防护措施,则可能面临恶意文件执行、路径遍历、服务器提权等严重风险。以下是保障PHP文件上传安全的具体防护措施:
一、严格校验文件类型
仅依赖客户端提交的文件扩展名或Content-Type头极易被绕过,必须在服务端基于文件内容进行MIME类型验证,并限制允许的类型白名单。
1、使用finfo_open()函数读取文件二进制头信息,获取真实MIME类型。
2、将获取到的MIME类型与预设白名单(如image/jpeg、image/png、application/pdf)逐项比对。
立即学习“PHP免费学习笔记(深入)”;
3、若MIME类型不在白名单中,立即终止上传并返回错误响应。
4、禁止接受text/html、application/x-php、application/x-sh等可执行或危险类型。
二、重命名上传文件
原始文件名可能包含恶意字符、路径遍历序列(如../)或可执行后缀,直接保存将导致覆盖系统文件或触发解析漏洞。
1、丢弃客户端提交的$_FILES['file']['name']全部内容。
2、生成唯一文件名:组合uniqid()、随机字符串与时间戳,例如uniqid('up_').bin2hex(random_bytes(8)).'.png'。
3、强制指定扩展名:根据步骤一确认的安全MIME类型映射为固定扩展名(如image/gif → '.gif'),不采用用户输入的后缀。
4、确保新文件名不含路径分隔符(/或\)、控制字符及空格。
三、限制文件大小与数量
过大的文件不仅消耗服务器资源,还可能用于DoS攻击或绕过部分检测逻辑;多文件上传若无约束则加剧风险暴露面。
1、在php.ini中设置upload_max_filesize和post_max_size为合理值(如2M),并重启Web服务。
2、在PHP脚本中检查$_FILES['file']['size']是否超过预设阈值(如2097152字节),超限则拒绝处理。
3、若允许多文件上传,使用count($_FILES['files']['name'])判断总数,超出设定上限(如5个)时中断流程。
4、对每个文件单独校验大小,防止通过数组伪造绕过单文件限制。
四、隔离存储上传目录
将上传文件存放在Web根目录下且未禁用脚本解析,可能导致攻击者上传webshell并直接访问执行。
1、将上传目录设置在Web服务器文档根目录之外(如/var/www/uploads/ → /var/data/uploads/)。
2、若必须置于Web可访问路径,需在Web服务器配置中禁用该目录下所有脚本执行权限(Apache中使用
3、设置上传目录权限为755,文件权限为644,禁止组和其他用户写入。
4、确保上传目录不继承父目录的.htaccess解析能力或类似机制。
五、扫描并清理恶意内容
部分恶意文件(如嵌入PHP代码的图片、带宏的Office文档)可能通过内容混淆规避基础MIME检测,需引入深度内容分析。
1、对图像类文件调用getimagesize()验证其是否为真实图片结构,非图像返回false则拒绝。
2、对PDF、DOCX等复合格式,使用专用库(如tcpdf、phpoffice/phpword)尝试解析首部结构,失败即拦截。
3、集成ClamAV等本地杀毒引擎,调用clamscan命令行对临时文件进行病毒扫描,exit code非0则删除文件。
4、对文本类文件(如CSV、TXT),扫描是否包含











