PHP 7.2文件上传安全审计核心是阻断“用户可控输入→文件操作→服务端执行”链路:严查$_FILES入口、三重校验(真实MIME、二进制头、白名单后缀)、上传目录禁解析、杜绝include/eval动态加载及路径遍历。

对 PHP 7.2 环境下的文件上传功能做安全审计,核心是盯住“用户可控输入 → 文件操作 → 服务端执行”这条链路是否被有效切断。PHP 7.2 已废弃 create_function(),但大量老项目仍用 eval()、include()、file_get_contents() 等函数配合上传逻辑,极易引发远程代码执行(RCE)或任意文件读取。
重点检查上传入口与参数控制点
先定位所有接收文件的地方:搜索 $_FILES、move_uploaded_file()、upload_tmp_dir 相关配置,以及框架封装类(如 Laravel 的 request()->file()、ThinkPHP 的 think\File)。确认每个上传点的参数是否完全由用户控制——比如 $_GET['type'] 决定保存路径、$_POST['filename'] 参与重命名、$_REQUEST['ext'] 覆盖后缀等。哪怕前端写了 accept="image/*",后端没校验就等于形同虚设。
严查后缀、MIME、内容三重校验是否落地
只校验后缀名(如 in_array(pathinfo($name, PATHINFO_EXTENSION), ['jpg','png']))是常见陷阱。攻击者可传 shell.php.jpg 绕过;只校验 $_FILES['file']['type'] 更危险,该值完全由浏览器伪造。必须做到:
- 用
finfo_open(FILEINFO_MIME_TYPE)检查真实 MIME 类型,拒绝text/html、application/x-php等可执行类型 - 用
getimagesize()或二进制头检测(如 PNG 文件开头为\x89PNG)验证文件内容 - 后缀强制白名单重写,不依赖用户输入;例如
$ext = 'jpg'; $newName = uniqid() . '.' . $ext;
确认上传目录不可解析、不可遍历
即使文件名和内容都安全,若上传目录被 Web 服务器当作 PHP 脚本执行,一切校验都失效。需检查:
立即学习“PHP免费学习笔记(深入)”;
- Web 服务器配置(Nginx/Apache)是否禁用上传目录的脚本执行,例如 Nginx 中
location ~ ^/uploads/.*\.(php|phar|phtml)$ { deny all; } - 上传路径是否在 Web 根目录外(推荐),或至少设置
open_basedir限制 - 是否存在路径遍历风险:如
$path = '/var/www/uploads/' . $_GET['dir'] . '/' . $filename;,且未过滤../
排查二次渲染与动态包含风险
很多漏洞不出现在上传瞬间,而藏在后续使用环节。重点审计:
- 是否用用户上传的文件名或路径直接
include、require(如模板加载、插件机制) - 是否将上传文件内容
eval()或unserialize()(尤其注意phar://协议触发反序列化) - 是否将文件路径拼进
file_get_contents()、curl_exec()等函数,导致 SSRF 或 LFI - 是否对上传后的文件做“解包”“解密”“还原”操作(如某OA中
.uptemp文件通过 ID 解码还原为原始 PHP)
验证错误处理与日志是否泄露信息
上传失败时的报错可能暴露真实路径、扩展名规则甚至临时文件名。确保:
-
display_errors = Off,log_errors = On,错误日志不记录敏感字段 - 返回给前端的提示统一为“上传失败,请重试”,不带技术细节
- 临时文件(
upload_tmp_dir)权限设为0600,避免被其他账户读取



















