From 24580c1e526baecb275eecf9e67dc15f793bfeac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Ledoyen?= Date: Fri, 18 Feb 2022 18:31:17 +0100 Subject: [PATCH] Deprecate SerializationUtils#deserialize As based on Java's serialization mechanism, it can be the source of Remote Code Execution vulnerabilities. --- .../interceptor/CacheResultInterceptor.java | 2 +- .../util/SerializationUtils.java | 17 +++++++++++++++++ .../util/SerializationUtilsTests.java | 5 +++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/CacheResultInterceptor.java b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/CacheResultInterceptor.java index ea2f4a09eac5..96781177eff8 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/CacheResultInterceptor.java +++ b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/CacheResultInterceptor.java @@ -150,7 +150,7 @@ private static CacheOperationInvoker.ThrowableWrapper rewriteCallStack( @Nullable private static T cloneException(T exception) { try { - return (T) SerializationUtils.deserialize(SerializationUtils.serialize(exception)); + return SerializationUtils.clone(exception); } catch (Exception ex) { return null; // exception parameter cannot be cloned diff --git a/spring-core/src/main/java/org/springframework/util/SerializationUtils.java b/spring-core/src/main/java/org/springframework/util/SerializationUtils.java index 1f15a163f0e3..cbe1df705a30 100644 --- a/spring-core/src/main/java/org/springframework/util/SerializationUtils.java +++ b/spring-core/src/main/java/org/springframework/util/SerializationUtils.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.Serializable; import org.springframework.lang.Nullable; @@ -57,8 +58,13 @@ public static byte[] serialize(@Nullable Object object) { * Deserialize the byte array into an object. * @param bytes a serialized object * @return the result of deserializing the bytes + * @deprecated This utility uses Java's reflection, which allows arbitrary code to be + * run and is known for being the source of many Remote Code Execution vulnerabilities. + *

Prefer the use of an external tool (that serializes to JSON, XML or any other format) + * which is regularly checked and updated for not allowing RCE. */ @Nullable + @Deprecated public static Object deserialize(@Nullable byte[] bytes) { if (bytes == null) { return null; @@ -74,4 +80,15 @@ public static Object deserialize(@Nullable byte[] bytes) { } } + /** + * Clone the given object using Java's serialization. + * @param object the object to clone + * @param the type of the object to clone + * @return a clone (deep-copy) of the given object + * @since 6.0.0 + */ + @SuppressWarnings("unchecked") + public static T clone(T object) { + return (T) SerializationUtils.deserialize(SerializationUtils.serialize(object)); + } } diff --git a/spring-core/src/test/java/org/springframework/util/SerializationUtilsTests.java b/spring-core/src/test/java/org/springframework/util/SerializationUtilsTests.java index d48b00b32f43..31eb26dff1c0 100644 --- a/spring-core/src/test/java/org/springframework/util/SerializationUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/SerializationUtilsTests.java @@ -67,4 +67,9 @@ void deserializeNull() throws Exception { assertThat(SerializationUtils.deserialize(null)).isNull(); } + @Test + void cloneException() { + IllegalArgumentException ex = new IllegalArgumentException("foo"); + assertThat(SerializationUtils.clone(ex)).hasMessage("foo").isNotSameAs(ex); + } }