CVE-2021-3622 (published 2021-12-23T21:15Z)

A flaw was found in the hivex library. This flaw allows an attacker to input a specially crafted Windows Registry (hive) file, which would cause hivex to recursively call the _get_children() function, leading to a stack overflow. The highest threat from this vulnerability is to system availability.

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 4.3, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L)

Weakness information:
cwe_id: CWE-400
cwe_name: Uncontrolled Resource Consumption
description: The product does not properly control the allocation and maintenance of a limited resource, thereby enabling an actor to influence the amount of resources consumed, eventually leading to the exhaustion of available resources.
extended_description: 
            Limited resources include memory, file system storage, database connection pool entries, and CPU. If an attacker can trigger the allocation of these limited resources, but the number or size of the resources is not controlled, then the attacker could cause a denial of service that consumes all available resources. This would prevent valid users from accessing the product, and it could potentially have an impact on the surrounding environment. For example, a memory exhaustion attack against an application could slow down the application as well as its host operating system.
            There are at least three distinct scenarios which can commonly lead to resource exhaustion:
               
                  Lack of throttling for the number of allocated resources
                  Losing all references to a resource before reaching the shutdown stage
                  Not closing/returning a resource after processing
               
            Resource exhaustion problems are often result due to an incorrect implementation of the following situations:
               
                  Error conditions and other exceptional circumstances.
                  Confusion over which part of the program is responsible for releasing the resource.
               
         
         

Fix information:
repo_url: https://github.com/libguestfs/hivex
commit_details: repo_url: https://github.com/libguestfs/hivex
author: Richard W.M. Jones
author_date: 2021-07-08 19:00:45+01:00
msg: lib/node.c: Limit recursion in ri-records (CVE-2021-3622)

Windows Registry hive "ri"-records are arbitrarily nested B-tree-like
structures:

  +-------------+
  | ri          |
  |-------------|
  | nr_offsets  |
  |   offset[0] ------>  points to another lf/lh/li/ri block
  |   offset[1] ------>
  |   offset[2] ------>
  +-------------+

It is possible to construct a hive with a very deeply nested tree of
ri-records, causing the internal _get_children function to recurse to
any depth which can cause programs linked to hivex to crash with a
stack overflow.

Since it is not thought that deeply nested ri-records occur in real
hives, limit recursion depth.  If you hit this limit you will see the
following error and the operation will return an error instead of
crashing:

  \> ls
  hivex: _get_children: returning EINVAL because: ri-record nested to depth >= 32
  ls: Invalid argument

Thanks to Jeremy Galindo for finding and reporting this bug.

Reported-by: Jeremy Galindo, Sr Security Engineer, Datto.com
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
Fixes: CVE-2021-3622
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1975489
(cherry picked from commit 781a12c4a49dd81365c9c567c5aa5e19e894ba0e)
repository: repo_url: https://github.com/libguestfs/hivex
repo_name: libguestfs/hivex
description: windows registry hive extraction library.  PLEASE DO NOT USE GITHUB FOR ISSUES OR PULL REQUESTS. See the website for how to file a bug or contact us.  http://libguestfs.org
repo_language: C
owner: libguestfs
file_changes: filename: node.c
change_type: ModificationType.MODIFY
diff: @@ -203,7 +203,7 @@ hivex_node_classname (hive_h *h, hive_node_h node)
 
 static int _get_children (hive_h *h, hive_node_h blkoff,
                           offset_list *children, offset_list *blocks,
-                          int flags);
+                          int flags, unsigned depth);
 static int check_child_is_nk_block (hive_h *h, hive_node_h child, int flags);
 
 /* Iterate over children (ie. subkeys of a node), returning child
@@ -335,7 +335,7 @@ _hivex_get_children (hive_h *h, hive_node_h node,
     goto error;
   }
 
-  if (_get_children (h, subkey_lf, &children, &blocks, flags) == -1)
+  if (_get_children (h, subkey_lf, &children, &blocks, flags, 0) == -1)
     goto error;
 
   /* Check the number of children we ended up reading matches
@@ -383,7 +383,7 @@ _hivex_get_children (hive_h *h, hive_node_h node,
 static int
 _get_children (hive_h *h, hive_node_h blkoff,
                offset_list *children, offset_list *blocks,
-               int flags)
+               int flags, unsigned depth)
 {
   /* Add this intermediate block. */
   if (_hivex_add_to_offset_list (blocks, blkoff) == -1)
@@ -486,7 +486,17 @@ _get_children (hive_h *h, hive_node_h blkoff,
         }
       }
 
-      if (_get_children (h, offset, children, blocks, flags) == -1)
+      /* Although in theory hive ri records might be nested to any
+       * depth, in practice this is unlikely.  Recursing here caused
+       * CVE-2021-3622.  Thus limit the depth we will recurse to
+       * something small.
+       */
+      if (depth >= 32) {
+        SET_ERRNO (EINVAL, "ri-record nested to depth >= %u", depth);
+        return -1;
+      }
+
+      if (_get_children (h, offset, children, blocks, flags, depth+1) == -1)
         return -1;
     }
   }

programming_language: C