Tomcat-AJP文件包含漏洞

slug
series-status
status
summary
date
series
type
password
icon
tags
category

Tomcat AJP 文件包含漏洞

CVE Num: CVE-2020-1938 Tags: RCE, Tomcat, 安全配置错误, 文件包含漏洞

环境搭建

  1. 借助Vulhub搭建基础环境容器
  1. 在其中配置好ssh等环境,并开启tomcat远程调试(catalina)
🖥️ 环境版本:Tomcat 8.0.50

EXP

  • 链接
  • 关键程序

复现结果

任意文件读取

  • 读取 /WEB-INF/web.xml
notion image
  • 自己在 /usr/local/tomcat/webapps/ROOT/WEB-INF 路径下写入 a.txt,内容为 Hello River
notion image
  • 借助AjpShotter进行读取
notion image
  • 尝试读取 /etc/passwd 失败
notion image

RCE

  • 首先上传jsp🐴 到ROOT路径下(/usr/local/tomcat/webapps/ROOT/a.jsp)
  • 借助AjpShooter执行该后门文件
notion image
  • 发现成功执行系统命令

任意文件读取漏洞原理分析

关键漏洞点

  • tomcat-coyote.jar
  • org.apache.ajp.AjpProcessor.java
  • 449行

分析过程中执行的命令

步进分析

  1. AjpProcessor.prepareRequest()方法下的这个位置打断点后步入调试
notion image
  1. 发现这里会将几个参数存入这个HashMap中
notion image
  1. 循环结束时HashMap中的内容
notion image
  1. 借助wireshark抓取exp执行时发出的数据包
notion image
可以看到这里发起了针对/WEB-INF/a.txt的访问请求
  1. 寻找这个数据包最后由哪个servlet接收
  • /usr/local/tomcat/conf/web.xml文件中的配置如下
notion image
notion image
  • 根据配置不难看出,其中定义了两个Servlet
  • 在用户请求的URI不能和其他的Servlet匹配的时候,就会交给默认的Servlet处理
    • 其中,如下图的配置所示,静态资源的请求主要由前者负责,而入jsp文件的请求则交给后者处理
notion image
  • 回顾抓到的数据包,请求的URI为index,匹配default情况,因此必然会处罚DefaultServlet中的方法
  1. 在DefaultServlet中的doGet方法处设置断点
notion image
<aside> 💯 这里之所以是get方法,是因为在exp中默认选择的是get方法
</aside>
  1. 跟随函数步进观察代码
  • 在这里获取到请求的目标路径
notion image
即这里这个路径:
notion image
  • 这里可以看出来,如果没有传递servlet_path,则会默认添加 ’/’ 到路径中,即访问webapp根路径
notion image
  • 回到doGet,如果路径为空,则直接重定向
notion image
  • 随后,在这里获取路径对应的资源
notion image
  • 进入getResource方法,可以看到,其中比较关键的应该就是这个validate方法
notion image
这个方法主要负责校验路径是否有效
  • 其中核心就是这个normalize方法
notion image
  • 而在这部分,针对 ../ 目录穿越的情况进行了判断
notion image
<aside> 💯 可能这里会有疑惑:为什么它判断index == 0就可以确定存在呢?如果不在开头呢? 答:因为这里的判断是在循环里,每次检测一部分,检测完某一部分以后就会截取掉那部分。
</aside>
  • 判断结束回来,这里如果请求的资源不存在,则会直接返回404,或其他状态码
notion image
同时,在这一部分,如果请求中不包含request_uri的话,则会导致漏洞利用失败
  • 这一部分判断是否有权限获取对应资源,如果没有则返回403
notion image
  • 在这一部分开始准备输出
notion image
  • 最后附上完整的调用链结构
notion image

RCE漏洞原理分析

执行RCE对应的EXP

  • 执行exp
notion image
  • 抓包
notion image

进入IDEA分析

定位到JspServlet

  • 根据前文的分析可知,针对jsp文件的请求会调用JspServlet,因此在该文件的service方法设定断点
notion image
  • 放行调试至此断点处,随后继续执行,可以看到首先会将servlet_path的值存储到jspUri中
notion image
这里可以看到,如果请求中带有path_info的话会将path_info的内容与servlet_path的值进行拼接
  • 这里还有一个预编译的函数用来针对含参的请求进行预处理
notion image
由于我们这次的请求是不含参数的,因此先跳过此部分
  • 随后进入关键的函数serviceJspFile
notion image
  • 首先生成JspServletWrapper对象
notion image
<aside> 💯 这里补充一下JSP是如何转化成Servlet的:
服务端对外提供JSP请求服务的是JspServlet,继承自HttpServlet。核心服务入口在service方法,大体流程如下:
  1. 首先获取请求的jspUri,如果客户端发起请求:https://xxx.xx.com/jsp/test.jsp,那么获取到的jspUri为:/jsp/test.jsp
  1. 然后查看缓存(Map结构)中是否包含该jspUri的JspServletWrapper,如果没有就需要创建一个JspServletWrapper并且缓存起来,并调用JspServletWrapper的service方法
  1. 如果为development模式,或者首次请求,那么就需要执行JspCompilationContext.compile() 方法
  1. 在JspCompilationContext.compile方法中,会根据jsp文件的lastModified判断文件是否已经被更新(out dated),如果被更新过了,就需要删除之前生成的相关文件,然后将jspLoader置空(后面需要加载的时候如果jspLoader为空,就会创建一个新的jspLoader),调用Compiler.compile方法生成servlet,设置reload为true(默认为true),后面会根据reload参数判断是否需要重新加载该servlet
  1. 调用JspServletWrapper.getServlet方法获取最终提供服务的servlet,这个过程会根据reload参数看是否需要重载servlet,如果需要重载,那么就会获取jspLoader实例化一个新的servlet(如果前面发现jsp文件过期,那么此时获取的jspLoader为空,则会创建一个新的jspLoader),并且设置reload为false
  1. 调用servlet的service方法提供服务,如果servlet实现了SingleThreadModel接口,那么会用synchronized做同步控制 </aside>
  • 随后调用JspServletWrapper的service方法:
notion image
  • 进入该方法可以看到在这一步获取到了Jsp转换为的Servlet
notion image
  • 最后附上RCE的执行调用链
notion image

修复建议

  1. 官网已经发布修复漏洞的Apache Tomcat版本,版本分别为:Tomcat9.0.31、Tomcat8.5.51、Tomcat7.0.100,可以通过Apache Tomcat官网下载相应的版本进行更新;
  1. 如有更老版本或者无法立即进行版本更新的用户,建议直接关闭AJPConnector,或将其监听地址改为仅监听本机localhost:
    1. 编辑<CATALINA_BASE>/conf/server.xml,找到如下行(<CATALINA_BASE>为Tomcat的工作目录): <Connector port="8009" protocol="AJP/1.3" redirectPort="8443/">
    2. 将此行注释(也可删掉改行) <!--<Connector port=”8009” protocol=”AJP/1.3” redirectPort=”8443/”>-->
  1. 如果使用了Tomcat AJP协议:
    1. 建议将 Tomcat 立即升级到 9.0.31、8.5.51 或 7.0.100 版本进行修复,同时为 AJP Connector 配置 secret 来设置 AJP 协议的认证凭证。例如(注意必须将 YOUR_TOMCAT_AJP_SECRET 更改为一个安全性高、无法被轻易猜解的值)
Loading...

尚未开始
更新中
近期核心
已完结
已弃更

© River 2021-2025