基于3.6版本的koca框架漏洞升级处理
本文档分为两部分,一部分漏洞只需要升级包的版本即可解决,另一部分为需要增加部分适配代码
升级版本即可解决
按照excel顺序编写
<!-- 修复漏洞 MyBatis远程代码执行漏洞(CVE-2020-26945)-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- h2一般用于测试,不建议在生产环境使用。如没有直接使用,可以将此包直接从pom中排除掉-->
<!-- H2 控制台 JNDI 远程代码执行漏洞(CVE-2021-42392)-->
<!-- <dependency>-->
<!-- <groupId>com.h2database</groupId>-->
<!-- <artifactId>h2</artifactId>-->
<!-- <version>2.2.220</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- 修复漏洞 Spring Security 身份认证绕过漏洞(CVE-2022-22978)-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.5.7</version>
</dependency>
<!-- 修复漏洞 Spring Framework 身份认证绕过漏洞(CVE-2023-20860)-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.26</version>
</dependency>
<!-- 修复漏洞 Apache Commons FileUpload 拒绝服务漏洞(CVE-2023-24998)-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.5</version>
</dependency>
<!-- 修复漏洞 Spring Boot 拒绝服务漏洞(CVE-2023-20883)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.5.15</version>
</dependency>
<!-- 修复漏洞 Spring Security 身份验证绕过漏洞(CVE-2024-22257)-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.8.11</version>
</dependency>
snakeyaml升级
对于yaml升级需要额外升级多个包,并且增加配置加载代码
包升级
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.27</version>
</dependency>
新增代码CustomOriginTrackedYamlLoader
/*
* <p>文件名称: CustomOriginTrackedYamlLoader.java</p>
* <p>项目描述: KOCA 金证云原生平台</p>
* <p>公司名称: 深圳市金证科技股份有限公司</p>
* <p>版权所有: (C) 2019-2020</p>
*/
package com.szkingdom.yaml;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.springframework.beans.factory.config.YamlProcessor;
import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.boot.origin.TextResourceOrigin;
import org.springframework.boot.origin.TextResourceOrigin.Location;
import org.springframework.core.io.Resource;
import org.springframework.util.ReflectionUtils;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.BaseConstructor;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.error.Mark;
import org.yaml.snakeyaml.nodes.CollectionNode;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.resolver.Resolver;
/**
*
*
* @author liyong
* @since 2024/7/2
*/
public class CustomOriginTrackedYamlLoader extends YamlProcessor {
private static final boolean HAS_RESOLVER_LIMIT = ReflectionUtils.findMethod(Resolver.class, "addImplicitResolver",
Tag.class, Pattern.class, String.class, int.class) != null;
private final Resource resource;
CustomOriginTrackedYamlLoader(Resource resource) {
this.resource = resource;
setResources(resource);
}
@Override
protected Yaml createYaml() {
LoaderOptions loaderOptions = new LoaderOptions();
loaderOptions.setAllowDuplicateKeys(false);
loaderOptions.setMaxAliasesForCollections(Integer.MAX_VALUE);
loaderOptions.setAllowRecursiveKeys(true);
return createYaml(loaderOptions);
}
private Yaml createYaml(LoaderOptions loaderOptions) {
BaseConstructor constructor = new OriginTrackingConstructor(loaderOptions);
DumperOptions dumperOptions = new DumperOptions();
Representer representer = new Representer(dumperOptions);
Resolver resolver = HAS_RESOLVER_LIMIT ? new NoTimestampResolverWithLimit() : new NoTimestampResolver();
return new Yaml(constructor, representer, dumperOptions, loaderOptions, resolver);
}
List<Map<String, Object>> load() {
final List<Map<String, Object>> result = new ArrayList<>();
process((properties, map) -> result.add(getFlattenedMap(map)));
return result;
}
/**
* {@link Constructor} that tracks property origins.
*/
private class OriginTrackingConstructor extends SafeConstructor {
OriginTrackingConstructor(LoaderOptions loadingConfig) {
super(loadingConfig);
}
@Override
public Object getData() throws NoSuchElementException {
Object data = super.getData();
if (data instanceof CharSequence && ((CharSequence) data).length() == 0) {
return null;
}
return data;
}
@Override
protected Object constructObject(Node node) {
if (node instanceof CollectionNode && ((CollectionNode<?>) node).getValue().isEmpty()) {
return constructTrackedObject(node, super.constructObject(node));
}
if (node instanceof ScalarNode) {
if (!(node instanceof KeyScalarNode)) {
return constructTrackedObject(node, super.constructObject(node));
}
}
if (node instanceof MappingNode) {
replaceMappingNodeKeys((MappingNode) node);
}
return super.constructObject(node);
}
private void replaceMappingNodeKeys(MappingNode node) {
node.setValue(node.getValue().stream().map(KeyScalarNode::get).collect(Collectors.toList()));
}
private Object constructTrackedObject(Node node, Object value) {
Origin origin = getOrigin(node);
return OriginTrackedValue.of(getValue(value), origin);
}
private Object getValue(Object value) {
return (value != null) ? value : "";
}
private Origin getOrigin(Node node) {
Mark mark = node.getStartMark();
Location location = new Location(mark.getLine(), mark.getColumn());
return new TextResourceOrigin(CustomOriginTrackedYamlLoader.this.resource, location);
}
}
/**
* {@link ScalarNode} that replaces the key node in a {@link NodeTuple}.
*/
private static class KeyScalarNode extends ScalarNode {
KeyScalarNode(ScalarNode node) {
super(node.getTag(), node.getValue(), node.getStartMark(), node.getEndMark(), node.getScalarStyle());
}
static NodeTuple get(NodeTuple nodeTuple) {
Node keyNode = nodeTuple.getKeyNode();
Node valueNode = nodeTuple.getValueNode();
return new NodeTuple(KeyScalarNode.get(keyNode), valueNode);
}
private static Node get(Node node) {
if (node instanceof ScalarNode) {
return new KeyScalarNode((ScalarNode) node);
}
return node;
}
}
/**
* {@link Resolver} that limits {@link Tag#TIMESTAMP} tags.
*/
private static class NoTimestampResolver extends Resolver {
@Override
public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
if (tag == Tag.TIMESTAMP) {
return;
}
super.addImplicitResolver(tag, regexp, first);
}
}
/**
* {@link Resolver} that limits {@link Tag#TIMESTAMP} tags.
*/
private static class NoTimestampResolverWithLimit extends Resolver {
@Override
public void addImplicitResolver(Tag tag, Pattern regexp, String first, int limit) {
if (tag == Tag.TIMESTAMP) {
return;
}
super.addImplicitResolver(tag, regexp, first, limit);
}
}
}
新增代码CustomYamlPropertySourceLoader
/*
* <p>文件名称: CustomYamlPropertySourceLoader.java</p>
* <p>项目描述: KOCA 金证云原生平台</p>
* <p>公司名称: 深圳市金证科技股份有限公司</p>
* <p>版权所有: (C) 2019-2020</p>
*/
package com.szkingdom.yaml;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;
/**
*
*
* @author liyong
* @since 2024/7/2
*/
public class CustomYamlPropertySourceLoader implements PropertySourceLoader {
@Override
public String[] getFileExtensions() {
return new String[] { "yml", "yaml" };
}
@Override
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
if (!ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", getClass().getClassLoader())) {
throw new IllegalStateException(
"Attempted to load " + name + " but snakeyaml was not found on the classpath");
}
List<Map<String, Object>> loaded = new CustomOriginTrackedYamlLoader(resource).load();
if (loaded.isEmpty()) {
return Collections.emptyList();
}
List<PropertySource<?>> propertySources = new ArrayList<>(loaded.size());
for (int i = 0; i < loaded.size(); i++) {
String documentNumber = (loaded.size() != 1) ? " (document #" + i + ")" : "";
propertySources.add(new OriginTrackedMapPropertySource(name + documentNumber,
Collections.unmodifiableMap(loaded.get(i)), true));
}
return propertySources;
}
}
在resource下的META-INF文件夹下的spring.factories(如果没有就新增)
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
com.szkingdom.yaml.CustomYamlPropertySourceLoader
其他漏洞
Nginx ngx_http_mp4_module 越界写入漏洞(CVE-2022-41742)
请自行升级nginx版本