diff --git a/docs/modules/secure-cluster/pages/hardening-recommendations.adoc b/docs/modules/secure-cluster/pages/hardening-recommendations.adoc index 5bb0807b5..49d596634 100644 --- a/docs/modules/secure-cluster/pages/hardening-recommendations.adoc +++ b/docs/modules/secure-cluster/pages/hardening-recommendations.adoc @@ -57,6 +57,7 @@ To avoid deserialization of objects from untrusted sources, Hazelcast offers som xref:security:tls-ssl.adoc#mutual-authentication[mutual TLS authentication] and disabling xref:clusters:network-configuration.adoc#multicast-element[multicast join] configuration. We recommend using Java serialization filter configuration for whitelisting the set of trusted classes or packages which are allowed for deserialization. +* Hazelcast can fall back to zero-configuration Compact serialization for classes that have no explicit serializer. We recommend restricting the classes eligible for zero-config Compact serialization by defining an allowlist of only the classes your application needs, rather than relying on the default behavior. See xref:serialization:compact-serialization.adoc#zero-config-filter[Restricting Classes for Zero-Config Compact Serialization]. * Hazelcast uses Java reflection during SQL execution when the object format is set to `java`. We recommend using xref:sql:sql-reflection-configuration.adoc#configuring-reflection[Java reflection filter configuration] to whitelist the set of trusted classes or packages that are allowed to create through reflection. * You can disable script executions on the Hazelcast members. Scripts executed from Management center have access to system resources (files, etc.) with privileges of user running Hazelcast. diff --git a/docs/modules/serialization/pages/compact-serialization.adoc b/docs/modules/serialization/pages/compact-serialization.adoc index 431cb18c1..a4e396fa7 100644 --- a/docs/modules/serialization/pages/compact-serialization.adoc +++ b/docs/modules/serialization/pages/compact-serialization.adoc @@ -111,7 +111,7 @@ Client.newHazelcastClient( compact: { serializers: [ new FooSerializer() - ] + ] ) ---- -- @@ -511,10 +511,10 @@ struct hz_serializer : public compact_serializer static employee read(compact_reader& reader) { employee e; - + e.id = reader.read_int64("id"); e.name = reader.read_string("name"); - + return e; } @@ -522,9 +522,9 @@ struct hz_serializer : public compact_serializer { writer.write_int64("id", e.id); writer.write_string("name", e.name); - } + } - static std::string type_name() { return "employee"; } + static std::string type_name() { return "employee"; } }; ---- -- @@ -1037,8 +1037,8 @@ When Hazelcast cannot associate a class with any other serialization mechanism, throwing an exception directly, it tries to use zero-configuration Compact serialization as a last effort. -Hazelcast tries to extract a schema out of the class. If successful, it registers the -zero-config serializer associated with the extracted schema and uses it while serializing +Hazelcast tries to extract a schema out of the class. If successful, it registers the +zero-config serializer associated with the extracted schema and uses it while serializing and deserializing instances of that class. If the automatic schema extraction fails, Hazelcast throws an exception. @@ -1132,6 +1132,86 @@ module org.example.Foo { } ---- +[[zero-config-filter]] +== Restricting Classes for Zero-Config Compact Serialization + +Zero-config Compact serialization uses reflection to serialize any class that does not have another registered serializer. To control which classes are eligible for this, and to prevent classes from being serialized unintentionally, configure a filter that allows or blocks classes. + +The filter uses an allowlist and a blocklist. This is the same format as the xref:sql:sql-reflection-configuration.adoc[SQL Java reflection filter]. You can allow or block classes by fully qualified class name, package name, or class-name prefix. The filter can be set on both members and clients. + +When a filter is configured: + +* If a class is on the blocklist, serializing an object of that class throws an exception. +* If a class is on the blocklist, deserializing its data returns a `GenericRecord` instead of an instance of the class, rather than throwing an exception. +* If the allowlist is non-empty, only classes on the allowlist (and not on the blocklist) are eligible for zero-config Compact serialization. + +Without a configured filter, Hazelcast applies a built-in blocklist of internal classes. This does not cover your own classes, so for the strongest protection, we suggest defining an allowlist containing only the classes your application needs. + +[tabs] +==== +XML:: ++ +-- +[source,xml] +---- + + ... + + + + + example.Foo + com.acme.app + com.acme. + + + com.acme.app.BeanComparator + + + + + ... + +---- +-- +YAML:: ++ +-- +[source,yaml] +---- +hazelcast: + serialization: + compact-serialization: + zero-config-filter: + defaults-disabled: false + whitelist: + class: + - example.Foo + package: + - com.acme.app + prefix: + - com.acme. + blacklist: + class: + - com.acme.app.BeanComparator +---- +-- +Java:: ++ +-- +[source,java] +---- +Config config = new Config(); +JavaSerializationFilterConfig filter = new JavaSerializationFilterConfig(); +filter.getWhitelist().addClasses("example.Foo"); +filter.getWhitelist().addPackages("com.acme.app"); +filter.getWhitelist().addPrefixes("com.acme."); +filter.getBlacklist().addClasses("com.acme.app.BeanComparator"); +config.getSerializationConfig().getCompactSerializationConfig().setZeroConfigFilter(filter); +---- +-- +==== + == Schema Evolution This section provides an introduction to schema evolution, explaining how Compact serialization allows your object @@ -1255,7 +1335,7 @@ public class Employee { [source,cs] ---- public record Employee( - long Id, + long Id, string Name, int Age // newly-added field ); @@ -1354,7 +1434,7 @@ public class EmployeeSerializer : ICompactSerializer { var id = reader.ReadInt64("id"); var name = reader.ReadString("name"); - // the new 'age' field is there, but the old reader does not + // the new 'age' field is there, but the old reader does not // know anything about it, and ignores the field. return new Employee(id, name); } @@ -1375,14 +1455,14 @@ struct hz_serializer : compact_serializer employee& read(compact_reader& reader) { employee e; - + e.id = reader.read_int32("id"); e.name = reader.read_string("name"); // The new "age" field is there, but the old reader does not // know anything about it. Hence, it will simply ignore that field. return e; } - + // ... }; ---- @@ -1507,10 +1587,10 @@ struct hz_serializer : compact_serializer employee& read(compact_reader& reader) { employee e; - + e.id = reader.read_int64("id"); e.name = reader.read_string("name"); - + // read the "age" field if it exists, else use the default value 0 // reader.read_int32("age") would throw if the "age" field // does not exist in data. @@ -1520,7 +1600,7 @@ struct hz_serializer : compact_serializer } else { e.age = 0; } - + return e; } }; diff --git a/docs/modules/sql/pages/sql-reflection-configuration.adoc b/docs/modules/sql/pages/sql-reflection-configuration.adoc index 08ac7c21c..56b02f038 100644 --- a/docs/modules/sql/pages/sql-reflection-configuration.adoc +++ b/docs/modules/sql/pages/sql-reflection-configuration.adoc @@ -19,15 +19,17 @@ When objects are constructed through reflection, the following filtering rules a When reflection fails, a `SecurityException` is thrown. -By default, reflection restriction filter is empty and all class names or package names are allowed. +By default, a basic blocklist is applied: class names with the prefixes `com.hazelcast.shaded` and `org.springframework.beans` are blocked, while all other class names and package names are allowed. -If the reflection restriction filter is not empty, class names or package names with the specified prefixes are automatically added to the whitelist by default: +We recommend configuring your own filter, ideally a minimal allowlist as this is more secure than a blocklist against possible future vulnerabilities. + +If the reflection restriction filter is configured, the following prefixes are automatically added to the allowlist by default: * `java` * `com.hazelcast.` * `[` (for primitives and arrays) -If you do not want to allow these default prefixes, set the `defaults-disabled` attribute to `true`. +The default blocklist is also applied. To turn off both the default allowlist prefixes and the default blocklist, set the `defaults-disabled` attribute to `true`. [tabs] ==== @@ -95,4 +97,4 @@ reflectionConfig.getWhitelist().addClasses(SomeAllowedClass.class.getName()); config.getSqlConfig().setJavaReflectionFilterConfig(reflectionConfig); ---- -- -==== \ No newline at end of file +====