开发者

springboot版本升级以及解决springsecurity漏洞的问题

目录
  • 背景
  • 需求
  • 版本改造问题
    • 坑一:类不存在,或包不存在
    • 坑二:idea中maven设置,最好调整成maven运行(推荐)
  • 代码兼容问题
    • 问题一:alibaba.fastjson.JSONObject cannot be cast to xx
    • 问题二:升级后通过feign调用认证服务接口/oauth/check_token接口提示如下
    • 问题三:feign调用token校验接口,在项目中未搜索到
  • jar包依赖冲突问题
    • 方式一:选择依赖的模块,鼠标右键,选择show dependency
    • 方式二:安装一个maven-helper插件
  • 总结

    背景

    项目中要解决 Spring Security RegexRequestMatcher 认证绕过漏洞(CVE-2022-22978) 漏洞问题,并且需要将项目的版本整体升级到boot版本2.1.7,升级改造过程非常的痛苦,一方面对整个框架的代码不是很熟悉,另外对解决漏洞问题相对较少。

    需求

    解决Spring Security RegexRequestMatcher 认证绕过漏洞(CVE-2022-22978) 漏洞,升级boot版本2.1.7

    改造前父pom如下(部分依赖省略):

    <?XML version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
     
    	<groupId>com.gisquest.realestate</groupId>
    	<artifactId>gisqrealestate-unityplatform-core</artifactId>
    	<version>2.2.1.RELEASE</version>
    	<modules>
    		<module>unityplatform-security</module>
            <module>unityplatform-microauth</module>
            <module>unityplatform-apigateway</module>
            <module>unityplatform-servicediscovery</module>
    		<module>unityplatform-microappadmin</module>
            <module>unityplatform-apigateway-core</module>
            <module>unityplatform-apigateway-app</module>
    		<module>unityplatform-microauth-app</module>
    		<module>unityplatform-core-comm</module>
    	</modules>
    	<packaging>pom</packaging>
     
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<spring-boot-admin.version>1.5.6</spring-boot-admin.version>
    		<jjwt.version>0.7.0</jjwt.version>
    		<commons-lang3.version>3.3.2</commons-lang3.version>
    		<swagger2.version>2.7.0</swagger2.version>
    		<apollo-client.version>1.0.0</apollo-client.version>
    		<jackson.version>2.10.2</jackson.version>
     
    		<!--micro version-->
    		<micro-apigateway.version>2.2.1.RELEASE</micro-apigateway.version>
    		<micro-auth.version>2.2.1.RELEASE</micro-auth.version>
            <micro-comm.version>2.2.1.RELEASE</micro-comm.version>
     
    		<micro-apigateway.img.version>2.2.RELEASE</micro-apigateway.img.version>
    		<micro-auth.img.version>2.2.RELEASE</micro-auth.img.version>
    		<micro.img.version>2.2.RELEASE</micro.img.version>
     
    		<com.hanweb.SecurityUtil.version>1.0</com.hanweb.SecurityUtil.version>
     
    		<!--XStream -->
    		<xstream.version>1.4.20</xstream.version>
     
    		<spring.version>5.3.20</spring.version>
    		<spring-security.version>5.5.8</spring-security.version>
    	</properties>
    	<dependencyManagement>
    		<dependencies>
     
    			<dependency>
    				<groupId>io.spring.platform</groupId>
    				<artifactId>platform-bom</artifactId>
    				<version>Brussels-SR7</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
    			<dependency>
    				<groupId>org.springframework.cloud</groupId>
    				<artifactId>spring-cloud-dependencies</artifactId>
    				<version>Edgware.SR2</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
    		</dependencies>
    	</dependencyManagement>
    </project>

    漏洞解决方案

    gisqrealewww.devze.comstate-unityplatform-core 项目下 解决Spring Security RegexRequestMatcher 认证绕过漏洞(CVE-2022-22978) 漏洞

    升级boot版本2.1.7(和快速构建保持一致)

    注意下升级之后一些配置文件(例如Redis,文件限制大小等) 和 代码 不兼容问题

    漏洞影响版本

    5.5.0 <= Spring Security < 5.5.7

    5.6.0 <= Spring Security < 5.6.4

    版本改造问题

    改造前 版本

    <spring-cloud.version>Edgware.SR2</spring-cloud.version> 
    <spring-boot.version>1.5.10.RELEASE </spring-boot.version>

    升级到2.x版本

    <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    <spring-boot.version>2.1.7.RELEASE</spring-boot.version>

    问题一:项目改造前是自定义的springboot依赖,现要求去掉原先的自定义封装依赖

    刚开始我是把原先自定义的springboot依赖的父依赖直接移到最外层,大概过程如下,导致出现一堆问题。

    springboot版本升级以及解决springsecurity漏洞的问题

    坑一:类不存在,或包不存在

    项目中出现大量的类不存在,但是明明可以用鼠标点击进去,此类问题经常是idea,什么缓存,或者是pom依赖下载不全导致,然后就陷入了这个误区,一直以为是idea的问题。

    先是清理 idea缓存、执行mvn idea:idea命令等方式很多次还是无法解决。

    然后分支代码提交后,同事检出也是同样的问题,项目还是无法启动,保错也是提示类不存在等。

    此时我就怀疑可能不是idea的问题了。

    后面就换了一种方式

    <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>1.5.10.RELEASE</version>
       <relativePath />
    </parent>

    改成

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-dependencies</artifactId>
       <version>${spring-boot.version}</version>
       <type>pom</type>
       <scope>import</scope>
    </dependency>

    改成这样后终于正常了,不在提示类不存在,包不存在等问题了。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<groupId>com.gisquest.realestate</groupId>
    	<artifactId>gisqrealestate-unityplatform-core</artifactId>
    	<version>2.2.1.RELEASE</version>
    	<modelVersion>4.0.0</modelVersion>
    	<packaging>pom</packaging>
    	<modules>
    		<module>unityplatform-security</module>
            <module>unityplatform-microauth</module>
            <module>unityplatform-apigateway</module>
            <module>unityplatform-servicediscovery</module>
    		<module>unityplatform-microappadmin</module>
            <module>unityplatform-apigateway-core</module>
            <module>unityplatform-apigateway-app</module>
    		<module>unityplatform-microauth-app</module>
    		<module>unityplatform-core-comm</module>
    	</modules>
     
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<spring-boot-admin.version>1.5.6</spring-boot-admin.version>
    		<jjwt.version>0.7.0</jjwt.version>
    		<commons-lang3.version>3.3.2</commons-lang3.version>
    		<swagger2.version>2.7.0</swagger2.version>
    		<apollo-client.version>1.0.0</apollo-client.version>
    		<jackson.version>2.10.2</jackson.version>
    		<!--micro version-->
    		<micro-apigateway.version>2.2.1.RELEASE</micro-apigateway.version>
    		<micro-auth.version>2.2.1.RELEASE</micro-auth.version>
            <micro-comm.version>2.2.1.RELEASE</micro-comm.version>
    		<micro-apigateway.img.version>2.2.RELEASE</micro-apigateway.img.version>
    		<micro-auth.img.version>2.2.RELEASE</micro-auth.img.version>
    		<micro.img.version>2.2.RELEASE</micro.img.version>
    		<com.hanweb.SecurityUtil.version>1.0</com.hanweb.SecurityUtil.version>
    		<!--XStream -->
    		<xstream.version>1.4.19</xstream.version>
    		<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    		<spring-boot.version>2.1.7.RELEASE</spring-boot.version>
    		<eureka.version>2.1.0.RELEASE</eureka.version>
    		<openfeign.version>2.0.0.RELEASE</openfeign.version>
    		<zuul.version>2.1.2.RELEASE</zuul.version>
    		<commons-lang.version>2.6</commons-lang.version>
    		<commons-collections.version>3.2.2&ljst;/commons-collections.version>
    		<commons-beanutils.version>1.9.3</commons-beanutils.version>
    	</properties>
    	<dependencyManagement>
    		<dependencies>
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-dependencies</artifactId>
    				<version>${spring-boot.version}</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
     
    			<dependency>
    				<groupId>org.springframework.cloud</groupId>
    				<artifactId>spring-cloud-dependencies</artifactId>
    				<version>${spring-cloud.version}</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
     
    	 
    </project>

    坑二:idea中maven设置,最好调整成maven运行(推荐)

    否则会出现稀奇古怪的问题,比如上面的之前用parent依赖方式我本地可以跑(奇了怪),但是同事拉下拉却跑不了,切换成eclipse也同样项目跑不起来。

    springboot版本升级以及解决springsecurity漏洞的问题

    经过一番折腾代码是跑起来了总算不提示类不存等问题。

    代码兼容问题

    org.springframework.data.redis.serializer.SerializationException: Cannot deserialize

    org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is Java.io.InvalidClassException: org.springframework.security.core.authority.SimpleGrantedAuthority; local class incompatible: stream classdesc serialVersionUID = 420, local class serialVersionUID = 510

        at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:84) ~[spring-data-redis-2.1.10.RELEASE.jar!/:2.1.10.RELEASE]

    解决方法:

    redis跨版本升级后,需要把redis缓存清理一下

    问题一:alibaba.fastjson.JSONObject cannot be cast to xx

    java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.gisquest.realestate.security.validate.code.ValidateCode

    • 改造前逻辑
         @Override
        public ValidateCode get(ServletWebRequest request, ValidateCodeType validateCodeType) {
            Object object = redisTemplate.opsForValue().get(buildKey(request, validateCodeType));
            if (object == null) {
                return null;
            }
       
            return (ValidateCodewww.devze.com)object ;
        }
    • 改造后
        @Override
        public ValidateCode get(ServletWebRequest request, ValidateCodeType validateCodeType) {
            Object object = redisTemplate.opsForValue().get(buildKey(request, validateCodeType));
            if (object == null) {
                return null;
            }
            String josn =JSON.toJSONString(object);
            return JSONObject.parseobject(josn,ValidateCode.class);
        }

    问题解决!!!!

    问题二:升级后通过feign调用认证服务接口/oauth/check_token接口提示如下

    Illegal hexadecimal character - at index 8

    org.apache.commons.codec.DecoderException: Illegal hexadecimal character - at index 8

    at org.apache.commons.codec.binary.Hex.toDigit(Hex.java:286)

    at org.apache.commons.codec.binary.Hex.decodeHex(Hex.java:106)

    at com.gisquest.r编程客栈ealestate.utils.Encodes.decodeHex(Encodes.java:41)

    原因版本问题

    改造前spring-security-core-4.2.4.RELEASE

    在AbstractUserDetailsAuthenticationProvider在实现类中additionalAuthenticationChecks方法逻辑如下

    	protected void additionalAuthenticationChecks(UserDetails userDetails,
    			UsernamePasswordAuthenticationToken authentication)
    			throws AuthenticationException {
    		Object salt = null;
     
    		if (this.saltSource != null) {
    			salt = this.saltSource.getSalt(userDetails);
    		}
     
    		if (authentication.getCredentials() == null) {
    			logger.debug("Authentication failed: no credentials provided");
     
    			throw new BadCredentialsException(messages.getMessage(
    					"AbstractUserDetailsAuthenticationProvider.badCredentials",
    					"Bad credentials"));
    		}
     
    		String presentedPassword = authentication.getCredentials().toString();
     
    		if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
    				presentedPassword, salt)) {
    			logger.debug("Authentication failed: password does not match stored value");
     
    			throw new BadCredentialsException(messages.getMessage(
    					"AbstractUserDetailsAuthenticationProvider.badCredentials",
    					"Bad credentials"));
    		}
    	}
    • 改造后

    spring-security-core-5.1.6.RELEASE版本中AbstractUserDetailsAuthenticationProvider在实现类中改方法additionalAuthenticationChecks

       protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
            if (authentication.getCredentials() == null) {
                this.logger.debug("Authentication failed: no credentials provided");
                throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
            } else {
                String presentedPassword = authentication.getCredentials().toString();
                if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
                    this.logger.debug("Authentication failed: password dwww.devze.comoes not match stored value");
                    throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
                }
            }
        }

    逻辑变化了

    springboot版本升级以及解决springsecurity漏洞的问题

    使用了自定义的密码加密类

    springboot版本升级以及解决springsecurity漏洞的问题

    密码加密方式发现不一样了,因此按照原先代码逻辑获取到的前后密码其实是一样的,但是升级后GisqPasswordEncoder起了作用,因此在比较时应该时加密后的匹配

    springboot版本升级以及解决springsecurity漏洞的问题

    因此改成这样

    springboot版本升级以及解决springsecurity漏洞的问题

    问题三:feign调用token校验接口,在项目中未搜索到

    后来打断点才发现竟然后spring-security-oaruth2包内部类CheckTokenEndpoint中的接口,无语,我还以为是自己定义的呢找了半天未找打!!!!!

    jar包依赖冲突问题

    方式一:选择依赖的模块,鼠标右键,选择show dependency

    如果有冲突会出现报红!!!

    springboot版本升级以及解决springsecurity漏洞的问题

    方式二:安装一个maven-helper插件

    如果有冲突会自动显示,然后去排处即可

    springboot版本升级以及解决springsecurity漏洞的问题

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