AJP 任意文件读取\包含
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请求协议分发处理。
2、漏洞关键触发点prepareRequest
方法:
在org.apache.coyote.ajp.AbstractAjpProcessor#prepareRequest
方法中恶意攻击者可以通过控制请求内容,为request对象任意的设置属性。如果传入的attribute不满足前面的条件,则会调用setAttribute存入我们传入的属性。
3、存入设置好属性,getAdapter().service(request, response);
发送给HTTP servlet处理
4、HttpServlet
类service()
方法处理时,调用了doGet()方法,HttpServlet.doGet()
方法有众多的子实现,怎么保证调用到我们需要的doGet()
方法。
查看tomcat#web路由配置文件发现($CATALINA_BASE/conf/web.xml
), url 为/开头
default路由,对应的servlet:org.apache.catalina.servlets.DefaultServlet
,正是我们需要进入利用点,第二条则是处理*.jsp,*.jspx
的路由,对应servle,org.apache.jasper.servlet.JspServlet
。
5、org.apache.catalina.servlets.DefaultServlet#serveResource
方法使用getRelativePath
获取路径
在获取路径时,对Attribute
做了判断,如果javax.servlet.include.request_uri
属性不为空的话,就会取出javax.servlet.include.path_info
属性的值,作为结果返回,我们设置的值为/WEB-INF/web.xml
,最终getRelativePath
返回的值就构造为://WEB-INF/web.xml
。
最后结果被带入到getResources
方法中获取路径指向的资源。如果资源存在则返回对应资源文件的内容。
文件包含:
接上文继续研究JspServlet路由,我们尝试触发该路由,包含我们上传的文件,来达到RCE的目的。
首先假设服务环境中存在一个上传点,并且我们知道它在web目录中的位置。我们就可以把代码写入到该文件,上传到web目录。
例如我上传的点为:/WEB-INF/rce.xml
,写入一个弹出计算器的代码示例。
修改攻击脚本路径 asdf
为1.jsp
,触发Jsp路由处理请求,进入org/apache/jasper/servlet/JspServlet
处理传入的请求,service
方法取出attribute
中的路径,赋值到jspUri。
调用serviceJspFile执行JspUri路径指定的资源文件。
如果从当前JspRuntimeContext
上下文中找不到我们传入路径的JspServletWrapper
,serviceJspFile
方法就会帮我们实例化一个JspUri路径的JspServletWrapper
,并添加到JspRuntimeContext
中。
然后进入service方法后会编译我们添加到上下文中的内容,最终通过_jspService()
方法执行我们传入的代码,实现代码执行。
0X05 漏洞危害
攻击者可以读取 Tomcat所有 webapp目录下的任意文件。
此外如果网站应用提供文件上传的功能,攻击者可以先向服务端上传一个内容含有恶意 JSP 脚本代码的文件(上传的文件本身可以是任意类型的文件,比如图片、纯文本文件等),然后利用漏洞进行文件包含,从而达到代码执行的危害。