目录导航
0x01 前言
最近在网上看到一些关于Java环境下任意文件上传的讨论。主要讨论点是如何在上传任意文件时绕过文件名检测。
因此,我写这篇文章来总结这些技巧。
0x02 丰富的技巧
- 使用
getSubmittedFileName
方法获取文件名
当我们在Java中使用originalServlet
开发多部分格式文件上传功能时,getSubmittedFileName()
经常使用方法来获取文件名,尤其是在早期的Java应用中。但是涉及此方法的潜在问题。
我们可以调试代码来分析一下。首先在 处设置断点getSubmittedFileName
,然后进入下一个名为HttpParser.unquote()
的方法HttpParser.unquote()
,这里是获取文件名的地方。

在调试代码的过程中,我们可以发现当文件名中包含\
时,会被省略。最后文件名变成pyn3rd.jsp

所以我们可以利用这个特性来规避文件名检测,比如基于正则表达式的WAF。

- 使用
getOriginalFilename
方法获取文件名
众所周知,在 SpringBoot 中分段格式文件上传的场景中,我们习惯使用getOriginalFilename()
获取文件名的方法,
它可以直接获取文件名,无需更改文件名。


但是,当我们使用另一种方法命名StringUtils.cleanPath()
规范化方法获得的文件名getOriginalFilename()
时,存在另一个特殊性。我们可以使用一个或多个/.
来附加文件名。
/
用作分隔符,.
表示当前目录。如果它指向当前目录,只需删除它。所以文件名的结果是pyn3rd.jsp


顺便说一句,在 Java(Windows 和 Linux)中,\
总是转换为/
,当我们遇到 SSRF/XXE 漏洞时,尝试替换\
为/
,例如http:\/
替换http://

- 使用
Apache commons-fileupload/commons-io
方法获取文件名
我们还可以使用一些常见的 Java 库,如org.apache.commons.fileupload.FileItem.getName
or org.apache.commons.io.FilenameUtils.getName
来获取文件名。例如commons-io
分析如下

如果/
或/[SPACE]
附加在文件名的末尾。换句话说,/
对于零字符或空字符,文件名的结果都是pyn3rd.jsp



如果在文件名末尾附加/
或/[SPACE]/
/
。如果分隔符后面存在非空白字符,则将后面的字符作为文件名。
