安全路透社
当前位置:安全路透社 > 安全客 > 正文

【漏洞分析】Tomcat Security Constraint Bypass CVE-2017-5664 分析

http://p9.qhimg.com/t01b1b113ed6836629d.jpg

作者:n1nty

在车上刚看到这个 CVE 的相关信息时,就感觉与PUT有关,让我猜到了。

首先,这是鸡肋。:)有兴趣看粗略技术分析的请继续。

这次的 CVE 涉及到 DefaultServlet 与 WebdavServlet。这里只讲 DefaultServlet。


背景知识


1. DefaultServlet 的作用

我前面的公众号文章讲过,JspServlet 的作用是处理jsp 与jspx 文件的请求,那么非jsp jspx 就是由 DefaultServlet 来处理的(其实有别的情况,但是因为这是个鸡肋,这里不讨论那么多了),这里我们就简单地认为静态文件会交由DefaultServlet 来处理吧。

2. DefaultServlet 可以处理 PUT 或 DELETE请求,前提要求是readOnly 为 false,然而默认值是 true。为了触发漏洞,需要在conf/web.xml 中 default servlet 的配置中添加如下配置:

<init-param>
            <param-name>readonly</param-name>
            <param-value>false</param-value>
</init-param>

3. 在WEB 应用的 web.xml 中添加如下配置,可以为WEB 程序自定义404 错误页面:

<error-page>
              <error-code>404</error-code>
              <location>/404.html</location>
</error-page>

当 DefaultServlet readOnly 为 false,我们就开启了DefaultServlet 处理 PUT 请求的功能,我们也就可以向目标上传文件。请求必须到达DefaultServlet 才能进行 PUT 操作,这也就是说我们能上传的文件的类型是受限制的,比如默认情况下我们是不能上传jsp 或者jspx 的。

比如如下命令:

curl -i -T aaa.jsp http://localhost:8080/CVE-2017-5664/aaa.jsp

我们的本意是将 aaa.jsp PUT至目标服务器,保存为aaa.jsp。这里我们所用的路径是

http://localhost:8080/CVE-2017-5664/aaa.jsp

这个请求将会被 JspServlet 处理,而不是被DefaultServlet 处理。JspServlet 是不处理 PUT 请求的(可以理解成JspServlet 将所有请求都当成 GET 来处理了。),这也就是我们不能上传 jsp jspx 文件的原因。我们只能上传其它类型的文件,而这通常是静态文件。

比如在readOnly 为 false 的时候,我们可以通过如下命令上传aaa.txt

curl -i -T aaa.txt http://localhost:8080/CVE-2017-5664/aaa.txt

因为以上请求会被 DefaultServlet 处理,所以PUT 操作会成功。

官方对于本次 CVE 的描述如下:

The error pagemechanism of the Java Servlet Specification requires that, when an error occursand an error page is configured for the error that occurred, the originalrequest and response are forwarded to the error page. This means that therequest is presented to the error page with the original HTTP method.
If the error page is a static file, expected behaviour is to serve content of the file as if processing a GET request,regardless of the actual HTTP method. Tomcat's Default Servlet did not do this.Depending on the original request this could lead to unexpected and undesirableresults for static error pages including, if the DefaultServlet is configuredto permit writes, the replacement or removal of the custom error page.

大意是:

Java Servlet 规范中要求,当访问的资源出现如 404 或 500 之类的错误,并且同时服务端配置了相应的错误页面时,原始请求应该被forward 到错误页面。

当错误页面是一个静态文件时,正确的做法应该是忽略掉原始请求的HTTP METHOD,直接像处理 GET 请求一样向客户端返回静态错误页面的内容。但是 Tomcat 的Default Servlet 却不是这么做的。如果 DefaultServlet 配置的readOnly 为 false,则一个恶意的请求有可能删除或者替换掉错误页面文件。

我这里直接说一下如何实现官方所说的 “replacement ofthe custom error page”。

curl -i -T aaa.jsp http://localhost:8080/CVE-2017-5664/aaa.jsp

上面说了这条命令是无法上传aaa.jsp 的,因为请求被JspServlet 处理了。那么这里直接简单说一下 Tomcat 在收到这个PUT 请求后是怎么处理的,这里就不分析代码了。

这里假设服务器上是不存在 aaa.jsp 的。JspServlet收到这个请求后,发现不存在/aaa.jsp 对应的 JspServletWrapper,同时连/aaa.jsp 这个文件也不存在,此时应该向客户端返回 404。

但是因为我们在上面给应用配置了一个自定义了 404 页面:/404.html,所以原始请求被会 forward 到这个 /404.html 。因为/404.html 是静态文件,所以会由 DefaultServlet 来处理(这里是关键,也解释了为什么错误页面一定要是一个静态文件,因为只有静态文件的请求才会到DefaultServlet ),DefaultServlet 发现请求是一个 PUT 请求,所以直接利用从客户端传来的文件数据将/404.html 重写了。


实例


原始 404.html 如下:

http://p3.qhimg.com/t0105c2e0cca154e69c.png

访问一个不存在的 111.jsp,返回了 404.html 的内容:

http://p8.qhimg.com/t01160d14a004d6d09b.png

现在直接 PUT 到一个不存在的 jsp 文件,这里还以111.jsp 为例子:

http://p0.qhimg.com/t01d8ee402fd0adbfb3.png

再去查看 404.html 的内容:

http://p1.qhimg.com/t011729c125d6662770.png

官方的补丁是让 DefaultServlet 重写了继承自父类的service 方法,当发现请求是是因为错误而转发过来的,则直接当成 GET 来处理:

http://p3.qhimg.com/t0143f7011461235de1.png


总结


鸡肋,低危。


触发要求


需要 DefaultServlet readonly 值为 false,默认为true。

要求服务端配置了自定义的静态错误页面,而且客户端能够触发相应的错误来使请求被转发至错误页面。

 

修复方式


升级

如非必要,不要更改DefaultServlet readonly 的默认值

不要使用静态文件做为错误页面,可以使用 jsp 文件。

 

最后,360 企业安全集团招高级安全研究员,base 北京,15K-35K:

https://maimai.cn/job?webjid=HjXNduFX&srcu=Zmz2rWdE&src=app&from=timeline 


原文链接:https://mp.weixin.qq.com/s/AWXjwO03oxrL960l3WxyCQ

未经允许不得转载:安全路透社 » 【漏洞分析】Tomcat Security Constraint Bypass CVE-2017-5664 分析

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册