
文件上传漏洞是网站被挂马、被植入 webshell、服务器沦陷最常见的入口。不管是 ZBlog 主题插件、自定义表单、后台文件上传、头像上传、附件上传,只要自己写上传功能,一旦过滤不严,攻击者就能传木马后门,直接控制网站甚至整台服务器。
本文讲透上传漏洞原理、常见绕过方式,给你可直接商用的安全上传代码,PHP 项目、CMS 二次开发都能直接套用。
一、文件上传漏洞核心原理
原理一句话:后端没有严格校验文件类型、后缀、MIME、文件内容,导致允许上传 php、phtml 等可执行脚本,被上传木马并访问执行。
常见危害:
上传 Webshell 后门
篡改首页、跳转博彩
拖库下载整站数据库
植入挖矿程序、内网横向渗透
拿下服务器权限
二、常见简陋过滤方式(全部可绕过)
1. 只判断后缀(不安全)
只拦截 .php,改成 .php5、.phtml、.phar 就能绕过。
2. 只校验 MIME 类型
Content-Type 可伪造,伪造图片类型轻松绕过。
3. 前端 JS 校验
前端限制完全没用,抓包改包直接绕过。
4. 只改文件名不检测内容
伪装图片后缀,里面仍是 PHP 木马,配合解析漏洞照样执行。
三、专业安全防御五大原则
禁止上传目录执行 PHP(Nginx 配置拦截)
后端双重校验:后缀 + MIME + 文件真实内容
上传文件统一重命名,不保留原文件名
上传目录独立隔离,不放在网站根程序目录
不允许用户自定义存放路径和文件名
四、Nginx 配置:上传目录禁止执行脚本(第一道防线)
location ~* /upload/.*\.(php|php5|phtml|phar|asp|aspx) {
deny all;
}把 /upload/ 换成你实际的上传文件夹路径。
五、PHP 安全上传完整代码(可直接上线)
1. 安全上传封装函数
<?php
// 允许的安全后缀
$allow_suffix = ['jpg','jpeg','png','gif','webp','bmp'];
// 允许的MIME类型
$allow_mime = [
'image/jpeg',
'image/png',
'image/gif',
'image/webp'
];
function get_file_suffix($filename){
return strtolower(pathinfo($filename,PATHINFO_EXTENSION));
}
// 安全上传主函数
function safe_upload($file,$save_path = 'upload/'){
global $allow_suffix,$allow_mime;
// 1. 创建目录不存在则新建
if(!is_dir($save_path)){
mkdir($save_path,0755,true);
}
$filename = $file['name'];
$tmp_name = $file['tmp_name'];
$file_mime = $file['type'];
$suffix = get_file_suffix($filename);
// 2. 校验后缀
if(!in_array($suffix,$allow_suffix)){
return ['code'=>0,'msg'=>'文件后缀不允许'];
}
// 3. 校验MIME类型
if(!in_array($file_mime,$allow_mime)){
return ['code'=>0,'msg'=>'文件类型非法'];
}
// 4. 校验文件真实内容(防止伪装图片)
$imginfo = getimagesize($tmp_name);
if(!$imginfo){
return ['code'=>0,'msg'=>'不是合法图片文件'];
}
// 5. 随机重命名,防止覆盖和后门探测
$new_name = date('YmdHis').mt_rand(1000,9999).'.'.$suffix;
$save_file = $save_path.$new_name;
// 6. 移动保存
if(move_uploaded_file($tmp_name,$save_file)){
return ['code'=>1,'msg'=>'上传成功','path'=>$save_file];
}else{
return ['code'=>0,'msg'=>'文件保存失败'];
}
}
?>2. 前端表单示例
<form action="upload.php" method="post" enctype="multipart/form-data"> <input type="file" name="upfile" /> <button type="submit">上传</button> </form>
3. 后端处理 upload.php
<?php
include "safe_upload.php";
if(!empty($_FILES['upfile'])){
$res = safe_upload($_FILES['upfile']);
if($res['code'] == 1){
echo "上传成功:".$res['path'];
}else{
echo "失败:".$res['msg'];
}
}
?>六、额外加固技巧
1、关闭 PHP 危险函数
禁用 file_put_contents、fopen、copy 等不必要文件函数,减少恶意写入。
2、上传目录设置权限
Linux 下设置目录权限 0755,禁止写入执行权限。
3、定期扫描上传目录
用宝塔木马扫描,定时检测 upload 目录是否出现可疑 PHP 文件。
3、不用原生上传,尽量用成熟组件
ZBlog、MetInfo 自带上传类已经做了防护,尽量不要自己手写简易上传。
七、总结
文件上传防护记住三步就够:
1、Nginx 上传目录禁止执行脚本
2、PHP 同时校验 后缀 + MIME + 文件真实内容
3、文件随机重命名、隔离目录、不保留原名
按本文代码和配置部署,能拦截 99% 上传漏洞与 Webshell 植入,
标签: PHP 文件上传漏洞 上传漏洞防御 PHP 安全上传代码 网站防挂马配置


