众所周知,Struts2经常被爆出一些奇奇怪怪的大漏洞,并且Struts2.3和Struts2.5是两个不同的分支,就像Python2.7和Python3一样,并且Struts2.3的分支在2018年已经停止维护了,想要修复漏洞那么只能做大版本升级。
本次为远程执行漏洞CVE-2021-31805(S2-062),由于版本差距悬殊,用时一天半,现在记录一下改了什么。

pom.xml

pom.xml(就是项目根目录那个)的<properties>中的版本升级
这个项目的Spring版本是3.1.2.RELEASE如果小于3.1请继续用Quartz1

<slf4j-api.version>1.7.30</slf4j-api.version>
<struts.version>2.5.30</struts.version>
<quartz.version>2.0.2</quartz.version>
<cglib.version>3.2.4</cglib.version>
<commons-lang3.version>3.9</commons-lang3.version>

<dependencyManagement> -> <dependencies>
新增加的依赖,其中Struts2.5需要Log4j2,为了让原有项目的Log4j1能正常运行,增加log4j-to-slf4j把日志转到slf4j

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j-api.version}</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>${slf4j-api.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-to-slf4j</artifactId>
    <version>2.17.2</version>
</dependency>

Struts2的那条需要修改一下,增加了log4j-api,也就是Log4j2的东西,他将被log4j-to-slf4j代替所以不用了

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-core</artifactId>
    <version>${struts.version}</version>
    <exclusions>
        <exclusion>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
        </exclusion>
        <exclusion>
            <artifactId>log4j-api</artifactId>
            <groupId>org.apache.logging.log4j</groupId>
        </exclusion>
    </exclusions>
</dependency>

至于子Maven包中的pom.xml,只需要将这些<dependencies>修改同步复制过去就行,区别在于要去掉<version>这一行,如不行,删掉报错缺少的包的<scope>provided</scope>配置。

spring-quartzJob.xml

因为版本更新,class的名字有变化,简单的说就是两个批量替换
Bean -> FactoryBean
FactoryFactoryBean -> FactoryBean
在Linux下可以用这两条命令实现

sed -i 's/Bean/FactoryBean/g' spring-quartzJob.xml
sed -i 's/FactoryFactoryBean/FactoryBean/g' spring-quartzJob.xml

struts.xml

首先要把头部的版本号换一下,2.3换成2.5,简单的说,就是把文件第二行的

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">

换成

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd">

另外在Struts2.5中多了一个叫Allowed Methods的功能,可以限制action允许请求的方法名,写在class注释@Action的旁边

@Action(value="zyymeAction",results={@Result(name="success",location="/success.jsp")})
@AllowedMethods(value={("add"),("update"),("delete")})

如果不配置,那就默认所有方法都不能被请求,最简单的方式就是配置一个全局配置允许所有方法
<struts> -> <package>中加入

<global-allowed-methods>regex:.*</global-allowed-methods>

因为配置有顺序要求,你可以尝试在原有标签的中间插入这一条直到他不报错为止,他的顺序要求是这样的

<result-types>
<interceptors>
<default-interceptor-ref>
<default-action-ref>
<default-class-ref>
<global-results>
<global-allowed-methods>
<global-exception-mappings>
<action>

web.xml

因为Struts2.5的包路径有所变化,需要删掉ng这一层
简单的说就是将.ng.替换成.
在Linux下可以用这条命令实现

sed -i 's/.ng././g' web.xml