java 文件包含漏洞_tomcat ajp任意文件包含漏洞分析.md

CVE-2020-1938:Tomcat AJP文件包含漏洞分析

--

### 0x01 前言

最近这个漏洞特别的火,各大媒体都在报道,在第一时间进行复现过后,我就想着找个时间分析分析,但是看了老半天的代码也没找到漏洞的触发点,只是根据PoC确定了是由于ajp协议可以自定义request的某些属性值导致的漏洞,而且我翻源码也找到了ajp协议的逻辑代码。但是更进一步,就卡住了,不知道自定义属性怎么就导致了漏洞的产生~没办法,只有去看看别的师傅的分析文章,恍然大悟,原来经过我们自定义属性过后的request对象的后续处理依旧符合tomcat的处理流程,就是针对某个地址的请求会被预先设置好的servlet处理,而任意文件包含也就出现在这些servlet中。下面我们就来看下具体的代码吧

### 0x02 漏洞分析

在分析之前我们还需要了解一下ajp协议的作用。移步: https://blog.csdn.net/jeikerxiao/article/details/82745516

我翻了下tomcat的源码,发现ajp协议实现在下面这一堆源码里:

![](tomcat_ajp_lfi/ajp.png)

然后我把这几个文件都翻了一遍,确定了几个可疑的文件以及可疑的函数,那么怎么确定我们的怀疑是否正确呢?只有下断点,然后发送payload,看看是否能够触发断点23333。结合网上公开的poc

![](tomcat_ajp_lfi/poc.png)

可以看到是设置了几个属性的,而且name是req_attrubute,然后我就去ajp协议源码中去找对这些属性进行处理的部分,一顿操作猛如虎,反正就是反复的调试,最后确定到prepareRequest这个方法,而且这个方法中可以看到这么一段代码:

![](tomcat_ajp_lfi/req_attribute.png)

经过几次调试,最终确定这里就是设置request属性的地方了,但是设置了request属性过后,request对象又会怎么被处理呢?我就是一直卡在这里了,当然,后面看到师傅的文章,知道请求会发送到对应的servlet,如果我们请求的是一个jsp文件,根据tomcat的默认web.xml文件:

```xml

jsp

org.apache.jasper.servlet.JspServlet

fork

false

xpoweredBy

false

3

```

可以看到是被JspServlet处理了,会执行到JspServlet的service方法:

```java

public void service (HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

//jspFile may be configured as an init-param for this servlet instance

String jspUri = jspFile;

if (jspUri == null) {

// JSP specified via in declaration and

// supplied through custom servlet container code

String jspFile = (String) request.getAttribute(Constants.JSP_FILE);

if (jspFile != null) {

jspUri = jspFile;

request.removeAttribute(Constants.JSP_FILE);

}

}

if (jspUri == null) {

/*

* Check to see if the requested JSP has been the target of a

* RequestDispatcher.include()

*/

jspUri = (String) request.getAttribute(

RequestDispatcher.INCLUDE_SERVLET_PATH);

if (jspUri != null) {

/*

* Requested JSP has been target of

* RequestDispatcher.include(). Its path is assembled from the

* relevant javax.servlet.include.* request attributes

*/

String pathInfo = (String) request.getAttribute(

RequestDispatcher.INCLUDE_PATH_INFO);

if (pathInfo != null) {

jspUri += pathInfo;

}

} else {

/*

* Requested JSP has not been the target of a

* RequestDispatcher.include(). Reconstruct its path from the

* request's getServletPath() and getPathInfo()

*/

jspUri = request.getServletPath();

String pathInfo = request.getPathInfo();

if (pathInfo != null) {

jspUri += pathInfo;

}

}

}

if (log.isDebugEnabled()) {

log.debug("JspEngine --> " + jspUri);

log.debug("\t ServletPath: " + request.getServletPath());

log.debug("\t PathInfo: " + request.getPathInfo());

log.debug("\t RealPath: " + context.getRealPath(jspUri));

log.debug("\t RequestURI: " + request.getRequestURI());

log.debug("\t QueryString: " + request.getQueryString());

}

try {

boolean precompile = preCompile(request);

serviceJspFile(request, response, jspUri, precompile);

} catch (RuntimeException e) {

throw e;

} catch (ServletException e) {

throw e;

} catch (IOException e) {

throw e;

} catch (Throwable e) {

ExceptionUtils.handleThrowable(e);

throw new ServletException(e);

}

}

```

经过上面代码的处理,最终jspUri的值变成了`javax.servlet.include.servlet_path + javax.servlet.include.path_info`,而这两个属性的值都是我们可控的。然后jspUri传入了serviceJspFile方法,也就是把jspUri指定的文件当作jsp文件解析了,所以能够造成RCE。

![](tomcat_ajp_lfi/calc.png)

而如果我们构造一个请求普通文件的ajp请求,tomcat最终根据web.xml中的配置调用DefaultServlet处理,也会造成LFI漏洞。具体就不分析了

### 0x03 其他

参考: https://www.colabug.com/2020/0222/7029362/

这篇文章写的比较水,主要是能写的并不多,其实就是通过ajp协议向tomcat发送请求包是可以控制request对象的`javax.servlet.include.request_uri, javax.servlet.include.path_info, javax.servlet.include.servlet_path` 这三个关键属性,导致我们可以访问任意的文件。

阅读本文需要结合PoC,因为很多线索都在PoC中: https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi/blob/master/CNVD-2020-10487-Tomcat-Ajp-lfi.py

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值