在 AjpProcessor
的 prepareRequest()
中,恶意攻击者可通过控制请求内容,为request对象任意的设置属性。
在switch/case
判断中,当attributeCode=10
时,将调用 request.setAttribute
方法存入。
所以在此攻击者拥有了可控的点,这个点该如何利用呢?
DefaultServlet
在$CATALINA_BASE/conf/web.xml
中默认配置了如下内容:
可以看到这是一个默认的Servlet,这个 DefaultServlet
服务于全部应用,当客户端请求不能匹配其他所有Servlet时,将由此Servlet处理,主要用来处理静态资源。使用 serveResource()
方法提供资源文件内容:
会调用 getRelativePath()
方法获取请求资源路径:
这个方法存在一个判断,如图中红框位置标出:如果 request.getAttribute()
中javax.servlet.include.request_uri
不为空,则会取 javax.servlet.include.path_info
和javax.servlet.include.servlet_path
的值,并进行路径拼接,返回路径结果。
这个结果 path 会被带入到 getResource()
方法中返回结果,只要文件存在,即可读取其中内容。
由此可见,配合AJP协议中的缺陷,可以控制attribute中的内容,造成任意文件读取漏洞。
但是需要注意的是,在读取资源文件的过程中,会调用org.apache.tomcat.util.http.RequestUtil.normalize()
方法来对路径的合法性进行校验,如果存在 ./
或 ../
则会返回 null
,在后续流程中会抛出一个非法路径的异常终止文件读取操作。
因此我们无法使用 ../
跳出目录,只能读取Web应用目录下的文件。
JspServlet
同样的在$CATALINA_BASE/conf/web.xml
中,对访问以 .jsp/*.jspx
后缀结尾的请求,调用 JspServlet
处理请求。
看一下重点的 service()
,代码如下图,在attribute中含有如下 javax.servlet.include.servlet_path
,javax.servlet.include.path_info
时,将会取出并拼接为文件路径 jspUri
。
拼接成 jspUri
后,调用 serviceJspFile()
,将此文件解析为jsp文件并执行。
因此这就构成了一个文件包含漏洞。在文件内容可控的情况下,就可以延伸为任意代码执行漏洞,所以网上有的分析文章也出现了任意代码执行、任意命令执行漏洞的字眼。