0x01 漏洞背景

CVE-2020-1938 是 Tomcat-Ajp 协议漏洞分析,Tomcat是由Apache软件基金会属下Jakarta项目开发的Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和JavaServer Page(JSP)的支持。由于Tomcat本身也内含了HTTP服务器,因此也可以视作单独的Web服务器。

0x02 影响版本

  1. Apache Tomcat 9.x < 9.0.31
  2. Apache Tomcat 8.x < 8.5.51
  3. Apache Tomcat 7.x < 7.0.100
  4. Apache Tomcat 6.x

0x03 环境搭建

0x1 JDK 安装

cp -r  jdk-8u161-linux-x64.tar.gz   /usr/local/java
cd  /usr/local/java
tar -zxvf jdk-8u161-linux-x64.tar.gz

在/etc/profile文件中写入

export JAVA_HOME=/usr/local/java/jdk1.8.0_161
export JRE_HOME=/$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

执行生效
source /etc/profile

0x2 Tomcat 安装

tar -zxvf  apache-tomcat-8.5.30.tar.gz

在/etc/profile文件中写入

export CATALINA_HOME=/usr/local/tomcat/apache-tomcat-8.5.30
export CLASSPATH=.:$JAVA_HOME/lib:$CATALINA_HOME/lib
export PATH=$PATH:$CATALINA_HOME/bin

执行生效
source /etc/profile
启动
catalina.sh start

0x3 开启Tomcat调试

在tomcat bin 文件夹下的catalina.sh中添加如下代码

export JAVA_OPTS='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005'
# OS specific support.  $var _must_ be set to either true or false.

Tomcat 调试原理
分为两种情况:

  1. 调试器开端口,远程JVM连接本地端口
  2. 远程JVM开放端口,调试器连接

总的来说,两个VM之间通过debug协议进行通信,然后以达到远程调试的目的。两者之间可以通过socket进行通信。其中,调试的程序常常被称为debugger, 而被调试的程序称为 debuggee。两种调试情况如下图所示:

关于调试协议JDWP这里先不讲,等有机会在进行讲解。

0x4 添加tomcat源码

在调试过程中,intellij反编译代码会有出入,直接下载tomcat相对应版本的源代码
https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.30/src/apache-tomcat-8.5.30-src.zip

将文件夹中的java 添加到intellij中,就可以对着源代码进行调试了

0x5 开启Intellij调试

设置Use module classpath 为项目根目录,设置调试端口等信息,如下图所示:

0x03 知识补充

0x1 Tomcat Connector

Apache Tomcat服务器通过Connector连接器组件与客户程序建立连接,Connector表示接收请求并返回响应的端点。即Connector组件负责接收客户的请求,以及把Tomcat服务器的响应结果发送给客户。在Apache Tomcat服务器中我们平时用的最多的8080端口,就是所谓的Http Connector,使用Http(HTTP/1.1)协议.

在conf/server.xml文件里,他对应的配置为

    <Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />

而 AJP Connector,它使用的是 AJP 协议(Apache Jserv Protocol)是定向包协议。因为性能原因,使用二进制格式来传输可读性文本,它能降低 HTTP 请求的处理成本,因此主要在需要集群、反向代理的场景被使用。

Ajp协议对应的配置为

<!-- Define an AJP 1.3 Connector on port 8009 --><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

下图是tomcat 服务器开放连接端口情况。

0x2 Tomcat Servlet

在tomcat conf/web.xml中配置着tomcat的路由处理,主要有两个servlet分支

这个规则匹配/后没有后缀的

<servlet><servlet-name>default</servlet-name><servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class><init-param><param-name>debug</param-name><param-value>0</param-value></init-param><init-param><param-name>listings</param-name><param-value>false</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>default</servlet-name><url-pattern>/</url-pattern></servlet-mapping>

这个规则匹配路径中有.jsp的路由

<servlet><servlet-name>jsp</servlet-name><servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class><init-param><param-name>fork</param-name><param-value>false</param-value></init-param><init-param><param-name>xpoweredBy</param-name><param-value>false</param-value></init-param><load-on-startup>3</load-on-startup></servlet><servlet-mapping><servlet-name>jsp</servlet-name><url-pattern>*.jsp</url-pattern><url-pattern>*.jspx</url-pattern></servlet-mapping>

0x3 Tomcat 请求处理

该图介绍了Tomcat内部处理HTTP请求的流程

  1. 用户发送请求至8080端口,被Connector获取后,Connector中的Processor用于封装Request,Adapter用于将封装好的Request交给Container。
  2. Connector把该请求交给Container中的Engine来处理,并等待Engine的回应。
  3. Engine 获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host。
  4. Engine搜索对应的主机,/test匹配到Context,
  5. path="/test"的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL PATTERN为*.jsp的Servlet,对应于JspServlet类(匹配不到指定Servlet的请求对应DefaultServlet类)
  6. Wrapper是最底层的容器,负责管理一个Servlet。构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost(),执行业务逻辑、数据存储等程序。
  7. Context把执行完之后的HttpServletResponse对象返回给Host
  8. Host把HttpServletResponse对象返回给Engine
  9. Engine把HttpServletResponse对象返回Connector
  10. Connector把HttpServletResponse对象返回给客户Browser

