Switch default check level (#11279)
This commit is contained in:
parent
fc00efd704
commit
67993e168e
|
|
@ -291,6 +291,8 @@ public interface LoggerCodeConstants {
|
||||||
|
|
||||||
String PROTOCOL_FAILED_DECODE = "4-20";
|
String PROTOCOL_FAILED_DECODE = "4-20";
|
||||||
|
|
||||||
|
String PROTOCOL_UNTRUSTED_SERIALIZE_CLASS = "4-21";
|
||||||
|
|
||||||
// Config module
|
// Config module
|
||||||
String CONFIG_FAILED_CONNECT_REGISTRY = "5-1";
|
String CONFIG_FAILED_CONNECT_REGISTRY = "5-1";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import java.util.Set;
|
||||||
|
|
||||||
public interface AllowClassNotifyListener {
|
public interface AllowClassNotifyListener {
|
||||||
|
|
||||||
SerializeCheckStatus DEFAULT_STATUS = SerializeCheckStatus.STRICT;
|
SerializeCheckStatus DEFAULT_STATUS = SerializeCheckStatus.WARN;
|
||||||
|
|
||||||
void notify(SerializeCheckStatus status, Set<String> prefixList);
|
void notify(SerializeCheckStatus status, Set<String> prefixList);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.utils;
|
package org.apache.dubbo.common.utils;
|
||||||
|
|
||||||
import org.apache.dubbo.common.logger.Logger;
|
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
|
||||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.GenericArrayType;
|
import java.lang.reflect.GenericArrayType;
|
||||||
|
|
@ -36,12 +32,18 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
|
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.SERIALIZE_ALLOW_LIST_FILE_PATH;
|
import static org.apache.dubbo.common.constants.CommonConstants.SERIALIZE_ALLOW_LIST_FILE_PATH;
|
||||||
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_IO_EXCEPTION;
|
||||||
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_INTERRUPTED;
|
||||||
|
|
||||||
public class SerializeSecurityManager {
|
public class SerializeSecurityManager {
|
||||||
private final Set<String> allowedPrefix = new LinkedHashSet<>();
|
private final Set<String> allowedPrefix = new LinkedHashSet<>();
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SerializeSecurityManager.class);
|
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(SerializeSecurityManager.class);
|
||||||
|
|
||||||
private final SerializeClassChecker checker = SerializeClassChecker.getInstance();
|
private final SerializeClassChecker checker = SerializeClassChecker.getInstance();
|
||||||
|
|
||||||
|
|
@ -59,6 +61,7 @@ public class SerializeSecurityManager {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
for (URL u : urls) {
|
for (URL u : urls) {
|
||||||
try {
|
try {
|
||||||
|
logger.info("Read serialize allow list from " + u);
|
||||||
String[] lines = IOUtils.readLines(u.openStream());
|
String[] lines = IOUtils.readLines(u.openStream());
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
|
|
@ -68,11 +71,12 @@ public class SerializeSecurityManager {
|
||||||
allowedPrefix.add(line);
|
allowedPrefix.add(line);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error("Failed to load allow class list! Will ignore allow lis from " + u, e);
|
logger.error(COMMON_IO_EXCEPTION, "", "", "Failed to load allow class list! Will ignore allow lis from " + u, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
logger.error("Failed to load allow class list! Will ignore allow list from configuration.", e);
|
logger.error(INTERNAL_INTERRUPTED, "", "", "Failed to load allow class list! Will ignore allow list from configuration.", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,11 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.serialize.fastjson2;
|
package org.apache.dubbo.common.serialize.fastjson2;
|
||||||
|
|
||||||
import org.apache.dubbo.common.logger.Logger;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.AllowClassNotifyListener;
|
import org.apache.dubbo.common.utils.AllowClassNotifyListener;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||||
|
|
@ -28,18 +32,16 @@ import com.alibaba.fastjson2.filter.ContextAutoTypeBeforeHandler;
|
||||||
import com.alibaba.fastjson2.filter.Filter;
|
import com.alibaba.fastjson2.filter.Filter;
|
||||||
import com.alibaba.fastjson2.util.TypeUtils;
|
import com.alibaba.fastjson2.util.TypeUtils;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import static com.alibaba.fastjson2.util.TypeUtils.loadClass;
|
import static com.alibaba.fastjson2.util.TypeUtils.loadClass;
|
||||||
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_UNTRUSTED_SERIALIZE_CLASS;
|
||||||
|
import static org.apache.dubbo.common.utils.SerializeCheckStatus.STRICT;
|
||||||
|
|
||||||
public class Fastjson2SecurityManager implements AllowClassNotifyListener {
|
public class Fastjson2SecurityManager implements AllowClassNotifyListener {
|
||||||
private Filter securityFilter = new Handler(AllowClassNotifyListener.DEFAULT_STATUS, new String[0]);
|
private Filter securityFilter = new Handler(AllowClassNotifyListener.DEFAULT_STATUS, new String[0]);
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(Fastjson2SecurityManager.class);
|
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(Fastjson2SecurityManager.class);
|
||||||
|
|
||||||
private final static Set<String> warnedClasses = new ConcurrentHashSet<>(1);
|
private static final Set<String> warnedClasses = new ConcurrentHashSet<>(1);
|
||||||
|
|
||||||
public Fastjson2SecurityManager(FrameworkModel frameworkModel) {
|
public Fastjson2SecurityManager(FrameworkModel frameworkModel) {
|
||||||
SerializeSecurityManager securityManager = frameworkModel.getBeanFactory().getOrRegisterBean(SerializeSecurityManager.class);
|
SerializeSecurityManager securityManager = frameworkModel.getBeanFactory().getOrRegisterBean(SerializeSecurityManager.class);
|
||||||
|
|
@ -65,28 +67,40 @@ public class Fastjson2SecurityManager implements AllowClassNotifyListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> apply(String typeName, Class<?> expectClass, long features) {
|
public Class<?> apply(String typeName, Class<?> expectClass, long features) {
|
||||||
switch (status) {
|
Class<?> tryLoad = super.apply(typeName, expectClass, features);
|
||||||
case STRICT:
|
|
||||||
return super.apply(typeName, expectClass, features);
|
// 1. in allow list, return
|
||||||
case WARN:
|
if (tryLoad != null) {
|
||||||
Class<?> tryLoad = super.apply(typeName, expectClass, features);
|
return tryLoad;
|
||||||
if (tryLoad != null) {
|
|
||||||
return tryLoad;
|
|
||||||
}
|
|
||||||
case DISABLED:
|
|
||||||
Class<?> localClass = loadClassDirectly(typeName);
|
|
||||||
if (localClass != null) {
|
|
||||||
if (status == SerializeCheckStatus.WARN && warnedClasses.add(typeName)) {
|
|
||||||
logger.error("[Serialization Security] Serialized class " + localClass.getName() + " is not in allow list. " +
|
|
||||||
"Current mode is `WARN`, will allow to deserialize it by default. " +
|
|
||||||
"Dubbo will set to `STRICT` mode by default in the future. " +
|
|
||||||
"Please add it into security/serialize.allowlist or follow FAQ to configure it.");
|
|
||||||
}
|
|
||||||
return localClass;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. check if in strict mode
|
||||||
|
if (status == STRICT) {
|
||||||
|
String msg = "[Serialization Security] Serialized class " + typeName + " is not in allow list. " +
|
||||||
|
"Current mode is `STRICT`, will disallow to deserialize it by default. " +
|
||||||
|
"Please add it into security/serialize.allowlist or follow FAQ to configure it.";
|
||||||
|
if (warnedClasses.add(typeName)) {
|
||||||
|
logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. try load
|
||||||
|
Class<?> localClass = loadClassDirectly(typeName);
|
||||||
|
if (localClass != null) {
|
||||||
|
if (status == SerializeCheckStatus.WARN && warnedClasses.add(typeName)) {
|
||||||
|
logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "",
|
||||||
|
"[Serialization Security] Serialized class " + localClass.getName() + " is not in allow list. " +
|
||||||
|
"Current mode is `WARN`, will allow to deserialize it by default. " +
|
||||||
|
"Dubbo will set to `STRICT` mode by default in the future. " +
|
||||||
|
"Please add it into security/serialize.allowlist or follow FAQ to configure it.");
|
||||||
|
}
|
||||||
|
return localClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. class not found
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> loadClassDirectly(String typeName) {
|
public Class<?> loadClassDirectly(String typeName) {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,10 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.common.serialize.hessian2;
|
package org.apache.dubbo.common.serialize.hessian2;
|
||||||
|
|
||||||
import org.apache.dubbo.common.logger.Logger;
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.AllowClassNotifyListener;
|
import org.apache.dubbo.common.utils.AllowClassNotifyListener;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||||
|
|
@ -24,8 +27,7 @@ import org.apache.dubbo.common.utils.SerializeCheckStatus;
|
||||||
import org.apache.dubbo.common.utils.SerializeSecurityManager;
|
import org.apache.dubbo.common.utils.SerializeSecurityManager;
|
||||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_UNTRUSTED_SERIALIZE_CLASS;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspired by Fastjson2
|
* Inspired by Fastjson2
|
||||||
|
|
@ -34,9 +36,9 @@ import java.util.Set;
|
||||||
public class Hessian2AllowClassManager implements AllowClassNotifyListener {
|
public class Hessian2AllowClassManager implements AllowClassNotifyListener {
|
||||||
private static final long MAGIC_HASH_CODE = 0xcbf29ce484222325L;
|
private static final long MAGIC_HASH_CODE = 0xcbf29ce484222325L;
|
||||||
private static final long MAGIC_PRIME = 0x100000001b3L;
|
private static final long MAGIC_PRIME = 0x100000001b3L;
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Hessian2AllowClassManager.class);
|
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(Hessian2AllowClassManager.class);
|
||||||
private volatile SerializeCheckStatus checkStatus = AllowClassNotifyListener.DEFAULT_STATUS;
|
private volatile SerializeCheckStatus checkStatus = AllowClassNotifyListener.DEFAULT_STATUS;
|
||||||
private final static Set<String> warnedClasses = new ConcurrentHashSet<>(1);
|
private static final Set<String> warnedClasses = new ConcurrentHashSet<>(1);
|
||||||
private volatile long[] allowPrefixes = new long[0];
|
private volatile long[] allowPrefixes = new long[0];
|
||||||
|
|
||||||
public Hessian2AllowClassManager(FrameworkModel frameworkModel) {
|
public Hessian2AllowClassManager(FrameworkModel frameworkModel) {
|
||||||
|
|
@ -99,14 +101,15 @@ public class Hessian2AllowClassManager implements AllowClassNotifyListener {
|
||||||
"Current mode is `STRICT`, will disallow to deserialize it by default. " +
|
"Current mode is `STRICT`, will disallow to deserialize it by default. " +
|
||||||
"Please add it into security/serialize.allowlist or follow FAQ to configure it.";
|
"Please add it into security/serialize.allowlist or follow FAQ to configure it.";
|
||||||
if (warnedClasses.add(className)) {
|
if (warnedClasses.add(className)) {
|
||||||
logger.error(msg);
|
logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException(msg);
|
throw new IllegalArgumentException(msg);
|
||||||
} else {
|
} else {
|
||||||
Class<?> clazz = Class.forName(className, false, classLoader);
|
Class<?> clazz = Class.forName(className, false, classLoader);
|
||||||
if (warnedClasses.add(className)) {
|
if (warnedClasses.add(className)) {
|
||||||
logger.error("[Serialization Security] Serialized class " + clazz.getName() + " is not in allow list. " +
|
logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "",
|
||||||
|
"[Serialization Security] Serialized class " + clazz.getName() + " is not in allow list. " +
|
||||||
"Current mode is `WARN`, will allow to deserialize it by default. " +
|
"Current mode is `WARN`, will allow to deserialize it by default. " +
|
||||||
"Dubbo will set to `STRICT` mode by default in the future. " +
|
"Dubbo will set to `STRICT` mode by default in the future. " +
|
||||||
"Please add it into security/serialize.allowlist or follow FAQ to configure it.");
|
"Please add it into security/serialize.allowlist or follow FAQ to configure it.");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue