一次测试引发的探索:关于分号在java web中的一个特性
作者:admin | 时间:2017-6-23 02:57:41 | 分类:黑客技术 隐藏侧边栏展开侧边栏
还记得IIS的解析漏洞吗?xx.asp;.jpg。而最近对java网站进行测试的时候发现了一个问题,也是由分号引起的,也因此去查看了一下源码,也许很多人已经知道了这个问题,但是也许有的人不知道,所以我将内容记录下来了并进行了分享。
起因
我在测试的时候的一个功能的配置文件片段为:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/view/" />
<property name="suffix" value=".jsp" />
</bean>
代码片段:
public static String PRE = "landingpage/"; @RequestMapping({"online"}) public String toOnline(String version) { if (StringUtils.isBlank(version)) {
version = "1.0";
} return PRE + "online-" + version;
}
很明显,version的值是可以通过客户端传递过来的,也就是返回的文件路径是可以被控制的:
当version=xxx时,返回的文件应该是:/view/landingpage/online-xxx.jsp
所以这一功能是存在任意文件下载漏洞的,前提是我们如何把后面的.jsp给分割出去,在很多时候我们会使用%00等空字符进行截断,但是这里并不能成功。
而经过一些测试,我发现分号在这里能有截断的功能,也就是当我输入../../WEB-INF/web.xml;的时候,我能够获取到web.xml的配置信息:
怀疑
漏洞已经测试成功,但是为什么分号能够有截断的功能呢?
我开始以为是spring mvc的框架中的问题,但似乎并不是,我又怀疑是tomcat中间件的问题,似乎也不全是。
如何验证这些疑问呢?
找一个java的网站,在路径的结尾也就是问号的前面输入:http://www.xxx.com/sdaf.jsp;xxxx?id=xx,你会发现和http://www.xxx.com/sdaf.jsp?id=xx返回的结果一样的,并没有提示找不到对应的页面。
也就是说;xxxx在处理的过程中与前面的内容被分隔开了。
也就是说这似乎是java web的一个普遍现象,而不仅仅是某个中间件或者spring的问题。
调试
于是直接写了一个简单的jsp的代码,来调试这个过程:
<% request.getRequestDispatcher(request.getParameter("filename")+".doc").include(request, response); %>
作为突破口,使用tomcat作为中间件进行调试,打开接口requestDispatcher的一个实现类:ApplicationDispatcher
在ApplicationDispatcher中设置断点进行调试
访问下面地址来触发断点:
http://localhost:8080/Spring/test123.jsp?filename=/WEB-INF/web.xml;
这时发现doForward函数中的变量servletPath中的值为:WEB-INF/web.xml,已经将分号以及后面的数据给去除了
而经过变量的追踪,就发现在经过wrequest.setServletPath(servletPath)这个方法前:wrequest.getServletPath=”test123.jsp”,而之后变成了/WEB-INF/web.xml,所以问题出在servletPath的获取上:servletPath的获取应该是在实例化的时候,也就是在代码中:
public ApplicationDispatcher (Wrapper wrapper, String requestURI, String servletPath, String pathInfo, String queryString, String name) { super(); // Save all of our configuration parameters this.wrapper = wrapper; this.context = (Context) wrapper.getParent(); this.requestURI = requestURI; this.servletPath = servletPath; this.pathInfo = pathInfo; this.queryString = queryString; this.name = name; if (wrapper instanceof StandardWrapper) this.support = ((StandardWrapper) wrapper).getInstanceSupport(); else this.support = new InstanceSupport(wrapper);
}
由此看出来servletPath的值也是从外部传递进来的
实例化该类的对象为:ApplicationContext.getRequestDispatcher:
查看代码
以及调试时发现初始的path传递的值为
而最终返回的内容的值为:/WEB-INF/web.xml
也因此定位了关键位置:
而这里并没有结束,因为在这个方法中,除了分号的一个截断外,还有一个符号也会被分割,就是问号“?”:
结束
也就是说在java web中我们使用分号和问号,在某种程度上来说,是可以起到截断的作用的,但会不会如xx.asp;.jpg一样,导致解析漏洞呢,事实上是没有的,当我们去访问http://www.xxx.com/1.jsp;.jpg的时候,事实上访问的是1.jsp这个文件,而不是1.jsp;.jpg这个文件,当我们上传了1.jsp;.jpg文件时,通过web是访问不到的。
PS:java servlet的重定向和转发:
request.getRequestDispatcher("http://www.xx.com").forward(request,reponse);
response.sendRedirect("/xxx.jsp");
*本文原创作者:wadcl