You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2020/05/12 14:44:07 UTC
[ignite] branch master updated: IGNITE-12962 Add support of classes
whitelist and blacklist for HTTP-REST - Fixes #7773.
This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 29ef5c8 IGNITE-12962 Add support of classes whitelist and blacklist for HTTP-REST - Fixes #7773.
29ef5c8 is described below
commit 29ef5c819e605b1ddfe7716b0645a25df0c08d9e
Author: Pavel Pereslegin <xx...@gmail.com>
AuthorDate: Tue May 12 17:09:40 2020 +0300
IGNITE-12962 Add support of classes whitelist and blacklist for HTTP-REST - Fixes #7773.
Signed-off-by: Aleksey Plekhanov <pl...@gmail.com>
---
.../rest/JettyRestProcessorAbstractSelfTest.java | 74 ++++++++++++++++++++--
.../test/config/class_list_exploit_included.txt | 3 +-
.../http/jetty/GridJettyObjectMapper.java | 35 +++++++++-
3 files changed, 105 insertions(+), 7 deletions(-)
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
index 2a0aca1..2443eba 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
@@ -151,6 +151,7 @@ import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.testframework.GridTestUtils;
import org.junit.Test;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_MARSHALLER_BLACKLIST;
import static org.apache.ignite.cache.CacheMode.PARTITIONED;
import static org.apache.ignite.cache.CacheMode.REPLICATED;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_ASYNC;
@@ -175,12 +176,22 @@ public abstract class JettyRestProcessorAbstractSelfTest extends JettyRestProces
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
+ String path = U.resolveIgnitePath("modules/core/src/test/config/class_list_exploit_included.txt").getPath();
+ System.setProperty(IGNITE_MARSHALLER_BLACKLIST, path);
+
super.beforeTestsStarted();
initCache();
}
/** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ System.clearProperty(IGNITE_MARSHALLER_BLACKLIST);
+
+ super.afterTestsStopped();
+ }
+
+ /** {@inheritDoc} */
@Override protected void beforeTest() throws Exception {
grid(0).cache(DEFAULT_CACHE_NAME).removeAll();
@@ -655,6 +666,23 @@ public abstract class JettyRestProcessorAbstractSelfTest extends JettyRestProces
);
assertResponseContainsError(ret, "Failed to convert value to specified type");
+
+ // Check forbidden type.
+ ForbiddenType forbidden = new ForbiddenType(new Exploit[] {
+ new Exploit(1),
+ new Exploit(2)
+ });
+
+ json = JSON_MAPPER.writeValueAsString(forbidden);
+
+ ret = content(DEFAULT_CACHE_NAME, GridRestCommand.CACHE_PUT,
+ "keyType", "int",
+ "key", "5",
+ "valueType", ForbiddenType.class.getName(),
+ "val", json
+ );
+
+ assertResponseContainsError(ret, "Deserialization of class " + Exploit.class.getName() + " is disallowed.");
}
/**
@@ -3280,8 +3308,46 @@ public abstract class JettyRestProcessorAbstractSelfTest extends JettyRestProces
}
/** */
+ private static class ForbiddenType {
+ /** Data. */
+ @JsonProperty
+ private Exploit[] data;
+
+ /** */
+ ForbiddenType() {
+ // No-op.
+ }
+
+ /**
+ * @param data Data.
+ */
+ ForbiddenType(Exploit[] data) {
+ this.data = data;
+ }
+ }
+
+ /** */
+ private static class Exploit {
+ /** Value. */
+ @JsonProperty
+ private int val = 10;
+
+ /**
+ * @param val Value
+ */
+ Exploit(int val) {
+ this.val = val;
+ }
+
+ /** */
+ Exploit() {
+ // No-op.
+ }
+ }
+
+ /** */
@JsonInclude(JsonInclude.Include.NON_NULL)
- public static class OuterClass {
+ private static class OuterClass {
/** */
@JsonProperty
private long id;
@@ -3329,7 +3395,6 @@ public abstract class JettyRestProcessorAbstractSelfTest extends JettyRestProces
}
/** */
- @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
OuterClass(long id, String name, double doubleVal, List<Integer> list, Timestamp timestamp, long[] longs,
UUID uuid, IgniteUuid igniteUuid, OptionalObject optional) {
this.id = id;
@@ -3412,7 +3477,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends JettyRestProces
}
/** */
- public enum Color {
+ private enum Color {
/** */
RED,
@@ -3424,8 +3489,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends JettyRestProces
}
/** Complex entity. */
- @SuppressWarnings({"InnerClassMayBeStatic", "AssignmentOrReturnOfFieldWithMutableType"})
- static class Complex implements Serializable {
+ private static class Complex implements Serializable {
/** */
@QuerySqlField(index = true)
@JsonProperty
diff --git a/modules/core/src/test/config/class_list_exploit_included.txt b/modules/core/src/test/config/class_list_exploit_included.txt
index b8cb550..b461d53 100644
--- a/modules/core/src/test/config/class_list_exploit_included.txt
+++ b/modules/core/src/test/config/class_list_exploit_included.txt
@@ -17,4 +17,5 @@
org.apache.ignite.spi.discovery.tcp.DiscoveryUnmarshalVulnerabilityTest$Exploit
org.apache.ignite.stream.socket.SocketStreamerUnmarshalVulnerabilityTest$Exploit
-org.apache.ignite.internal.processors.rest.TcpRestUnmarshalVulnerabilityTest$Exploit
\ No newline at end of file
+org.apache.ignite.internal.processors.rest.TcpRestUnmarshalVulnerabilityTest$Exploit
+org.apache.ignite.internal.processors.rest.JettyRestProcessorAbstractSelfTest$Exploit
\ No newline at end of file
diff --git a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyObjectMapper.java b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyObjectMapper.java
index 28c4298..98c214f 100644
--- a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyObjectMapper.java
+++ b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyObjectMapper.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.processors.rest.protocols.http.jetty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -39,6 +40,7 @@ import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.Locale;
+import org.apache.ignite.IgniteException;
import org.apache.ignite.binary.BinaryObject;
import org.apache.ignite.binary.BinaryObjectException;
import org.apache.ignite.binary.BinaryType;
@@ -50,6 +52,7 @@ import org.apache.ignite.internal.processors.cache.query.GridCacheSqlMetadata;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.visor.util.VisorExceptionWrapper;
import org.apache.ignite.lang.IgniteBiTuple;
+import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.lang.IgniteUuid;
/**
@@ -88,9 +91,14 @@ public class GridJettyObjectMapper extends ObjectMapper {
module.addSerializer(Date.class, IGNITE_SQLDATE_SERIALIZER);
module.addDeserializer(Date.class, IGNITE_SQLDATE_DESERIALIZER);
- if (ctx != null)
+ if (ctx != null) {
module.addDeserializer(BinaryObject.class, new IgniteBinaryObjectJsonDeserializer(ctx));
+ IgnitePredicate<String> clsFilter = ctx.marshallerContext().classNameFilter();
+
+ setDefaultTyping(new RestrictedTypeResolverBuilder(clsFilter).init(JsonTypeInfo.Id.CLASS, null));
+ }
+
configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@@ -329,4 +337,29 @@ public class GridJettyObjectMapper extends ObjectMapper {
return Date.valueOf(parser.getText());
}
};
+
+ /** */
+ private static class RestrictedTypeResolverBuilder extends DefaultTypeResolverBuilder {
+ /** */
+ private final IgnitePredicate<String> clsFilter;
+
+ /**
+ * @param clsFilter Class name filter.
+ */
+ public RestrictedTypeResolverBuilder(IgnitePredicate<String> clsFilter) {
+ super(DefaultTyping.NON_FINAL);
+
+ this.clsFilter = clsFilter;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean useForType(JavaType type) {
+ String clsName = type.getRawClass().getName();
+
+ if (!clsFilter.apply(clsName))
+ throw new IgniteException("Deserialization of class " + clsName + " is disallowed.");
+
+ return false;
+ }
+ }
}