写在前面
之前上一篇文章中浅析帆软FineVis默认插件前台RCE提到jasper依赖没被加载,当时只是简单做了测试,没有具体看为什么jsp未被解析,只是疑惑了下tomcat下jspservlet配置明明正确配置页面却直接返回空(没有考虑到编译报错这一层问题),今天无意间看到星球有师傅分享了如何解析jsp的过程,写文章同时也顺带分享下如何实现RCE的两种姿势
当然至于为什么是windows,之前的两篇漏洞文章中都有提到过,因为linux的默认可以解析,这一点从官方文档就能知道(https://help.fanruan.com/finereport/doc-view-822.html),要求自行下载tomcat部署启动,因此在linux下也不存在这个jsp的解析问题
如何在Windows下完成RCE
SPI
由于这个插件写文件比较特殊,遇到不存在的文件夹会自动创建,因此我们很容易利用Java中SPI的机制完成RCE的利用,比较简单,这里不再展开,不熟悉的可以去网上了解下以前SpringBoot FatJar的一些打法
加载JSP
比较抽象直接访问jsp能访问到但是页面为空白
之前没细细研究,想着这里不是有对应的servlet配置吗,直到看到了别的星球发了一篇文章才发现,原来启动时使用了Tomcat().start()启动
这和Springboot整合tomcat启动时使用的方法一致,也算学到了点新东西(之前一直以为只能通过BootStrap启动),具体可以看看这篇文章了解https://blog.csdn.net/qq_33468007/article/details/107620507
接下来调试可以看到确实触发了jsp编译的过程,但是报错了
经过最终调试发现,报错是因为javax.servlet.jsp.JspFactory#deflt
为null
因此让jsp加载就要解决这个属性为null的问题,而这个来源于JasperInitializer
初始化的过程,它是Tomcat内部的一个初始化器,本就是用于处理支持JSP页面的,在静态块中设置了这个factory,而由于启动方式的原因这个类并没有被初始化
因此要解析jsp,就需要解决这个类初始化的问题,因此我们需要找到一个前台的类帮助我们完成任意类加载
而在com.fr.web.controller.common.FileRequestService#getFile
中就存在我们需要的初始化过程
简单看看下面的代码通过PlatformScaffold.getReflectionProvider().classForName(path)
完成了任意类的初始化,因此也就成功解决了javax.servlet.jsp.JspFactory#deflt
为null的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public void getFile(HttpServletRequest req, HttpServletResponse res, String path, String type, String parser, String tag)throws Exception { xxxxxx省略部分代码xxxxxx } } else if (fileType == FileType.CLASS) { String charset = PlatformScaffold.getBasicConfigProvider().getServerCharset(); // 参数path可控制初始化的类 TextGenerator generator = (TextGenerator)Reflect.on(PlatformScaffold.getReflectionProvider().classForName(path)).create().get(); ((HttpServletResponse)res).setContentType(generator.mimeType() + ";charset=" + charset); String text = generator.text(req, (HttpServletResponse)res); PrintWriter writer = WebUtil.createPrintWriter((HttpServletResponse)res); writer.write(text); writer.flush(); writer.close(); } } catch (Exception var17) { FineLoggerFactory.getLogger().error(var17.getMessage(), var17); } finally { if (wrappedResponse != null) { wrappedResponse.finishResponse(); } } } else { throw new SpecialCharProhibitException(); } } |
因此只需要通过一个请求
1
|
http://xxxx/webroot/decision/file?path=org.apache.jasper.servlet.JasperInitializer&type=class
|
这一次我们的jsp成功被渲染了
: