CVE-2022-42004 (published 2022-10-02T05:15Z)

In FasterXML jackson-databind before 2.13.4, resource exhaustion can occur because of a lack of a check in BeanDeserializer._deserializeFromArray to prevent use of deeply nested arrays. An application is vulnerable only with certain customized choices for deserialization.

CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-502
cwe_name: Deserialization of Untrusted Data
description: The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.
extended_description: 
            It is often convenient to serialize objects for communication or to save them for later use. However, deserialized data or code can often be modified without using the provided accessor functions if it does not use cryptography to protect itself. Furthermore, any cryptography would still be client-side security -- which is a dangerous security assumption.
            Data that is untrusted can not be trusted to be well-formed.
            When developers place no restrictions on "gadget chains," or series of instances and method invocations that can self-execute during the deserialization process (i.e., before the object is returned to the caller), it is sometimes possible for attackers to leverage them to perform unauthorized actions, like generating a shell.
         
         

Fix information:
repo_url: https://github.com/FasterXML/jackson-databind
commit_details: repo_url: https://github.com/FasterXML/jackson-databind
author: Tatu Saloranta
author_date: 2022-08-23 20:54:42-07:00
msg: Fix #3582
repository: repo_url: https://github.com/FasterXML/jackson-databind
repo_name: FasterXML/jackson-databind
description: General data-binding package for Jackson (2.x): works on streaming API (core) implementation(s)
repo_language: Java
owner: FasterXML
file_changes: filename: VERSION-2.x
change_type: ModificationType.MODIFY
diff: @@ -13,6 +13,8 @@ Project: jackson-databind
 #3565: `Arrays.asList()` value deserialization has changed from mutable to
   immutable in 2.13
  (reported by JonasWilms@github)
+#3582: Add check in `BeanDeserializer._deserializeFromArray()` to prevent
+  use of deeply nested arrays
 
 2.13.3 (14-May-2022)
 

programming_language: Markdown
filename: DeserializationFeature.java
change_type: ModificationType.MODIFY
diff: @@ -317,8 +317,10 @@ public enum DeserializationFeature implements ConfigFeature
      * values to the corresponding value type.  This is basically the opposite of the {@link #ACCEPT_SINGLE_VALUE_AS_ARRAY}
      * feature.  If more than one value is found in the array, a JsonMappingException is thrown.
      * <p>
+     * NOTE: only <b>single</b> wrapper Array is allowed: if multiple attempted, exception
+     * will be thrown.
      * 
-     * Feature is disabled by default
+     * Feature is disabled by default.
      * @since 2.4
      */
     UNWRAP_SINGLE_VALUE_ARRAYS(false),

programming_language: Java
filename: BeanDeserializer.java
change_type: ModificationType.MODIFY
diff: @@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.cfg.CoercionAction;
 import com.fasterxml.jackson.databind.deser.impl.*;
 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring;
+import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.IgnorePropertiesUtil;
 import com.fasterxml.jackson.databind.util.NameTransformer;
 import com.fasterxml.jackson.databind.util.TokenBuffer;
@@ -628,6 +629,15 @@ public class BeanDeserializer
                 return ctxt.handleUnexpectedToken(getValueType(ctxt), JsonToken.START_ARRAY, p, null);
             }
             if (unwrap) {
+                // 23-Aug-2022, tatu: To prevent unbounded nested arrays, we better
+                //   check there is NOT another START_ARRAY lurking there..
+                if (p.nextToken() == JsonToken.START_ARRAY) {
+                    JavaType targetType = getValueType(ctxt);
+                    return ctxt.handleUnexpectedToken(targetType, JsonToken.START_ARRAY, p,
+"Cannot deserialize value of type %s from deeply-nested JSON Array: only single wrapper allowed with `%s`",
+                            ClassUtil.getTypeDescription(targetType),
+                                    "DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS");
+                }
                 final Object value = deserialize(p, ctxt);
                 if (p.nextToken() != JsonToken.END_ARRAY) {
                     handleMissingEndArrayForSingle(p, ctxt);

programming_language: Java
filename: DeepArrayWrappingForDeser3582Test.java
change_type: ModificationType.MODIFY
diff: @@ -1,13 +1,12 @@
 package com.fasterxml.jackson.databind.deser.dos;
 
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
 
 public class DeepArrayWrappingForDeser3582Test extends BaseMapTest
 {
-    // 23-Aug-2022, tatu: Before fix, fails with 5000
-    //    (but passes with 2000)
-//    private final static int TOO_DEEP_NESTING = 4999;
-    private final static int TOO_DEEP_NESTING = 999;
+    // 23-Aug-2022, tatu: Before fix, failed with 5000
+    private final static int TOO_DEEP_NESTING = 9999;
 
     private final ObjectMapper MAPPER = jsonMapperBuilder()
             .enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
@@ -16,8 +15,14 @@ public class DeepArrayWrappingForDeser3582Test extends BaseMapTest
     public void testArrayWrapping() throws Exception
     {
         final String doc = _nestedDoc(TOO_DEEP_NESTING, "[ ", "] ", "{}");
-        Point p = MAPPER.readValue(doc, Point.class);
-        assertNotNull(p);
+        try {
+            MAPPER.readValue(doc, Point.class);
+            fail("Should not pass");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Cannot deserialize");
+            verifyException(e, "nested JSON Array");
+            verifyException(e, "only single");
+        }
     }
 
     private String _nestedDoc(int nesting, String open, String close, String content) {

programming_language: Java