CVE-2020-1938 - Ajp任意文件读取\包含

0X01漏洞描述

Apache Tomcat AJP协议(默认8009端口)由于存在实现缺陷导致相关参数可控,攻击者利用该漏洞可通过构造特定参数,读取服务器webapp目录下的任意文件。若服务器端同时存在文件上传功能,攻击者可进一步结合文件包含实现远程代码的执行。

0X02 影响版本

Tomcat 6.*
Tomcat 7.* < 7.0.100
Tomcat 8.* < 8.5.51
Tomcat 9.* < 9.0.31

0X03 漏洞原理

在Ajp接受到数据后, 先进行prepareRequest()获取request属性,然后getAdapter().service(request, response)根据web路由发送servlet对象处理。

其中以*.jsp, *.jspx结尾的URI会经JspServlet处理,而其他请求资源使用DefaultServlet处理。

在处理过程中使用了用户可控的request 属性,然后造成文件读取,及文件包含漏洞(需要上传文件)。

0x04 漏洞复现

文件读取:

1、Tomcat 处理外部请求时经由 org/apache/coyote/AbstractProtocol 抽象类 中调用了Ajp和http协议的公共接口 processor.process(wrapper) 方法,对传入的socket请求协议分发处理。

image-20220326195538764

2、漏洞关键触发点prepareRequest方法:

org.apache.coyote.ajp.AbstractAjpProcessor#prepareRequest方法中恶意攻击者可以通过控制请求内容,为request对象任意的设置属性。如果传入的attribute不满足前面的条件,则会调用setAttribute存入我们传入的属性。

image-20220326162518726

3、存入设置好属性,getAdapter().service(request, response); 发送给HTTP servlet处理

image-20220326201258149
image-20220326202030499

4、HttpServletservice()方法处理时,调用了doGet()方法,HttpServlet.doGet()方法有众多的子实现,怎么保证调用到我们需要的doGet()方法。

image-20220326203053025

查看tomcat#web路由配置文件发现($CATALINA_BASE/conf/web.xml), url 为/开头default路由,对应的servlet:org.apache.catalina.servlets.DefaultServlet,正是我们需要进入利用点,第二条则是处理*.jsp,*.jspx的路由,对应servle,org.apache.jasper.servlet.JspServlet

image-20220326204936520

5、org.apache.catalina.servlets.DefaultServlet#serveResource 方法使用getRelativePath获取路径

image-20220326205239762
image-20220326205535497

在获取路径时,对Attribute做了判断,如果javax.servlet.include.request_uri属性不为空的话,就会取出javax.servlet.include.path_info属性的值,作为结果返回,我们设置的值为/WEB-INF/web.xml,最终getRelativePath返回的值就构造为://WEB-INF/web.xml

image-20220326210305333

最后结果被带入到getResources方法中获取路径指向的资源。如果资源存在则返回对应资源文件的内容。

image-20220326210844514

文件包含:

接上文继续研究JspServlet路由,我们尝试触发该路由,包含我们上传的文件,来达到RCE的目的。

首先假设服务环境中存在一个上传点,并且我们知道它在web目录中的位置。我们就可以把代码写入到该文件,上传到web目录。

例如我上传的点为:/WEB-INF/rce.xml,写入一个弹出计算器的代码示例。

image-20220326234253055

修改攻击脚本路径 asdf1.jsp,触发Jsp路由处理请求,进入org/apache/jasper/servlet/JspServlet处理传入的请求,service方法取出attribute中的路径,赋值到jspUri。

image-20220326225516949

调用serviceJspFile执行JspUri路径指定的资源文件。

image-20220326230928081

如果从当前JspRuntimeContext上下文中找不到我们传入路径的JspServletWrapper,serviceJspFile方法就会帮我们实例化一个JspUri路径的JspServletWrapper,并添加到JspRuntimeContext中。

image-20220326231345003

然后进入service方法后会编译我们添加到上下文中的内容,最终通过_jspService() 方法执行我们传入的代码,实现代码执行。

image-20220326233055837
image-20220326233335653
image-20220326233506156
image-20220326233822322

0X05 漏洞危害

攻击者可以读取 Tomcat所有 webapp目录下的任意文件。

此外如果网站应用提供文件上传的功能,攻击者可以先向服务端上传一个内容含有恶意 JSP 脚本代码的文件(上传的文件本身可以是任意类型的文件,比如图片、纯文本文件等),然后利用漏洞进行文件包含,从而达到代码执行的危害。