springboot2对应tomcat的AJP漏洞

背景

2020年1月6日,国家信息安全漏洞共享平台(CNVD)收录了由北京长亭科技有限公司发现并报送的Apache Tomcat文件包含漏洞(CNVD-2020-10487,对应CVE-2020-1938)。攻击者利用该漏洞,可在未授权的情况下远程读取特定目录下的任意文件。目前,漏洞细节尚未公开,厂商已发布新版本完成漏洞修复。

具体公告: https://www.cnvd.org.cn/webin…

一、漏洞描述

      Apache与Tomcat都是Apache开源组织开发的用于处理HTTP服务的项目,两者都是免费的,都可以做为独立的Web服务器运行。

      Apache Tomcat服务器存在文件包含漏洞,攻击者可利用该漏洞读取或包含 Tomcat 上所有 webapp 目录下的任意文件,如:webapp 配置文件或源代码等。

二、漏洞危害等级

        高

三、影响版本

该文件包含漏洞影响以下版本:

  • 7.*分支7.0.100之前版本,建议更新到7.0.100版本;

  • 8.*分支8.5.51之前版本,建议更新到8.5.51版本;

  • 9.*分支9.0.31之前版本,建议更新到9.0.31版本。

    扫描二维码关注公众号,回复: 9832178 查看本文章

四、AJP 协议

根据 apache 官网 AJP 协议相关介绍:

The original document was written by Dan Milstein, [email protected] on December 2000.

Overview of the protocol

The ajp13 protocol is packet-oriented. A binary format was presumably chosen over the more readable plain text for reasons of performance. The web server communicates with the servlet container over TCP connections. To cut down on the expensive process of socket creation, the web server will attempt to maintain persistent TCP connections to the servlet container, and to reuse a connection for multiple request/response cycles.

Once a connection is assigned to a particular request, it will not be used for any others until the request-handling cycle has terminated. In other words, requests are not multiplexed over connections. This makes for much simpler code at either end of the connection, although it does cause more connections to be open at once.

AJP13 协议全称为 Apache JServ Protocol version 1.3 ,最初由 Dan Milstein 于2000年12月发表,后被 Apache 软件基金会 Jakarta 项目采纳。

AJP13 是一种二进制 TCP 传输协议,通过在网络传输二进制包(packet)来完成 Tomcat 与 http 服务器的请求与响应,显然这种方式比纯文本(如 text、xml等)传输的 http 协议效率要高的多。

嵌入式 Tomcat AJP 协议对 SpringBoot 应用的影响

但是 AJP13 协议对浏览器支持不够好,由于其定位是 “ Tomcat 与 HTTP 服务器之间通信的协议”,这或许是 http 协议比较盛行的原因吧。

说完了 Tomcat AJP13 协议的来龙去脉接着,进入主题。

五、SpringBoot 为什么这么火?

spring-boot-starter-web

对 Spring 比较熟悉的话, 基于 SpringBoot 开发 web 应用时,引入 spring-boot-starter-web 组件是必不可少的,spring-boot-starter-web 的职责是负责 web 应用的启动 、初始化、运行和停止。而 spring-boot-starter-web 组件之所以能够跑起来,少不了 http 协议的支持,典型代表就是 tomcat 服务器。

通过翻阅 spring-boot-starter-web 组件的相关 maven 依赖,我们找到了 spring-boot-starter-tomcat 组件。

<dependency>    
<groupId>org.springframework.boot</groupId>   
<artifactId>spring-boot-starter-tomcat</artifactId>   
 <version>2.1.5.RELEASE</version>  
<scope>compile</scope>
</dependency>

接着查找 spring-boot-starter-tomcat 的 maven 依赖, 其引入了 tomcat-embed-core 、tomcat-embed-el 、tomcat-annotations-api 等嵌入式组件。

<dependency>    
<groupId>javax.annotation</groupId>    
<artifactId>javax.annotation-api</artifactId>    
<version>1.3.2</version>    
<scope>compile</scope>  
</dependency>  

<dependency>    
<groupId>org.apache.tomcat.embed</groupId>    
<artifactId>tomcat-embed-core</artifactId>    
<version>9.0.19</version>    
<scope>compile</scope>    
<exclusions>      
<exclusion>        
<artifactId>tomcat-annotations-api</artifactId>        
<groupId>org.apache.tomcat</groupId>      
</exclusion>    
</exclusions>  
</dependency>  

<dependency>    
<groupId>org.apache.tomcat.embed</groupId>    
<artifactId>tomcat-embed-el</artifactId>    
<version>9.0.19</version>    
<scope>compile</scope>  
</dependency>  

<dependency>    
<groupId>org.apache.tomcat.embed</groupId>    
<artifactId>tomcat-embed-websocket</artifactId>    
<version>9.0.19</version>    
<scope>compile</scope>  
</dependency></dependencies>

