前言
前阵子看有师傅在公众号上发表了Resin解析漏洞分析,我们也知道有个常用的OA用的就是Resin,因此我认为了解它的漏洞是十分必要的。
【学习资料】
原理分析
这个漏洞和IIS解析漏洞比较像,可以通过创建一个xxx.jsp的文件夹,并在其中放置一个txt文件,文件的内容将会被当作JSP解析。
我认为要分析这个漏洞原理,首先得先了解访问jsp文件时Resin是如何处理我们请求的。
首先看下*.jsp是被哪个Servlet处理的,从配置app- default.xml中可以看出,我们的请求会被com.caucho.jsp.JspServlet处理。
<servlet servlet-name="resin-jsp"
servlet-class="com.caucho.jsp.JspServlet">
<init>
<load-tld-on-init>false</load-tld-on-init>
<page-cache-max>1024</page-cache-max>
</init>
<load-on-startup/>
</servlet>
<servlet-mapping url-pattern="*.jsp" servlet-name="resin-jsp" default="true"/>
本来以为在JspServlet下断点可以看到请求调用栈,但是在实际操作的过程中发现并没有执行到JspServlet中的方法就返回了,确实比较奇怪。
在Resin中发起HTTP请求一定会经过HttpRequest#handleRequest方法处理,可以在这个方法中打断点排查问题,经过排查发现在PageFilterChain#doFilter中就完成了JSP的"编译"和执行工作,这点比较奇怪,因为之前分析Tomcat中"编译JSP"的操作是在servlet中完成的。所以其实针对Resin对JSP文件处理的分析重点就在PageFilterChain#doFilter中。
- JSP编译后会被封装到Page对象中,而Page对象的引用被保存以pageRef属性中,因此首先检测pageRef是否为空,如果是则直接通过page.pageservice(req,
res);执行请求,不经过后面编译的逻辑。 - 如果缓存中没有page对象,则通过compilePage编译JSP并封装为Page对象返回,new
SoftReference创建引用对象,再通过pageservice执行请求。
public void doFilter(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
FileNotFoundException notFound = null;
SoftReference<Page> pageRef = _pageRef;
Page page;
//首先从换从中获取Page对象的引用,如果有就不再编译。
if (pageRef != null)
page = pageRef.get();
else
page = null;
//如果缓存为空或者page对象被修改过则编译
if (page &#