This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/master by this push:
new 4d3a318 Add serialize class checker (#7436)
4d3a318 is described below
commit 4d3a318fb68067fd5f174e064e1d7b54c62cee9c
Author: Albumen Kevin <[email protected]>
AuthorDate: Fri Mar 26 16:08:55 2021 +0800
Add serialize class checker (#7436)
---
.../common/beanutil/JavaBeanSerializeUtil.java | 2 +
.../dubbo/common/constants/CommonConstants.java | 10 ++
.../org/apache/dubbo/common/utils/PojoUtils.java | 1 +
.../dubbo/common/utils/SerializeClassChecker.java | 150 ++++++++++++++++++
.../main/resources/security/serialize.blockedlist | 167 +++++++++++++++++++++
.../common/utils/SerializeClassCheckerTest.java | 105 +++++++++++++
.../org/apache/dubbo/rpc/filter/GenericFilter.java | 21 ++-
.../apache/dubbo/rpc/filter/GenericFilterTest.java | 4 +
.../rpc/protocol/hessian/HessianProtocolTest.java | 6 +-
9 files changed, 463 insertions(+), 3 deletions(-)
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
index 8121d65..c4463a2 100644
---
a/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
+++
b/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.LogHelper;
import org.apache.dubbo.common.utils.ReflectUtils;
+import org.apache.dubbo.common.utils.SerializeClassChecker;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
@@ -464,6 +465,7 @@ public final class JavaBeanSerializeUtil {
if (isReferenceType(name)) {
name = name.substring(1, name.length() - 1);
}
+ SerializeClassChecker.getInstance().validateClass(name);
return Class.forName(name, false, loader);
}
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
index 3f234dd..e4f6af8 100644
---
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
+++
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
@@ -371,4 +371,14 @@ public interface CommonConstants {
String CLASSPATH_URL_PREFIX = "classpath:";
String DEFAULT_VERSION = "0.0.0";
+
+ String CLASS_DESERIALIZE_BLOCK_ALL =
"dubbo.security.serialize.blockAllClassExceptAllow";
+
+ String CLASS_DESERIALIZE_ALLOWED_LIST =
"dubbo.security.serialize.allowedClassList";
+
+ String CLASS_DESERIALIZE_BLOCKED_LIST =
"dubbo.security.serialize.blockedClassList";
+
+ String ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE =
"dubbo.security.serialize.generic.native-java-enable";
+
+ String SERIALIZE_BLOCKED_LIST_FILE_PATH = "security/serialize.blockedlist";
}
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
index 80e4ad3..29328b2 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
@@ -387,6 +387,7 @@ public class PojoUtils {
if (pojo instanceof Map<?, ?> && type != null) {
Object className = ((Map<Object, Object>) pojo).get("class");
if (className instanceof String) {
+ SerializeClassChecker.getInstance().validateClass((String)
className);
try {
type = ClassUtils.forName((String) className);
} catch (ClassNotFoundException e) {
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeClassChecker.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeClassChecker.java
new file mode 100644
index 0000000..b75ae65
--- /dev/null
+++
b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeClassChecker.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.utils;
+
+import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil;
+import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class SerializeClassChecker {
+ private static final Logger logger =
LoggerFactory.getLogger(SerializeClassChecker.class);
+
+ private static volatile SerializeClassChecker INSTANCE = null;
+
+ private final boolean BLOCK_ALL_CLASS_EXCEPT_ALLOW;
+ private final Set<String> CLASS_DESERIALIZE_ALLOWED_SET = new
ConcurrentHashSet<>();
+ private final Set<String> CLASS_DESERIALIZE_BLOCKED_SET = new
ConcurrentHashSet<>();
+
+ private final Object CACHE = new Object();
+ private final LFUCache<String, Object> CLASS_ALLOW_LFU_CACHE = new
LFUCache<>();
+ private final LFUCache<String, Object> CLASS_BLOCK_LFU_CACHE = new
LFUCache<>();
+
+ private final AtomicLong counter = new AtomicLong(0);
+
+ private SerializeClassChecker() {
+ String blockAllClassExceptAllow =
System.getProperty(CommonConstants.CLASS_DESERIALIZE_BLOCK_ALL, "false");
+ BLOCK_ALL_CLASS_EXCEPT_ALLOW =
Boolean.parseBoolean(blockAllClassExceptAllow);
+
+ String[] lines;
+ try {
+ ClassLoader classLoader =
ClassUtils.getClassLoader(JavaBeanSerializeUtil.class);
+ if (classLoader != null) {
+ lines =
IOUtils.readLines(classLoader.getResourceAsStream(CommonConstants.SERIALIZE_BLOCKED_LIST_FILE_PATH));
+ } else {
+ lines =
IOUtils.readLines(ClassLoader.getSystemResourceAsStream(CommonConstants.SERIALIZE_BLOCKED_LIST_FILE_PATH));
+ }
+ for (String line : lines) {
+ line = line.trim();
+ if (StringUtils.isEmpty(line) || line.startsWith("#")) {
+ continue;
+ }
+ CLASS_DESERIALIZE_BLOCKED_SET.add(line);
+ }
+
+ } catch (IOException e) {
+ logger.error("Failed to load blocked class list! Will ignore
default blocked list.", e);
+ }
+
+ String allowedClassList =
System.getProperty(CommonConstants.CLASS_DESERIALIZE_ALLOWED_LIST,
"").trim().toLowerCase(Locale.ROOT);
+ String blockedClassList =
System.getProperty(CommonConstants.CLASS_DESERIALIZE_BLOCKED_LIST,
"").trim().toLowerCase(Locale.ROOT);
+
+ if (StringUtils.isNotEmpty(allowedClassList)) {
+ String[] classStrings = allowedClassList.trim().split(",");
+ CLASS_DESERIALIZE_ALLOWED_SET.addAll(Arrays.asList(classStrings));
+ }
+
+ if (StringUtils.isNotEmpty(blockedClassList)) {
+ String[] classStrings = blockedClassList.trim().split(",");
+ CLASS_DESERIALIZE_BLOCKED_SET.addAll(Arrays.asList(classStrings));
+ }
+
+ }
+
+ public static SerializeClassChecker getInstance() {
+ if (INSTANCE == null) {
+ synchronized (SerializeClassChecker.class) {
+ if (INSTANCE == null) {
+ INSTANCE = new SerializeClassChecker();
+ }
+ }
+ }
+ return INSTANCE;
+ }
+
+ /**
+ * For ut only
+ */
+ @Deprecated
+ protected static void clearInstance() {
+ INSTANCE = null;
+ }
+
+ /**
+ * Check if a class is in block list, using prefix match
+ *
+ * @throws IllegalArgumentException if class is blocked
+ * @param name class name ( all are convert to lower case )
+ */
+ public void validateClass(String name) {
+ name = name.toLowerCase(Locale.ROOT);
+ if (CACHE == CLASS_ALLOW_LFU_CACHE.get(name)) {
+ return;
+ }
+
+ if (CACHE == CLASS_BLOCK_LFU_CACHE.get(name)) {
+ error(name);
+ }
+
+ for (String allowedPrefix : CLASS_DESERIALIZE_ALLOWED_SET) {
+ if (name.startsWith(allowedPrefix)) {
+ CLASS_ALLOW_LFU_CACHE.put(name, CACHE);
+ return;
+ }
+ }
+
+ for (String blockedPrefix : CLASS_DESERIALIZE_BLOCKED_SET) {
+ if (BLOCK_ALL_CLASS_EXCEPT_ALLOW ||
name.startsWith(blockedPrefix)) {
+ CLASS_BLOCK_LFU_CACHE.put(name, CACHE);
+ error(name);
+ }
+ }
+
+ CLASS_ALLOW_LFU_CACHE.put(name, CACHE);
+ }
+
+ private void error(String name) {
+ String notice = "Trigger the safety barrier! " +
+ "Catch not allowed serialize class. " +
+ "Class name: " + name + " . " +
+ "This means currently maybe being attacking by others." +
+ "If you are sure this is a mistake, " +
+ "please add this class name to `" +
CommonConstants.CLASS_DESERIALIZE_ALLOWED_LIST +
+ "` as a system environment property.";
+ if (counter.incrementAndGet() % 1000 == 0 || counter.get() < 100) {
+ logger.error(notice);
+ }
+ throw new IllegalArgumentException(notice);
+ }
+
+}
diff --git a/dubbo-common/src/main/resources/security/serialize.blockedlist
b/dubbo-common/src/main/resources/security/serialize.blockedlist
new file mode 100644
index 0000000..de0b68d
--- /dev/null
+++ b/dubbo-common/src/main/resources/security/serialize.blockedlist
@@ -0,0 +1,167 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+aj.org.objectweb.asm.
+br.com.anteros.
+ch.qos.logback.
+clojure.core$constantly
+clojure.main$eval_opt
+com.alibaba.citrus.springext.support.parser.abstractnamedproxybeandefinitionparser$proxytargetfactory
+com.alibaba.citrus.springext.util.springextutil.abstractproxy
+com.alibaba.druid.pool.druiddatasource
+com.alibaba.druid.stat.jdbcdatasourcestat
+com.alibaba.fastjson.annotation
+com.alipay.custrelation.service.model.redress.pair
+com.caucho.
+com.ibatis.
+com.mchange
+com.mysql.cj.jdbc.admin.
+com.mysql.cj.jdbc.mysqlconnectionpooldatasource
+com.mysql.cj.jdbc.mysqldatasource
+com.mysql.cj.jdbc.mysqlxadatasource
+com.mysql.cj.log.
+com.p6spy.engine.
+com.rometools.rome.feed.impl.equalsbean
+com.rometools.rome.feed.impl.tostringbean
+com.sun.
+com.taobao.eagleeye.wrapper
+com.zaxxer.hikari.
+flex.messaging.util.concurrent.
+java.awt.i
+java.awt.p
+java.beans.expression
+java.io.closeable
+java.io.serializable
+java.lang.autocloseable
+java.lang.class
+java.lang.cloneable
+java.lang.iterable
+java.lang.object
+java.lang.readable
+java.lang.runnable
+java.lang.thread
+java.lang.unixprocess
+java.net.inetaddress
+java.net.socket
+java.net.url
+java.rmi
+java.security.signedobject
+java.util.collection
+java.util.eventlistener
+java.util.jar.
+java.util.logging.
+java.util.prefs.
+java.util.serviceloader$lazyiterator
+javassist.
+javax.activation.
+javax.imageio.imageio$containsfilter
+javax.imageio.spi.serviceregistry
+javax.management.
+javax.naming.
+javax.net.
+javax.print.
+javax.script.
+javax.sound.
+javax.swing.j
+javax.tools.
+javax.xml
+jdk.internal.
+jodd.db.connection.
+junit.
+net.bytebuddy.dynamic.loading.bytearrayclassloader
+net.sf.cglib.
+net.sf.ehcache.hibernate.
+net.sf.ehcache.transaction.manager.
+oracle.jdbc.
+oracle.jms.aq
+oracle.net
+org.aoju.bus.proxy.provider.
+org.apache.activemq.activemqconnectionfactory
+org.apache.activemq.activemqxaconnectionfactory
+org.apache.activemq.jms.pool.
+org.apache.activemq.pool.
+org.apache.activemq.spring.
+org.apache.aries.transaction.
+org.apache.axis2.jaxws.spi.handler.
+org.apache.axis2.transport.jms.
+org.apache.bcel
+org.apache.carbondata.core.scan.expression.expressionresult
+org.apache.catalina.
+org.apache.cocoon.
+org.apache.commons.beanutils
+org.apache.commons.collections.comparators.
+org.apache.commons.collections.functors
+org.apache.commons.collections.functors.
+org.apache.commons.collections.transformer
+org.apache.commons.collections4.comparators
+org.apache.commons.collections4.functors
+org.apache.commons.collections4.transformer
+org.apache.commons.configuration
+org.apache.commons.dbcp
+org.apache.commons.fileupload
+org.apache.commons.jelly.
+org.apache.commons.logging.
+org.apache.commons.proxy.
+org.apache.cxf.jaxrs.provider.
+org.apache.hadoop.shaded.com.zaxxer.hikari.
+org.apache.http.auth.
+org.apache.http.conn.
+org.apache.http.cookie.
+org.apache.http.impl.
+org.apache.ibatis.datasource
+org.apache.ibatis.executor.
+org.apache.ibatis.javassist.
+org.apache.ibatis.ognl.
+org.apache.ibatis.parsing.
+org.apache.ibatis.reflection.
+org.apache.ibatis.scripting.
+org.apache.ignite.cache.jta.
+org.apache.log4j.
+org.apache.logging.
+org.apache.myfaces.context.servlet
+org.apache.openjpa.ee.
+org.apache.shiro.jndi.
+org.apache.shiro.realm.
+org.apache.tomcat
+org.apache.wicket.util
+org.apache.xalan
+org.apache.xbean.
+org.apache.xpath.xpathcontext
+org.codehaus.groovy.runtime
+org.codehaus.jackson.
+org.eclipse.jetty.
+org.geotools.filter.constantexpression
+org.h2.jdbcx.
+org.h2.server.
+org.hibernate
+org.javasimon.
+org.jaxen.
+org.jboss
+org.jdom.
+org.jdom2.transform.
+org.logicalcobwebs.
+org.mortbay.jetty.
+org.mozilla.javascript
+org.objectweb.asm.
+org.osjava.sj.
+org.python.core
+org.quartz.
+org.slf4j.
+org.springframework.
+org.yaml.snakeyaml.tokens.directivetoken
+sun.rmi.server.unicastref
\ No newline at end of file
diff --git
a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/SerializeClassCheckerTest.java
b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/SerializeClassCheckerTest.java
new file mode 100644
index 0000000..b58f399
--- /dev/null
+++
b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/SerializeClassCheckerTest.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.utils;
+
+import org.apache.dubbo.common.constants.CommonConstants;
+
+import javassist.compiler.Javac;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.net.Socket;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
+public class SerializeClassCheckerTest {
+
+ @BeforeEach
+ public void setUp() {
+ SerializeClassChecker.clearInstance();
+ }
+
+ @Test
+ public void testCommon() {
+ SerializeClassChecker serializeClassChecker =
SerializeClassChecker.getInstance();
+
+ for (int i = 0; i < 10; i++) {
+ serializeClassChecker.validateClass(List.class.getName());
+ serializeClassChecker.validateClass(LinkedList.class.getName());
+ serializeClassChecker.validateClass(Integer.class.getName());
+ serializeClassChecker.validateClass(int.class.getName());
+
+
serializeClassChecker.validateClass(List.class.getName().toUpperCase(Locale.ROOT));
+
serializeClassChecker.validateClass(LinkedList.class.getName().toUpperCase(Locale.ROOT));
+
serializeClassChecker.validateClass(Integer.class.getName().toUpperCase(Locale.ROOT));
+
serializeClassChecker.validateClass(int.class.getName().toUpperCase(Locale.ROOT));
+ }
+
+ Assertions.assertThrows(IllegalArgumentException.class, ()-> {
+ serializeClassChecker.validateClass(Socket.class.getName());
+ });
+ }
+
+ @Test
+ public void testAddAllow() {
+ System.setProperty(CommonConstants.CLASS_DESERIALIZE_ALLOWED_LIST,
Socket.class.getName() + "," + Javac.class.getName());
+
+ SerializeClassChecker serializeClassChecker =
SerializeClassChecker.getInstance();
+ for (int i = 0; i < 10; i++) {
+ serializeClassChecker.validateClass(Socket.class.getName());
+ serializeClassChecker.validateClass(Javac.class.getName());
+ }
+
+ System.clearProperty(CommonConstants.CLASS_DESERIALIZE_ALLOWED_LIST);
+ }
+
+ @Test
+ public void testAddBlock() {
+ System.setProperty(CommonConstants.CLASS_DESERIALIZE_BLOCKED_LIST,
LinkedList.class.getName() + "," + Integer.class.getName());
+
+ SerializeClassChecker serializeClassChecker =
SerializeClassChecker.getInstance();
+ for (int i = 0; i < 10; i++) {
+ Assertions.assertThrows(IllegalArgumentException.class, ()-> {
+
serializeClassChecker.validateClass(LinkedList.class.getName());
+ });
+ Assertions.assertThrows(IllegalArgumentException.class, ()-> {
+ serializeClassChecker.validateClass(Integer.class.getName());
+ });
+ }
+
+ System.clearProperty(CommonConstants.CLASS_DESERIALIZE_BLOCKED_LIST);
+ }
+
+ @Test
+ public void testBlockAll() {
+ System.setProperty(CommonConstants.CLASS_DESERIALIZE_BLOCK_ALL,
"true");
+ System.setProperty(CommonConstants.CLASS_DESERIALIZE_ALLOWED_LIST,
LinkedList.class.getName());
+
+ SerializeClassChecker serializeClassChecker =
SerializeClassChecker.getInstance();
+ for (int i = 0; i < 10; i++) {
+ serializeClassChecker.validateClass(LinkedList.class.getName());
+ Assertions.assertThrows(IllegalArgumentException.class, ()-> {
+ serializeClassChecker.validateClass(Integer.class.getName());
+ });
+ }
+
+ System.clearProperty(CommonConstants.CLASS_DESERIALIZE_BLOCK_ALL);
+ System.clearProperty(CommonConstants.CLASS_DESERIALIZE_ALLOWED_LIST);
+ }
+}
diff --git
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
index 9c2ef94..2e6d3a8 100644
---
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
+++
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
@@ -19,11 +19,14 @@ package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.beanutil.JavaBeanAccessor;
import org.apache.dubbo.common.beanutil.JavaBeanDescriptor;
import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil;
+import org.apache.dubbo.common.config.Configuration;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.io.UnsafeByteArrayInputStream;
import org.apache.dubbo.common.io.UnsafeByteArrayOutputStream;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.serialize.Serialization;
import org.apache.dubbo.common.utils.PojoUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
@@ -35,6 +38,7 @@ import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.service.GenericException;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.ProtocolUtils;
@@ -54,6 +58,7 @@ import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
*/
@Activate(group = CommonConstants.PROVIDER, order = -20000)
public class GenericFilter implements Filter, Filter.Listener {
+ private static final Logger logger =
LoggerFactory.getLogger(GenericFilter.class);
@Override
public Result invoke(Invoker<?> invoker, Invocation inv) throws
RpcException {
@@ -71,7 +76,7 @@ public class GenericFilter implements Filter, Filter.Listener
{
args = new Object[params.length];
}
- if(types == null) {
+ if (types == null) {
types = new String[params.length];
}
@@ -90,6 +95,18 @@ public class GenericFilter implements Filter,
Filter.Listener {
|| ProtocolUtils.isGenericReturnRawResult(generic)) {
args = PojoUtils.realize(args, params,
method.getGenericParameterTypes());
} else if (ProtocolUtils.isJavaGenericSerialization(generic)) {
+ Configuration configuration =
ApplicationModel.getEnvironment().getConfiguration();
+ if
(!configuration.getBoolean(CommonConstants.ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE,
false)) {
+ String notice = "Trigger the safety barrier! " +
+ "Native Java Serializer is not allowed by
default." +
+ "This means currently maybe being attacking by
others. " +
+ "If you are sure this is a mistake, " +
+ "please set `" +
CommonConstants.ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE + "` enable in
configuration! " +
+ "Before doing so, please make sure you have
configure JEP290 to prevent serialization attack.";
+ logger.error(notice);
+ throw new RpcException(new
IllegalStateException(notice));
+ }
+
for (int i = 0; i < args.length; i++) {
if (byte[].class == args[i].getClass()) {
try (UnsafeByteArrayInputStream is = new
UnsafeByteArrayInputStream((byte[]) args[i])) {
@@ -205,7 +222,7 @@ public class GenericFilter implements Filter,
Filter.Listener {
GENERIC_SERIALIZATION_PROTOBUF +
"] serialize result failed.", e);
}
- } else if(ProtocolUtils.isGenericReturnRawResult(generic)) {
+ } else if (ProtocolUtils.isGenericReturnRawResult(generic)) {
return;
} else {
appResponse.setValue(PojoUtils.generalize(appResponse.getValue()));
diff --git
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericFilterTest.java
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericFilterTest.java
index c49aa92..48ae217 100644
---
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericFilterTest.java
+++
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericFilterTest.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
@@ -75,6 +76,8 @@ public class GenericFilterTest {
@Test
public void testInvokeWithJavaException() throws Exception {
+ // temporary enable native java generic serialize
+
System.setProperty(CommonConstants.ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE,
"true");
Assertions.assertThrows(RpcException.class, () -> {
Method genericInvoke = GenericService.class.getMethods()[0];
@@ -95,6 +98,7 @@ public class GenericFilterTest {
genericFilter.invoke(invoker, invocation);
});
+
System.clearProperty(CommonConstants.ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE);
}
@Test
diff --git
a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocolTest.java
b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocolTest.java
index a9bf02e..7ee98b3 100644
---
a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocolTest.java
+++
b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocolTest.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.protocol.hessian;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.beanutil.JavaBeanDescriptor;
import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil;
+import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.serialize.ObjectOutput;
@@ -32,8 +33,8 @@ import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.protocol.hessian.HessianServiceImpl.MyException;
-
import org.apache.dubbo.rpc.service.GenericService;
+
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -86,6 +87,8 @@ public class HessianProtocolTest {
@Test
public void testGenericInvokeWithNativeJava() throws IOException,
ClassNotFoundException {
+ // temporary enable native java generic serialize
+
System.setProperty(CommonConstants.ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE,
"true");
HessianServiceImpl server = new HessianServiceImpl();
Assertions.assertFalse(server.isCalled());
ProxyFactory proxyFactory =
ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
@@ -110,6 +113,7 @@ public class HessianProtocolTest {
Assertions.assertEquals("Hello, haha", objectInput.readObject());
invoker.destroy();
exporter.unexport();
+
System.clearProperty(CommonConstants.ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE);
}
@Test