0x04 漏洞分析

该漏洞通过AJP协议端口触发,正是由于上文所述,Ajp协议的请求在Tomcat内的处理流程与我们上文介绍的Tomcat处理HTTP请求流程类似。我们构造两个不同的请求,经过tomcat内部处理流程,一个走default servlet(DefaultServlet),另一个走jsp servlet(JspServlet),可导致的不同的漏洞。

0x1 文件读取漏洞

# 请求url
req_uri = '/asdf'# AJP协议请求中的三个属性
javax.servlet.include.request_uri = '/'
javax.servlet.include.path_info = 'WEB-INF/web.xml'
javax.servlet.include.servlet_path = '/'

在搭好的环境上,设置断点

Step 1 AjpProcessor->service()->prepareRequest()

进入prepareRequest函数,该函数处理Requests请求,重点在这一块

在该case分支request.setAttribute(n,v )函数是解析函数,通过三次循环可见下图效果

通过三个循环将attributes变量赋值成如下所示:

随后将请求传给CoyoteAdapter,对request进行封装,将请求抓发给Container:

通过多级反射和调用,到达Servlet路由分发


Step 2 DefaultServlet-> service() -> doGet()

从CoyoteAdapter到达doGet的调用链

Servlet 的service函数根据请求的方法,调用不同的处理函数如下图匹配Get 方法:
1588562393145.png


Step 3 getRelativePath()

从get函数进入后执行serveResource函数

其中有个关键的函数getRelativePath

 protected String getRelativePath(HttpServletRequest request, boolean allowEmptyPath) {String servletPath;String pathInfo;if (request.getAttribute("javax.servlet.include.request_uri") != null) {pathInfo = (String)request.getAttribute("javax.servlet.include.path_info");servletPath = (String)request.getAttribute("javax.servlet.include.servlet_path");} else {pathInfo = request.getPathInfo();servletPath = request.getServletPath();}StringBuilder result = new StringBuilder();if (servletPath.length() > 0) {result.append(servletPath);}if (pathInfo != null) {result.append(pathInfo);}if (result.length() == 0 && !allowEmptyPath) {result.append('/');}return result.toString();}

从代码中可以看出request.getAttribute的变量正好是我们POC中的变量,POC中的参数代入getRelativePath()方法,RequestDispatcher.INCLUDE_REQUEST_URI的值为’/’,不为空。pathInfo和servletPath参数的值拼接成result,getRelativePath()方法将result返回,返回内容为:’/WEB-INF/web.xml’。

Step 4 getResource() -> validate() -> normalize()

serveResource()方法继续往下,可以看到这行代码:

该函数功能从字面意思上就是获取内容

进入了valiate方法,该方法为路径检测方法,其中主要调用了normalize方法,重点关注该方法:

         if (normalized.endsWith("/.") || normalized.endsWith("/..")) {normalized = normalized + "/";addedTrailingSlash = true;}// Resolve occurrences of "//" in the normalized pathwhile (true) {int index = normalized.indexOf("//");if (index < 0) {break;}normalized = normalized.substring(0, index) + normalized.substring(index + 1);}// Resolve occurrences of "/./" in the normalized pathwhile (true) {int index = normalized.indexOf("/./");if (index < 0) {break;}normalized = normalized.substring(0, index) + normalized.substring(index + 2);}// Resolve occurrences of "/../" in the normalized pathwhile (true) {int index = normalized.indexOf("/../");if (index < 0) {break;}

过滤掉了请求中的路径穿越符号 /…/,也就导致了该漏洞只能读取webapps目录下的文件。

Step5 ServletOutputStream.write()

经过Tomcat内部流程处理,经过Tomcat的Container和Connector,最终返回给客户端。

特别注意

关键参数req_uri决定了我们可以读取webapps下其他目录的文件。当为’asdf’时无法匹配到webapps下的路径,所以路由到tomcat默认的ROOT目录;二来是为了让tomcat将请求流到DefaultServlet,从而触发漏洞。

真实文件 请求路径
webapps/manager manager/asdf
webapps/ROOT /asdf

0x2 文件包含漏洞

该漏洞的触发与上个相似,只不过servlet的分支不同,该漏洞走的是JspServlet,所有的jsp文件的路由
将漏洞利用代码修改为

Step 1 JspServlet -> service() -> serviceJspFile()

从CoyoteAdapter进行分发,这里分发到jspservlet路由,因此我们要在jspservlet上下断点

0x05 后续

  1. 自己编写ajp协议
  2. tomcat web服务器交互原理
  3. java 反射调用链分析

0x06 参考链接

  1. https://xz.aliyun.com/t/7683
  2. https://www.anquanke.com/post/id/199448#h2-7
  3. https://www.freebuf.com/column/227973.html
  4. https://www.jianshu.com/p/f902ac5d29e4

