记某系统有趣的文件上传
字数 1486 2025-08-06 08:35:00
Windows环境下PHP文件上传漏洞分析与利用
漏洞概述
本文记录了一个基于Windows系统的PHP文件上传漏洞,该漏洞利用了Windows文件命名规则和PHP在Windows环境下的特殊特性,成功绕过了文件上传限制,实现了任意文件上传。
环境搭建
- 系统环境:Windows
- 服务器环境:phpstudy集成环境
- 目标系统:SEMCMS(具体版本未明确)
漏洞分析
初始黑盒测试
- 使用默认凭证进入后台
- 在图库管理功能中发现文件上传点
- 尝试上传PHP文件时发现系统自动添加.jpg后缀
源码分析
关键文件:/Admin/SEMCMS_Upfile.php
文件上传处理流程
- 从
filename获取文件类型并截取后缀 - 使用正则表达式进行白名单校验:
preg_match("/jpg|jpeg|gif|png|doc|xls|pdf|rar|zip|bmp|ico/i", $file_ext) - 从POST参数
wname获取文件名并与后缀拼接 - 使用
test_input()函数进行过滤(去除空格、反斜杠,HTML实体编码) - 使用
move_uploaded_file()写入文件
漏洞利用技术
第一阶段:Windows文件命名规则利用
Windows系统中,文件名中的冒号(:)会导致:
- 文件名被截断
- 生成空文件
利用方法:
- 构造
wname参数为test.php: - 系统会生成
test.php空文件
局限性:
- 只能创建空文件,无法写入内容
第二阶段:PHP在Windows下的特殊特性
PHP在Windows环境下对某些字符有特殊处理:
>:相当于通配符?(匹配单个字符)<<:相当于通配符*(匹配多个字符)":相当于字符.(点)
利用步骤:
-
首先上传一个空PHP文件:
- 设置
wname为test.jpg.php: - 生成文件:
test.jpg.php(空文件)
- 设置
-
然后写入内容:
- 设置
wname为test,filename为test.jpg<< - 由于
<<的通配符特性,会匹配到test.jpg.php文件并写入内容
- 设置
其他有效payload:
test123.jpg\">>ptest123.jpg\"php
技术验证
编写测试代码验证通配符特性:
<?php
$file = @$_REQUEST['filename'];
$file_contents = @file_get_contents($file);
echo "匹配到的文件为:".$file_contents;
测试结果:
test.jpg<<:依次匹配test.jpg、test.jpg.jpg、test.jpg.php>:匹配单个字符(类似?)":匹配点字符(.)
影响范围
该特性在PHP5、PHP7和PHP8的Windows环境下均存在,影响以下函数:
include()/include_once()require()/require_once()fopen()copy()file_get_contents()readfile()file_put_contents()mkdir()opendir()readdir()move_uploaded_file()getimagesize()
防御建议
- 严格校验文件扩展名,使用白名单机制
- 在保存文件时重命名文件(如使用随机文件名)
- 禁用危险字符在文件名中的使用
- 在Linux环境下部署PHP应用
- 对上传文件内容进行严格校验
参考资源
- PHP源码调试之Windows文件通配符分析
- PHP官方文档中关于Windows文件系统处理的说明
总结
该漏洞巧妙利用了Windows文件系统和PHP在Windows环境下的特殊特性,通过多阶段攻击最终实现了任意文件上传。理解这些底层特性对于攻防双方都具有重要意义,既可以帮助安全人员发现更多潜在漏洞,也能帮助开发人员编写更安全的代码。