正是由于这些嵌入式组件的加入,免去了 Tomcat 单独安装部署的繁杂步骤,我想这也是 SpringBoot 非常火的原因之一吧。

六、SpringBoot 对 AJP 协议的支持

springboot开启AJP方法
springboot默认不启用AJP,如果需要开启,则需要手动配置:

通过阅读 tomcat-embed-core 组件,说明嵌入式 tomcat 是支持 AJP 协议的,相关代码在 org.apache.coyote.ajp 目录下。

但是奇怪的是,在 SpringBoot 的 yml 文件配置中,并没有找到 ajp 协议相关的 server 参数配置。

嵌入式 Tomcat AJP 协议对 SpringBoot 应用的影响

笔者猜测,虽然 Tomcat 集成了 ajp 协议,但是不推荐使用吧。但是有没有办法支持 ajp 协议了,答案是可以的,具体代码如下:

SpringBoot 1.x 环境:

@Configurationpublic class AJPConfig {
    private static final String PROTOCOL = "AJP/1.3";
    @Value("${tomcat.ajp.port:8009}")
    private int ajpPort;
    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        Connector ajpConnector = new Connector();
        ajpConnector.setProtocol(PROTOCOL);
        ajpConnector.setPort(ajpPort);
        tomcat.addAdditionalTomcatConnectors(ajpConnector);
        return tomcat;
    }
}

笔者上述配置需要依赖 SpringBoot 1.x 环境。

SpringBoot 2.x 环境:

@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainer() {
    return server -> {
        if (server instanceof TomcatServletWebServerFactory) {
            ((TomcatServletWebServerFactory)   server).addAdditionalTomcatConnectors(redirectConnector());
        }
    };
}

private Connector redirectConnector() {
    Connector connector = new Connector("AJP/1.3");
    connector.setScheme("http");
    connector.setPort(ajpPort);
    connector.setSecure(false);
    connector.setAllowTrace(false);
    return connector;
}

七、AjpProcessor

如果对 tomcat 架构比较了解的话,tomcat 大部分请求与响应由协议(Protocol)中的处理器(Processor)完成的。

嵌入式 Tomcat AJP 协议对 SpringBoot 应用的影响

所以在 tomcat 服务器接收 ajp 请求时, 由 AjpProcessor 来处理 ajp 真实的 request 请求消息。

嵌入式 Tomcat AJP 协议对 SpringBoot 应用的影响

然后,通过 prepareRequest 方法将 ajp 请求内容取出来,设置成 request 对象的 Attribute 属性

嵌入式 Tomcat AJP 协议对 SpringBoot 应用的影响

嵌入式 Tomcat AJP 协议对 SpringBoot 应用的影响

因此,黑客通过设置 request_uri、path_info 、servlet_path 属性值,从而可以读取到 /WEB-INF 下面的所有敏感文件,不限于class、xml、jar等文件。

javax.servlet.include.request_uri
javax.servlet.include.path_info
javax.servlet.include.servlet_path

至于漏洞的详细分析不是本文重点,传送门:

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

 

八、解决方案

如果使用的是外置tomcat,参考公告中的对应方法即可。

如果使用的是springboot的内置tomcat,且手动开启了AJP协议,则需要升级内置tomcat版本。

如果你的springboot(使用默认内置tomcat)并没有手动开启AJP,那么你可以不升级tomcat内置版本。当然你想升级也可以。

1、临时禁用AJP协议端口

在conf/server.xml配置文件中注释掉

<Connector port="8009" protocol="AJP/1.3"redirectPort="8443" />

2、配置ajp配置中的secretRequired跟secret属性来限制认证

3、官方下载最新版下载地址:

https://tomcat.apache.org/download-70.cgi

https://tomcat.apache.org/download-80.cgi

https://tomcat.apache.org/download-90.cgi

Github下载:https://github.com/apache/tomcat/releases

或者升级tomcat到9.0.31

示例:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>tomcat-embed-core</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
<exclusion>
<artifactId>tomcat-embed-el</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
<exclusion>
<artifactId>tomcat-embed-websocket</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.31</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>9.0.31</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>9.0.31</version>
<exclusions>
<exclusion>
<artifactId>tomcat-embed-core</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
</exclusions>
</dependency>

这里列出了tomcat-embed-core,tomcat-embed-el和tomcat-embed-websocket这三个依赖包,实际上应该根据你的具体项目中的依赖来升级版本

九、AJP协议规范

详见https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html

转自:

https://juejin.im/post/5e535765e51d4526ce614328

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

发布了120 篇原创文章 · 获赞 125 · 访问量 107万+

猜你喜欢

转载自blog.csdn.net/yangyangye/article/details/104611522
今日推荐