CVE-2020-1938 /CNVD-2020-10487漏洞调试相关推荐

  1. java毕业生设计蛋糕销售网站演示录像2020计算机源码+系统+mysql+调试部署+lw

    java毕业生设计蛋糕销售网站演示录像2020计算机源码+系统+mysql+调试部署+lw java毕业生设计蛋糕销售网站演示录像2020计算机源码+系统+mysql+调试部署+lw 本源码技术栈: ...

  2. java毕业生设计医院药品管理系统演示录像2020计算机源码+系统+mysql+调试部署+lw

    java毕业生设计医院药品管理系统演示录像2020计算机源码+系统+mysql+调试部署+lw java毕业生设计医院药品管理系统演示录像2020计算机源码+系统+mysql+调试部署+lw 本源码技 ...

  3. 心音数据库_小V云端数据库 | 2020.9.14—2020.9.18

    桂花的芬芳 在雨后空气中弥散开来 似为湿润的情绪 赠予了一丝甜蜜 小V云端数据库 2020.9.14-2020.9.18 资讯情报关键词 健康.示范.安全 V宝体检,助力成长 2020年9月14日上午 ...

  4. kylin源码调试_Apache Kylin 命令注入漏洞调试分析(CVE-2020-1956)

    原标题:Apache Kylin 命令注入漏洞调试分析(CVE-2020-1956) 1.前言 Apache Kylin是一个开源的.分布式的分析型数据仓库,提供Hadoop/Spark 之上的 SQ ...

  5. 从ICLR 2020、AAAI 2020看对话系统近期研究进展

    ©PaperWeekly 原创 · 作者|王馨月 学校|四川大学本科生 研究方向|自然语言处理 本文盘点近期 ICLR 2020.AAAI 2020 上几篇对话系统相关的论文. ICLR 2020 论 ...

  6. SRC漏洞挖掘--CNVD国家信息安全漏洞共享平台

    目录 0x00 简介 0x01 过程中使用的工具 0x02 详细过程 一.  寻找挖洞目标 1.1 工具介绍 1.2 目标检索过程 二. 趁手的挖洞工具 2.1 工具介绍 2.2 工具下载链接 2.3 ...

  7. flash怎么强制gc_flash漏洞调试技巧

    本周中心抓到一个在野的flash 0day(相关信息见此链接),于是又捡起了一年多的flash 漏洞的相关知识,遂总结一下. 普通的trace 调试flasher样本一般建议使用调试版的flash p ...

  8. 从ACL 2020和ICLR 2020看知识图谱嵌入的近期研究进展

    ©PaperWeekly 原创 · 作者|舒意恒 学校|南京大学硕士生 研究方向|知识图谱 本文介绍三篇发表于 ACL 2020 或 ICLR 2020 关于知识图谱嵌入的近期研究进展. 1. ACL ...

  9. 2020年十大开源漏洞回顾

     聚焦源代码安全,网罗国内外最新资讯! WhiteSource 公司基于 NVD.安全公告和开源项目问题追踪工具等回顾了2020年出现的十大开源漏洞.如下: 1.Lodash CVE-2020-820 ...

  10. 博诺杯工业机器人比赛2019_嘉兴技师学院 智能制造 师生同台献技艺 赛场争相出佳绩——记2020机械行业“博诺杯”工业机器人维修调试与技术应用大赛...

    近日,工业机器人项目组团队参加了2020机械行业"博诺杯"教育技能大赛之工业机器人维修调试与技术应用大赛,嘉兴技师学院教师倪晨玮.李仁财.马宗耀以及6位学生分别参加教师组.学生组的 ...

最新文章

  1. 个人网站架构设计(一)
  2. 从音乐到全“声”态,腾讯音乐发展的“中国范本”
  3. oracle查询排序asc/desc 多列 order by
  4. 使用Swift触摸任意位置以关闭iOS键盘
  5. [转]跟我一起写Makefile系列
  6. 基本数据类型与字符串之间的转换
  7. python交通调查数据处理_python数据分析--关于时间类型数据处理的一种方法
  8. Spring - 事件监听机制 源码解析
  9. 借了你的爱,用我一辈子来还
  10. K8s预选策略和优选函数简介
  11. 关闭win10任务视图功能
  12. Banner——轮播图
  13. matlab白光干涉,matlab白光干涉
  14. 从redis中取值 然后通过list进行分页查询
  15. 宝尚在线炒股 12.22 午评
  16. 怎么申请企业电子邮箱?TOM企业邮箱注册电子邮件流程详解
  17. 百度知道推广技巧大全
  18. 详解设计模式:桥接模式
  19. PHP 访问 samba,如何使用SMB共享绕过PHP远程文件包含限制进行安全测试
  20. dumpbin的命令

热门文章

  1. hdu4699 Editor(栈)
  2. Android 渠道抽成,内容为主,渠道为辅,国内Android商店何时才能调整分成比?
  3. (转载)file_get_contents(php://input)
  4. 嵌入式行业和职业选择的看法
  5. 【Python】python转义字符
  6. mysql取消安全模式
  7. tx2上装scikit-image
  8. 计算机组装硬件配置清单,组装电脑配置清单
  9. 【已解决】ubuntu无法进入启动页面,全屏出现【ok】并且不停闪烁
  10. QQ邮箱如何快速批量删除所有的垃圾邮件