| 标题 | libyal (Joachim Metz) libvmdk 396e1873a030ac535bf919f6707d5be57613ae08` Memory corruption |
|---|
| 描述 | ## Affected Versions
- libvmdk commit `396e1873a030ac535bf919f6707d5be57613ae08` (main, 2026-07-14, version string 20260714, bundled libfvalue tag 20260531): reproduced with an ASan-built vmdkinfo and gdb.
- Re-checked 2026-10-13: current main (commit `420083c1def7…`, 2026-10-12) still contains the unfixed code. The same quoting pattern also exists in `libvmdk_descriptor_file_read_change_tracking_file()` (line 2066) and `libvmdk_descriptor_file_read_disk_database()` (line 2455) on current main.
As of the material update date (2026-10-14), upstream issue #41 is still open and no fix commit exists. The status should be updated once the maintainer merges a fix.
## Classification
- Attack type: Local
- Attack complexity: Low
- Privileges required: None
- User interaction: None (opening a supplied image in vmdkinfo/vmdkmount/pyvmdk reaches the parser; a UI:R re-score is acceptable)
- Exploit availability: Public proof-of-concept (attached to upstream issue #41)
- Proven impact: Deterministic parse failure / file rejection (denial of service); a wrapped SIZE_MAX length is demonstrably passed into heap-reading conversion routines and is only intercepted by a downstream size-cap check
- Suggested severity: Medium (a Low rating based strictly on the demonstrated availability impact is also defensible)
- CVSS 3.1 score: 4.0
- CVSS 3.1 vector: `CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L`
## Technical Description
libvmdk is an open-source library to access the VMware Virtual Disk (VMDK) format. When parsing `identifier=value` lines of the descriptor header, `libvmdk_descriptor_file_read_header()` in `libvmdk/libvmdk_descriptor_file.c` initializes `size_t value_length` to `line_string_segment_size - 1` (line 819), decrements it while advancing the index for an opening quote (lines 823-829), and decrements it again for a closing quote (lines 830-836) — neither block is bounds-guarded. For an empty quoted value such as `version=""`, `value_length` drops to 8 while `line_string_segment_index` rises to 9; the unsigned subtraction `value_length -= line_string_segment_index` at line 841 wraps to `0xFFFFFFFFFFFFFFFF` (SIZE_MAX, confirmed under gdb). The corrupted length is then passed as a byte-count parameter into `libfvalue_utf8_string_copy_to_integer()` (CID/version/parentCID, lines 859/906/1024) and `libclocale_codepage_copy_from_string()` (encoding, line 990), so those heap-reading conversion routines are no longer bounded by the original buffer.
The descriptor text is parsed before any content validation when an untrusted VMDK is opened (`libvmdk_handle.c:2097/2200`), and the affected lines are fully attacker-controlled. With the currently bundled dependency (libfvalue tag 20260531), an internal size-cap check intercepts the wrapped length ("invalid UTF-8 string size value exceeds maximum"), so the observed result is a parse failure / file rejection (denial of service). That cap is an incidental defense in a downstream routine, not protection in the vulnerable function — if the downstream routine changes or another caller trusts the length, an out-of-bounds read becomes possible. The submission asserts the demonstrated underflow (SIZE_MAX passed as a length) and the availability impact; it does not assert an observed out-of-bounds read or any confidentiality impact.
## Proof of Concept
PoC archive: `poc/03_integer_underflow_poc.zip`
PoC URL: https://github.com/user-attachments/files/33394231/03_integer_underflow_poc.zip (attached to issue #41; SHA-256 verified identical to the local copy on 2026-10-14)
Contents: `poc4_quoted_underflow.vmdk` — a 118-byte minimal descriptor (`# Disk DescriptorFile`, `version=""`, `CID="`, `parentCID=""`, `encoding="`) — and the expected output.
Command (libvmdk commit 396e187, Ubuntu 24.04, gcc 13.3.0, ASan-built vmdkinfo):
```bash
LD_LIBRARY_PATH=~/build/libvmdk-verify/libvmdk/.libs \
ASAN_OPTIONS=detect_leaks=0 \
~/build/libvmdk-verify/vmdktools/.libs/vmdkinfo poc4_quoted_underflow.vmdk
```
Observed result:
```text
vmdkinfo 20260714
Unable to open source file(s).
libfvalue_utf8_string_with_index_copy_to_integer: invalid UTF-8 string size value exceeds maximum.
libfvalue_utf8_string_copy_to_integer: unable to copy UTF-8 string to integer value.
libvmdk_descriptor_file_read_header: unable to determine version value from string.
libvmdk_descriptor_file_read_string: unable to read descriptor file header.
```
gdb observation (conditional breakpoint on `value_length > 0xfffffffffffffff`):
```text
UNDERFLOW CONFIRMED: value_length=18446744073709551615 (0xffffffffffffffff)
line_string_segment_index=9 value_points_at="
```
## Root Cause
The quote-stripping logic assumes every line carries a well-formed quoted value. The opening-quote block increments `line_string_segment_index` and decrements `value_length` unconditionally; the closing-quote block inspects `line_string_segment[value_length - 1]` and decrements unconditionally; and nothing verifies `value_length >= line_string_segment_index` before line 841 subtracts the index. For `version=""` the arithmetic lands at 8 - 9, and the size_t underflow produces SIZE_MAX — a length that should have been 0. The signature check only validates the first `# Disk DescriptorFile` line, so malformed header lines reach this code before any other validation. |
|---|
| 来源 | ⚠️ https://github.com/libyal/libvmdk/issues/41 |
|---|
| 用户 | fczhang (UID 97720) |
|---|
| 提交 | 2026-10-14 08時45分 (23 日前) |
|---|
| 管理 | 2026-11-05 19時11分 (22 days later) |
|---|
| 状态 | 已接受 |
|---|
| VulDB条目 | 431575 [libyal libvmdk Descriptor File Parser libvmdk_descriptor_file.c libvmdk_descriptor_file_read_header 信息公开] |
|---|
| 积分 | 20 |
|---|