Fedora Account System
Red Hat Associate
Red Hat Customer
Affected component: hivex, the Windows Registry hive parsing library. Affected component: the big-data ("db") block list loop in hivex_value_value (lib/value.c), used on the default read-only parse path by libguestfs, virt-win-reg, guestfish, and hivexget. Tested version(s): Release v1.3.24, pinned tag commit 7996d79 (2024-08-31), the latest release tag. The same code is present on the default branch master HEAD unchanged. Reviewed by static source review of the released source at the pinned commit. Details: Out-of-bounds read while reading a registry value whose data uses a big-data ("db") block, driven by an attacker-controlled block count that is never bounded against the block that holds the block list. Class: CWE-125 Out-of-bounds Read, CWE-129 Improper Validation of Array Index. Root cause (file:line). hivex opens a hive read-only with hivex_open (lib/handle.c:101), maps the file, and records the start offset of every used block in a bitmap. The per-reference validation macro IS_VALID_BLOCK (lib/hivex-internal.h:74) confirms only that an offset is 4-aligned, inside the file, and the start of a used block. It does not bound an array read that begins inside a valid block and runs off its end. When a caller reads a value's data through hivex_value_value (lib/value.c:316), and the declared data length is larger than the single data block that holds it, and that block carries the id "db", execution enters the big-data branch (lib/value.c:386). There the code reads a 16-bit block count nr_blocks and a block list offset from the db record (lib/value.c:398 and lib/value.c:400, db record layout at lib/hivex-internal.h:249), validates only that the block list start is a valid block (lib/value.c:401), then loops for (i = 0; i < nr_blocks; ++i) and reads bl->offset[i] (lib/value.c:411 to lib/value.c:432). There is no check that the block list block is large enough to hold nr_blocks four-byte offsets. nr_blocks is read straight from the file and can be up to 65535, so the loop can index up to about 262140 bytes from a block list block that can be as small as 8 bytes, reading past the end of that block and past the end of the mapped file. Every sibling list walk in hivex does perform the missing check: the value list in _hivex_get_values (lib/value.c:88, "4 + nr_values * 4 > len"), and the lf, li, and ri lists in _get_children (lib/node.c:408, lib/node.c:442, lib/node.c:469). The db block list walk is the one place that omits the comparison. Attacker model. An administrator, a forensic workflow, or a libguestfs based pipeline reads values out of a hive that arrived from an untrusted source, such as a guest disk image, an uploaded registry export, or a sample under analysis. Tools such as virt-win-reg, guestfish hivex commands, and hivexget call this path while enumerating values. The structural gates are a parseable hive header (a valid regf header with a recomputed checksum, which is an xor of the header dwords) and a value whose data points to a db block, all file-controlled. No password, write mode, option, or non-default build flag is required. Impact. Out-of-bounds read of up to about 262140 bytes past the block list block, crossing the end of the mapping when the block list is placed near the end of the file, leading to a likely crash (denial of service) in any process that reads values from an untrusted hive. The out-of-bounds offset value is passed to IS_VALID_BLOCK rather than returned to the caller, so a direct read-back of leaked bytes is not demonstrated. No out-of-bounds write and no code execution were shown. Fix. In the big-data branch of hivex_value_value, after reading nr_blocks and the block list, add "size_t bllen = block_len (h, blocklist_offset, NULL); if (4 + nr_blocks * 4 > bllen) { free (ret); return error; }" before the loop, matching the value list guard at lib/value.c:88. Defense in depth, cap nr_blocks with an explicit limit like the existing HIVEX_MAX_VALUES and HIVEX_MAX_SUBKEYS constants. Verification (static only). The full chain was confirmed against the released source at the pinned commit 7996d79. No hive was built, no tool was run, and no live system was contacted. The crash and faulting address were not confirmed at runtime. Distinct from prior hivex advisories: CVE-2014-9273 (lib/handle.c on tiny files), CVE-2021-3504 (missing bounds check in hivex_open, lib/handle.c), and CVE-2021-3622 (recursion stack overflow in _get_children, lib/node.c). None covers the db big-data block list loop in hivex_value_value.
Upstream fix: https://github.com/libguestfs/hivex/pull/40