freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

Tomcat-Ajp漏洞:我是如何一步步写出POC的?
FreeBuf_302373 2020-03-06 09:30:05 483157

前言

晚上,朋友圈有人发了篇tomcat-ajp漏洞的通告和一个简要分析的文章,也是当时唯一的参考文章,本着“好好学习、天天向上”的态度,作为小白,就想试着分析下,看看能不能写出poc。所以本文主要讲述一个小白(当然也不能太白,java至少要会吧,网站要知道是啥吧)如何一步步调试分析,编写poc的过程。

一、漏洞介绍

简单来说就是apache tomcat服务器的8009端口上的ajp协议存在漏洞,导致未授权用户可以读网站目录下的任意文件。

漏洞编号:

CNVD-2020-10487/CVE-2020-1938

受影响版本:

ApacheTomcat 9.x < 9.0.31

ApacheTomcat 8.x < 8.5.51

ApacheTomcat 7.x < 7.0.100

ApacheTomcat 6.x

二、调试环境搭建

为了观察数据流向、编写poc,我们需要搭建调试环境。

tomcat是开源项目,所以我首先想的是下载源码,在源码基础上调试,这里我下载的版本是9.0.2的代码。调试器选择的是Idea。

我先在网上搜索了下idea 调试 tomcat源码的文章。最后参考了

https://blog.csdn.net/weixin_30631587/article/details/96528373

这篇文章,将pom.xml中tomcat的版本由9.0.14修改成9.0.2。,不过这里我觉得不改也不会影响结果。成功运行tomcat服务。

三、ajp协议学习

到目前为止,我还不知道什么是ajp协议,这个协议是干啥的,但是既然知道此次tomcat漏洞是ajp协议造成的。我们肯定要去了解下这个协议是什么。

Apache官方有说明文档

http://tomcat.apache.org/connectors-doc-archive/jk2/common/AJPv13.html

当然这个文档一眼看上去,是不太容易理解的,于是百度一番

我理解的是,我们要访问tomcat网站有两种方式,一种是通过浏览器直接输入url地址。

另外一种就是通过ajp协议访问。

AJP协议是定向包(面向包)协议,采用二进制形式代替文本形式,以提高性能。

所以我们需要写个ajp的客户端程序用来与tomcat服务器的8009端口进行数据交互。当然我们可以自己从头写一个ajp客户端,前提是我们需要很详细了解ajp协议及其各个字段含义。我并不打算如此,毕竟自己从头写起来还是很费劲的。我先到github上用关键词ajp和ajp client搜了一下,看来白的人运气不会太差,发现已经有别人的ajp-client项目。

我把三个ajp-client都下了下来,经过测试和对比(边调试边测试),最后使用了

https://github.com/espenhw/ajp-client

这个项目,最后poc也是在这个项目上完成的。

这里我们需要说下ajp协议中比较重要的字段。

Forward Request包就是我们要发送给tomcat 8009端口的内容,用来触发漏洞的。该字段中比较重要的字段是attributes,后面调试跟踪的时候,也会发现的,后面再说。

四、调试跟踪

通过参考我们知道,tomcat在接收ajp请求的时候调用org.apache.coyote.ajp.AjpProcessor来处理ajp消息,prepareRequest将ajp里面的内容取出来设置成request对象的Attribute属性。

我们现在AjpProcessor中定位到prepareRequest()函数,并在函数开始出下上断点,在request.setAttribute(n, v )也下上断点。

编写测试代码如下(test_servlet是我自己编写的servlet代码,放在了webapps目录下):

运行程序,程序成功断在了prepareRequest(),继续向下单步执行,期间可以观察一些字段的变化。但是程序并没有进入while循环,自然也不会执行request.setAttribute(n, v )函数。(此时我对attributes还不懂,不知道这个字段的意义),再次跟踪时发现while循环的判断条件中在获取attitudes的值时,返回值为-1。然后又回头重新看了下前一节所说的Forward Request结构,看到了其中的attitudes字段,心想这个字段也许和代码中while循环判断的attitudecode有关。

然后看了看ajp-client中代码对attitudes字段的处理,发现该项目没有处理attitudes字段。就按照自己的理解在AjpClient.java中添加了attitudes处理相关代码。

public List<Pair<String,String>> headers = new LinkedList<Pair<String,String>>(); 

public List<Pair<String,String>> attributes = new LinkedList<Pair<String, String>>();

添加函数setHeaders()此函数并不重要,添加函数addAttributes()。

在query函数中添加,处理atrribute代码

修改测试代码如下

(test_servlet/xx是一个不存在的地址或映射,只有设置成不存在的地址,代码流程才会进入DefaultServlet)

运行程序,程序成功进入while循环

至于addAttributes参数为什么这样写,我已开始自然也是不知道的,多跟踪调试几次就知道了。

程序执行了request.setAttribute(n, v )函数,接下来就是DefaultServlet的serveResource函数。

跟踪到getRelativePath函数中,

这里就会获取我们设置的attributes值。然后通过resources.getResource(path);判断设置的路径文件是否存在,如果存在则返回文件内容,不存在则报错。

已经成功读到文件。

关于org.apache.jasper.servlet.JspServlet类实现文件包含,这里就不分析了,有兴趣的如法炮制即可。

五、编写poc

如何编写poc就不在讲了,上面的测试代码稍微修改,就是poc了。

六、总结

总的来说,该漏洞的利用并不是很难,即使你不懂ajp协议,有些参考,稍微花点时间,还是能够独立写出poc的,当然我实际调试的时候也没有文章中那么顺的,要有耐心,多调试几次就好。修复的话,如果不需要ajp的,可以把配置文件中的8009配置关闭,或者更新到最新版本。

参考:

https://blog.csdn.net/u012206617/article/details/104416626/

https://blog.csdn.net/kalman2008/article/details/24487703

https://blog.csdn.net/jeikerxiao/article/details/82745516

http://tomcat.apache.org/connectors-doc-archive/jk2/common/AJPv13.html

*本文原创作者:MrCoding,本文属于FreeBuf原创奖励计划,未经许可禁止转载

# poc # Tomcat-Ajp漏洞
本文为 FreeBuf_302373 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
FreeBuf_302373 LV.2
这家伙太懒了,还未填写个人描述!
  • 3 文章数
  • 0 关注者
Liferay portal java反序列化漏洞分析
2020-04-30
JMX远程代码漏洞研究
2020-04-04
文章目录