CVE-2020-1938 /CNVD-2020-10487漏洞调试
0x01 漏洞背景
CVE-2020-1938 是 Tomcat-Ajp 协议漏洞分析,Tomcat是由Apache软件基金会属下Jakarta项目开发的Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和JavaServer Page(JSP)的支持。由于Tomcat本身也内含了HTTP服务器,因此也可以视作单独的Web服务器。
0x02 影响版本
- Apache Tomcat 9.x < 9.0.31
- Apache Tomcat 8.x < 8.5.51
- Apache Tomcat 7.x < 7.0.100
- 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 调试原理
分为两种情况:
- 调试器开端口,远程JVM连接本地端口
- 远程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请求的流程
- 用户发送请求至8080端口,被Connector获取后,Connector中的Processor用于封装Request,Adapter用于将封装好的Request交给Container。
- Connector把该请求交给Container中的Engine来处理,并等待Engine的回应。
- Engine 获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host。
- Engine搜索对应的主机,/test匹配到Context,
- path="/test"的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL PATTERN为*.jsp的Servlet,对应于JspServlet类(匹配不到指定Servlet的请求对应DefaultServlet类)
- Wrapper是最底层的容器,负责管理一个Servlet。构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost(),执行业务逻辑、数据存储等程序。
- Context把执行完之后的HttpServletResponse对象返回给Host
- Host把HttpServletResponse对象返回给Engine
- Engine把HttpServletResponse对象返回Connector
- 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 后续
- 自己编写ajp协议
- tomcat web服务器交互原理
- java 反射调用链分析
0x06 参考链接
- https://xz.aliyun.com/t/7683
- https://www.anquanke.com/post/id/199448#h2-7
- https://www.freebuf.com/column/227973.html
- https://www.jianshu.com/p/f902ac5d29e4
CVE-2020-1938 /CNVD-2020-10487漏洞调试相关推荐
- java毕业生设计蛋糕销售网站演示录像2020计算机源码+系统+mysql+调试部署+lw
java毕业生设计蛋糕销售网站演示录像2020计算机源码+系统+mysql+调试部署+lw java毕业生设计蛋糕销售网站演示录像2020计算机源码+系统+mysql+调试部署+lw 本源码技术栈: ...
- java毕业生设计医院药品管理系统演示录像2020计算机源码+系统+mysql+调试部署+lw
java毕业生设计医院药品管理系统演示录像2020计算机源码+系统+mysql+调试部署+lw java毕业生设计医院药品管理系统演示录像2020计算机源码+系统+mysql+调试部署+lw 本源码技 ...
- 心音数据库_小V云端数据库 | 2020.9.14—2020.9.18
桂花的芬芳 在雨后空气中弥散开来 似为湿润的情绪 赠予了一丝甜蜜 小V云端数据库 2020.9.14-2020.9.18 资讯情报关键词 健康.示范.安全 V宝体检,助力成长 2020年9月14日上午 ...
- kylin源码调试_Apache Kylin 命令注入漏洞调试分析(CVE-2020-1956)
原标题:Apache Kylin 命令注入漏洞调试分析(CVE-2020-1956) 1.前言 Apache Kylin是一个开源的.分布式的分析型数据仓库,提供Hadoop/Spark 之上的 SQ ...
- 从ICLR 2020、AAAI 2020看对话系统近期研究进展
©PaperWeekly 原创 · 作者|王馨月 学校|四川大学本科生 研究方向|自然语言处理 本文盘点近期 ICLR 2020.AAAI 2020 上几篇对话系统相关的论文. ICLR 2020 论 ...
- SRC漏洞挖掘--CNVD国家信息安全漏洞共享平台
目录 0x00 简介 0x01 过程中使用的工具 0x02 详细过程 一. 寻找挖洞目标 1.1 工具介绍 1.2 目标检索过程 二. 趁手的挖洞工具 2.1 工具介绍 2.2 工具下载链接 2.3 ...
- flash怎么强制gc_flash漏洞调试技巧
本周中心抓到一个在野的flash 0day(相关信息见此链接),于是又捡起了一年多的flash 漏洞的相关知识,遂总结一下. 普通的trace 调试flasher样本一般建议使用调试版的flash p ...
- 从ACL 2020和ICLR 2020看知识图谱嵌入的近期研究进展
©PaperWeekly 原创 · 作者|舒意恒 学校|南京大学硕士生 研究方向|知识图谱 本文介绍三篇发表于 ACL 2020 或 ICLR 2020 关于知识图谱嵌入的近期研究进展. 1. ACL ...
- 2020年十大开源漏洞回顾
聚焦源代码安全,网罗国内外最新资讯! WhiteSource 公司基于 NVD.安全公告和开源项目问题追踪工具等回顾了2020年出现的十大开源漏洞.如下: 1.Lodash CVE-2020-820 ...
- 博诺杯工业机器人比赛2019_嘉兴技师学院 智能制造 师生同台献技艺 赛场争相出佳绩——记2020机械行业“博诺杯”工业机器人维修调试与技术应用大赛...
近日,工业机器人项目组团队参加了2020机械行业"博诺杯"教育技能大赛之工业机器人维修调试与技术应用大赛,嘉兴技师学院教师倪晨玮.李仁财.马宗耀以及6位学生分别参加教师组.学生组的 ...
最新文章
- 个人网站架构设计(一)
- 从音乐到全“声”态,腾讯音乐发展的“中国范本”
- oracle查询排序asc/desc 多列 order by
- 使用Swift触摸任意位置以关闭iOS键盘
- [转]跟我一起写Makefile系列
- 基本数据类型与字符串之间的转换
- python交通调查数据处理_python数据分析--关于时间类型数据处理的一种方法
- Spring - 事件监听机制 源码解析
- 借了你的爱,用我一辈子来还
- K8s预选策略和优选函数简介
- 关闭win10任务视图功能
- Banner——轮播图
- matlab白光干涉,matlab白光干涉
- 从redis中取值 然后通过list进行分页查询
- 宝尚在线炒股 12.22 午评
- 怎么申请企业电子邮箱?TOM企业邮箱注册电子邮件流程详解
- 百度知道推广技巧大全
- 详解设计模式:桥接模式
- PHP 访问 samba,如何使用SMB共享绕过PHP远程文件包含限制进行安全测试
- dumpbin的命令