打强网杯的时候,一道题目直接就是考JEESITE V1.2.7读配置文件,用以前挖的一个洞拿了flag,漏洞比较简单水一篇。
JEESITE存在两个版本JEESITE1、JEESITE4,其中1.2.7是JEESITE1中的最新版本,不过已经在四年前就不再维护。
分析
com/thinkgem/jeesite/common/servlet/UserfilesDownloadServlet.java
1 | public void fileOutputStream(HttpServletRequest req, HttpServletResponse resp) |
该servlet用来查看CK上传的图片,配置的路由为
1 | <servlet-mapping> |
该Servlet方法很简单,直接获取RequestURI稍作处理后就开始读取文件。
1 | String filepath = req.getRequestURI(); |
filepath即为RequestURI中”/userfiles/“之后的内容,
File file = new File(Global.getUserfilesBaseDir() + Global.USERFILES_BASE_URL + filepath); 虽然限制了只能读取/userfiles/下的文件,但是如果能在filepath进行目录穿越依然能够实现任意文件读取。
不过这里存在一个问题,因为是通过RequestURI获取的文件名而不是GET/POST参数,当需要通过目录穿越读取任意文件时需要在URI中包含”../“,当URI为/userfiles/../xxxxx 会先在TOMCAT这目录穿越,最终请求到的是xxxxx接口,无法访问到UserfilesDownloadServlet。
虽然后面有对filepath进行url解码操作,但是req.getRequestURI获取到的是未URL解码的数据,造成无法二次编码最多只能一次编码,/userfiles/%2e%2e/xxxx 一次编码会被tomcat容器给处理掉然后目录穿越,最后还是无法访问到UserfilesDownloadServlet。
再回过头来看一下对filepath的处理,
1 | String filepath = req.getRequestURI(); |
USERFILES_BASE_URL的定义,
public static final String USERFILES_BASE_URL = “/userfiles/“;
首先从requesturi中查找/userfiles/的起始位置,然后截取它后面的内容作为filepath,这里userfiles后面有/,这时候借助TOMCAT的path parameter特性”;”后面的内容会当作参数,/userfiles;xxx/依然能够访问到UserfilesDownloadServlet。
但是这时候因为没能在requesturi中找到/userfiles/,就将整个requesturi带入到了文件读取的目录中这样肯定也是不行的。可以通过在/userfiles;xxx/再新增一个/userfiles/xxxx, 即/userfiles;xxx/userfiles/xxxxx,字符串截取后filepath后就为xxxxx,并且这时候可以发现requesturi中已经存在了两个目录,这时候再目录穿越/userfiles;xxx/userfiles/../xxxx, tomcat处理后/userfiles/xxxx 依然请求到了UserfilesDownloadServlet,并且此时filepath为../xxxx可以实现目录穿越读取任意文件了,只要requesturi中的目录够多那么就可以目录穿越任意数量目录,在/userfiles/前面新增大数量的目录即可。
qwb利用,
登录邮箱拿到flag