1、Tomcat漏洞
近日,Apache Tomcat 发布安全更新,更新了一处拒绝服务漏洞(CVE-2021-42340)。攻击者可以通过该漏洞进行拒绝服务攻击。建议广大用户及时升级至最新版本。
1.1、漏洞描述
Apache Tomcat 是阿帕奇(Apache)基金会的一款轻量级 Web应用服务器。该程序实现了对 Servlet 和 JavaServer Page(JSP) 的支持。
CVE-2021-42340
当 Tomcat WebSocket 连接关闭时,用于收集 HTTP 升级连接指标的对象没有被释放,于是造成了内存泄漏。攻击者可通过内存泄露错误进行拒绝服务攻击。
该漏洞CVSS3评分:7.5,危害等级:高危
1.2、CVE 编号
CVE-2021-42340
1.3、FOFA 查询
1.4、影响范围
影响版本:
Apache Tomcat 10.0.0-M10 - 10.0.11
Apache Tomcat 10.1.0-M1 - 10.1.0-M5
Apache Tomcat 9.0.40 - 9.0.53
Apache Tomcat 8.5.60 - 8.5.71
修复版本:
Apache Tomcat 10.0.12
Apache Tomcat 10.1.0-M6
Apache Tomcat 9.0.54
Apache Tomcat 8.5.72
参考:【安全通报】Apache Tomcat 拒绝服务漏洞(CVE-2021-42340)|NOSEC安全讯息平台 - 白帽汇安全研究院
2、查看当前使用的Tomcat版本号
2.1、Maven Repository中查看
比如我们需要查Spring Boot 2.3.12.RELEASE 的内嵌Tomcat版本, 可以打开链接:
如下图, 红框标记的就是tomcat的版本。
2.2、查看dependepency
透过IDE
目前大家主要使用IDEA来进行开发,下面是IDEA查看Tomcat的版本:
透过命令行
Gradle可以采用以下命令打印依赖项:
./gradlew dependencies
数据结果示例:
...
| +--- org.springframework.boot:spring-boot-starter-tomcat:2.1.0.RELEASE
| | +--- javax.annotation:javax.annotation-api:1.3.2
| | +--- org.apache.tomcat.embed:tomcat-embed-core:9.0.12
| | +--- org.apache.tomcat.embed:tomcat-embed-el:9.0.12
| | \--- org.apache.tomcat.embed:tomcat-embed-websocket:9.0.12
| | \--- org.apache.tomcat.embed:tomcat-embed-core:9.0.12
...
Maven可以采用以下命令打印依赖项:
mvn dependency:tree > output.txt # 输出到文件里
3、指定SpringBoot项目内嵌的Tomcat版本
3.1、直接升级SpringBoot的版本
因为SpringBoot内嵌的Tomcat会伴随SpringBoot的升级而升级,所以可以根据需要选择合适的Tomcat版本,这种特别需要升级Tomcat版本时使用,当然还是要根据情况,因为升级SpringBoot的版本也是有成本的。
3.2、排除SpringBoot的Tomcat,指定Tomcat版本
有时候我们需要在特定情况下使用特定的Tomcat版本,这时候总不能因为Tomcat就改变SpringBoot的版本,所以可以采用排除SpringBoot中的Tomcat包,然后手动指定Tomcat的版本,当然还要引入Tomcat相关的包。
Gradle的配置:
compile('org.springframework.boot:spring-boot-starter-web') {
exclude module: "spring-boot-starter-tomcat"
}
compile 'org.apache.tomcat.embed:tomcat-embed-core:+'
compile 'org.apache.tomcat.embed:tomcat-embed-el:+'
compile 'org.apache.tomcat.embed:tomcat-embed-logging-juli:+'
compile 'org.apache.tomcat.embed:tomcat-embed-websocket:+'
如果不指定版本,则会使用最新的Tomcat版本, 否则直接指定对应的版本号。
Maven的配置:
若引入spring-boot的方式为加入<parent>:
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
</parent>
则只需在properties中指定tomcat版本即可,在 pom.xml文件里面添加一个标签<properties>,添加期望的版本。其实这个配置就是指定tomcat版本。
<properties>
<tomcat.version>9.0.54</tomcat.version>
</properties>
添加必要的Jar包:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
4、springboot启动看Tomcat版本号
到这里基本就结束了,springboot启动会看到Tomcat的版本号:
3.3 升级包含多个模块的项目
升级多模块的项目的tomcat版本,子模块依赖tomcat,但是子模块的父项目不可能是org.springframework.boot,而是项目对应的父模块,此时第一种方法就不见效了。那我们粗暴的,先将tomcat依赖剔除,再引入对应版本的tomcat版本不就行了嘛。因为tomcat相关的依赖再spring-boot-starter-web依赖模块下面,所以先将它内部包含的tomcat依赖剔除,再引入对应的tomcat版本,具体如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-annotations-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-annotations-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-annotations-api</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</exclusion>
</exclusions>
</dependency>
5、其他方式
修改內置的默認版本
即在 pom.xml 文件裏面添加一個標籤<properties>
,添加指望的版本<tomcat.version>8.0.30</tomcat.version>
如何知道修改是否成功?
修改爲<tomcat.version>8.0.30</tomcat.version>
啓動信息:
2018-03-15 00:46:26.275 INFO 47112 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2018-03-15 00:46:26.282 INFO 47112 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat 2018-03-15 00:46:26.283 INFO 47112 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.0.30 2018-03-15 00:46:26.333 INFO 47112 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2018-03-15 00:46:26.333 INFO 47112 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1000 ms
可是,有時候啓動會報錯:
Caused by: java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory at org.apache.catalina.util.LifecycleBase.<clinit>(LifecycleBase.java:37) at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:169) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:164) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:134) ... 13 common frames omitted
顯然是缺乏 jar 包,在 dependency 裏面添加如下二者之一便可:
<dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-juli</artifactId> <version>${tomcat.version}</version> </dependency>
若是項目是以war包形式打包部署,即pom
標籤是war
,則推薦使用上面這個。
若是項目是使用內嵌Tomcat servlet容器形式打包部署,推薦使用下面這個,其groupId和artifactId皆是embed類型的jar包。
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-logging-juli</artifactId> <version>${tomcat.version}</version> </dependency>
可是,還有一個問題:spring-boot-starter-web
是包含spring-boot-starter-tomcat
的,查看 pom 文件可知。
也就是說,咱們沒有必要重複添加spring-boot-starter-tomcat
,一個spring-boot-starter-web
就能夠把一個典型的 spring web 項目搭建成功,也方便 jar 包的管理,此時須要額外添加Tomcat的GA:
<properties> <tomcat.version>8.0.30</tomcat.version> </properties> <!-- 顯式指定Tomcat版本 --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>${tomcat.version}</version> </dependency>
参考:
【安全通报】Apache Tomcat 拒绝服务漏洞(CVE-2021-42340)|NOSEC安全讯息平台 - 白帽汇安全研究院
查看和指定SpringBoot内嵌Tomcat的版本 - 简书
springboot:修改內置tomcat版本 - 菜鳥學院