🎯 Pass-01:前端 JS 校验
关键函数 :checkFile()(JavaScript)
漏洞原因:仅在客户端用 JS 检查扩展名,可禁用 JS 或直接 Burp 改包绕过。
防御 :前端校验只做用户体验,后端必须做同等校验。
🎯 Pass-02:Content-Type 绕过
关键函数 :$_FILES['upload_file']['type']
漏洞原因 :仅判断浏览器传来的 type 字段(image/jpeg/image/png/image/gif),该值完全可由攻击者篡改。
防御 :使用 finfo_file() 或 exif_imagetype() 读取文件二进制头,获取真实 MIME。
🎯 Pass-03:特殊后缀绕过(黑名单不全)
关键函数 :in_array($file_ext, $deny_ext)
漏洞原因 :黑名单遗漏 php5、phtml、pht 等可解析后缀,攻击者上传 shell.phtml 即可绕过。
防御 :改用白名单 ,只允许 jpg/png/gif 等业务必需后缀。
🎯 Pass-04:.htaccess 解析绕过
关键函数 :move_uploaded_file()
漏洞原因 :黑名单未过滤 .htaccess,上传 .htaccess 后可使目录下 .jpg 被当作 PHP 解析。
防御:
-
白名单 + 上传目录禁用脚本执行
-
Apache 配置
php_flag engine off
🎯 Pass-05:.user.ini 绕过
关键函数 :move_uploaded_file()
漏洞原因 :黑名单未过滤 .user.ini,通过 auto_prepend_file=shell.png 让同目录 PHP 文件自动包含图片马。
防御 :上传目录禁止 .ini、.htaccess 等配置文件生效;Web 服务器层面 deny all 拦截。
🎯 Pass-06:大小写绕过
关键函数 :strtolower()(缺失)
漏洞原因 :未统一后缀大小写,shell.PhP 不在黑名单中。
防御 :提取后缀后立即 strtolower(),再比对白名单。
🎯 Pass-07:空格绕过
关键函数 :trim()(缺失)
漏洞原因 :未在 deldot() 前后做 trim(),shell.php(末尾空格)绕过黑名单。
防御:
php
$file_ext = trim($file_ext);
$file_ext = strtolower($file_ext);
🎯 Pass-08:末尾点绕过
关键函数 :deldot()(缺失)
漏洞原因 :未在 deldot() 删除文件名末尾的点,shell.php. 在 Windows 保存时自动去点。
防御 :循环删除末尾的 .、、\t:
php
while (in_array(substr($file_name, -1), ['.', ' ', "\t"])) {
$file_name = substr($file_name, 0, -1);
}
🎯 Pass-09:::$DATA 绕过
关键函数 :str_ireplace('::$DATA', '', $file_ext)(缺失)
漏洞原因 :Windows NTFS 备用数据流特性,shell.php::$DATA 实际落盘为 shell.php。
防御:
php
$file_ext = str_ireplace('::$DATA', '', $file_ext);
🎯 Pass-10:点空格点绕过(你贴源码的真实关卡)
关键函数 :deldot() + trim() + strrchr()
漏洞原因 :deldot() 从右向左删点遇到空格停下,strrchr() 取到空格,trim() 后变成空字符串,不在黑名单中。
payload :shell.php. .(点+空格+点)
防御:采用循环清洗 + 白名单双保险(见 Pass-08 防御代码)。
🎯 Pass-11:双写绕过
关键函数 :str_ireplace($deny_ext, '', $file_ext)(替换为空但未递归检查)
漏洞原因 :str_ireplace() 只替换一次,pphphp 替换 php 后剩下 php。
防御 :替换为空后重新校验后缀 ,或使用白名单 in_array() 直接拒绝。
🎯 Pass-12 & Pass-13:%00 截断绕过
关键函数 :move_uploaded_file()(PHP < 5.3.4)
漏洞原因 :路径拼接 $img_path = $_GET['save_path'].'/'.$file_name,save_path 可控,注入 shell.php%00 截断后续字符串。
防御:
-
升级 PHP 版本 ≥ 5.3.4
-
对用户输入路径做
basename()剥离目录信息 -
使用白名单 + 随机文件名
🎯 Pass-14 & Pass-15:图片马 + 文件包含
关键函数 :getimagesize()
漏洞原因 :getimagesize() 只检查文件头魔术字节,攻击者在合法图片后追加 <?php ?> 代码,函数仍返回 true。需配合文件包含漏洞 include.php?file=upload/shell.jpg 执行。
防御:
php
$info = getimagesize($tmp_file);
if ($info === false) die('非法图片');
// 配合:上传目录禁执行 + 随机重命名 + 图片二次渲染
🎯 Pass-16:exif_imagetype 绕过
关键函数 :exif_imagetype()
漏洞原因 :与 getimagesize() 类似,仅检查文件头第一个字节,图片马仍可绕过。
防御:同 Pass-14/15,且额外做图片重编码。
🎯 Pass-17:二次渲染绕过(条件竞争前的高级关卡)
关键函数 :imagecreatefromjpeg() / imagecreatefromgif() / imagecreatefrompng() + imagejpeg() 等
漏洞原因:服务器用 GD 库重新生成图片,丢弃非像素数据。JPG 几乎无法绕过(有损压缩),但 GIF 在渲染后仍存在未变区域,可在这些区域插入 PHP 代码。
防御:
php
// 强制重编码,丢弃原始文件
$im = imagecreatefromgif($tmp_file);
imagegif($im, $new_path);
imagedestroy($im);
unlink($tmp_file); // 删除原始上传