官方公告:
https://cwiki.apache.org/confluence/display/WW/S2-066
漏洞描述:
攻击者可以操纵文件上传参数以启用路径遍历,在某些情况下,这可能导致上传可用于执行远程代码执行的恶意文件。
Struts 2.0.0 – Struts 2.3.37 (EOL)
Struts 2.5.0 – Struts 2.5.32
Struts 6.0.0 – Struts 6.3.0
2. 环境搭建
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>6.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>8.5.81</version>
</dependency>
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<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>
package blckder02.struts2.action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
publicclass UploadAction extends ActionSupport {
private File myfile;
private String myfileContentType;
private String myfileFileName;
private String destpath;
public String execute() {
destpath = ServletActionContext.getServletContext().getRealPath("/")+"uploads\upload\";
try{
System.out.println("Src File name: " + myfile);
System.out.println("Dst File name: " + myfileFileName);
File destFile = new File(destpath, myfileFileName);
FileUtils.copyFile(myfile, destFile);
return SUCCESS;
} catch (IOException | NullPointerException e) {
e.printStackTrace();
return ERROR;
}
}
public File getMyfile() {
return myfile;
}
public void setMyfile(File myfile) {
this.myfile = myfile;
}
public String getMyfileContentType() {
return myfileContentType;
}
public void setMyfileContentType(String myfileContentType) {
this.myfileContentType = myfileContentType;
}
public String getMyfileFileName() {
return myfileFileName;
}
public void setMyfileFileName(String myfileFileName) {
this.myfileFileName = myfileFileName;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Upload</title>
</head>
<body>
<h2>Upload</h2><br/>
<form action="upload.action" method="post" enctype="multipart/form-data">
<s:label for="myfile">Please upload your file</s:label><br/>
<input type="file" name="myfile"/>
<input type="submit" value="Upload"/>
</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Success</title>
</head>
<body>
You have successfully uploaded <s:property value="myfileFileName"/>
</body>
</html>
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default">
<action name="upload" class="blckder02.struts2.action.UploadAction" method="execute">
<result name="success">/success.jsp</result>
<result name="error">/upload.jsp</result>
</action>
</package>
</struts>
3. 漏洞复现
上传成功后可以看到文件名为自定义的参数值;
4. 漏洞分析
可以看到 request 中含有一个文件类型参数files和一个字符串类型的参数params;
在TreeMap.put()方法中,会将新添入的参数名与已保存的参数名做比较;
5. 补丁分析
在 6.3.0.2版本中,HttpParameters 类的appendAll()中添加调用了remove()方法;遍历检查参数是否需要删除,remove()方法中添加使用了equalsIgnoreCase()方法来忽略大小写进行比较。
https://y4tacker.github.io/2023/12/09/year/2023/12/Apache-Struts2-文件上传分析-S2-066/
https://xz.aliyun.com/t/13172
原文始发于微信公众号(中孚安全技术研究):Apache Struts2 文件上传漏洞分析(CVE-2023-50164)