From c60663ea9311f2d4468d96e18883d5c442c6fe5b Mon Sep 17 00:00:00 2001 From: simei2k <137663782+simei2k@users.noreply.github.com> Date: Sun, 20 Apr 2025 09:51:51 +0800 Subject: [PATCH] Fix: Replace Unsafe Java Deserialization with Jackson Mapper This PR addresses a critical security vulnerability in the code that could lead to Remote Code Execution (RCE). The code was using Java's built-in ObjectInputStream.readObject() for deserialization, which is known to be vulnerable to deserialization attacks if the input comes from an untrusted source. This vulnerability was initially found and fixed in the git commit below. References: https://github.com/apache/helix/commit/7af17a31819859e6c46bcb3994ef7d52347760c4 --- .../dev33/satoken/jboot/SaJdkSerializer.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/sa-token-starter/sa-token-jboot-plugin/src/main/java/cn/dev33/satoken/jboot/SaJdkSerializer.java b/sa-token-starter/sa-token-jboot-plugin/src/main/java/cn/dev33/satoken/jboot/SaJdkSerializer.java index fb7a57440..0a47911b6 100644 --- a/sa-token-starter/sa-token-jboot-plugin/src/main/java/cn/dev33/satoken/jboot/SaJdkSerializer.java +++ b/sa-token-starter/sa-token-jboot-plugin/src/main/java/cn/dev33/satoken/jboot/SaJdkSerializer.java @@ -55,18 +55,25 @@ public Object deserialize(byte[] bytes) { if (bytes == null || bytes.length == 0) { return null; } - ObjectInputStream objectInput = null; + + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); try { - ByteArrayInputStream bytesInput = new ByteArrayInputStream(bytes); - objectInput = new ObjectInputStream(bytesInput); - return objectInput.readObject(); - } - catch (Exception e) { + // Configure mapper for safe deserialization + mapper.configure(MapperFeature.AUTO_DETECT_FIELDS, true); + mapper.configure(MapperFeature.AUTO_DETECT_SETTERS, true); + mapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + // Use mapper instead of ObjectInputStream + return mapper.readValue(bais, _clazz); + } catch (Exception e) { + LOG.error("Error during deserialization of bytes", e); throw new RuntimeException(e); - } - finally { - if (objectInput != null) - try {objectInput.close();} catch (Exception e) {LOG.error(e.getMessage(), e);} + } finally { + try { + bais.close(); + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } } } }