How 7‑Zip 26.00’s NTFS handling triggers a heap‑overflow RCE (CVE‑2026‑48095)

In April 2026, GitHub Security Lab disclosed a critical heap‑overflow vulnerability (CVE‑2026‑48095) in 7‑Zip 26.00 that can be triggered by opening a crafted NTFS image, leading to vtable hijacking and remote code execution with a CVSS score of 8.8.

Black & White Path
Black & White Path
Black & White Path
How 7‑Zip 26.00’s NTFS handling triggers a heap‑overflow RCE (CVE‑2026‑48095)

1. Vulnerability Overview

GitHub Security Lab researcher Jaroslav Lobačevski (JabLob) reported GHSL‑2026‑140, assigned CVE‑2026‑48095. The flaw resides in the core logic that processes NTFS compression streams in 7‑Zip. A 32‑bit shift undefined behavior (shift UB) causes a heap overflow when a specially crafted NTFS image is opened, allowing an attacker‑controlled 256 MB write into a 1‑byte buffer, leading to vtable hijack and remote code execution.

Affected versions: 7‑Zip 26.00 and all earlier releases that support NTFS compression streams. Fixed in 7‑Zip 26.01 (released 27 April 2026).

2. Technical Analysis

2.1 Root Cause – GetCuSize() Shift Overflow

The entry point is CInStream::GetCuSize() in CPP/7zip/Archive/NtfsHandler.cpp line 687:

UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); }

The function computes the buffer size for NTFS compression units. When two conditions are met, the shift exponent reaches 32:

ClusterSizeLog ≥ 28 (maximum allowed by the boot sector parser is 30, but a crafted image can set it to 28)

CompressionUnit == 4 (accepted by the non‑resident compression data attribute header)

Thus BlockSizeLog + CompressionUnit = 28 + 4 = 32, and (UInt32)1 << 32 is undefined in C++. On x86/x64 hardware the shift mask yields a result of 1, so _inBuf is allocated only 1 byte.

2.2 Heap Overflow – 1‑Byte Buffer Overwritten with 256 MB

After allocating the 1‑byte _inBuf, the code immediately reads compressed data into it:

// NtfsHandler.cpp, lines 940‑941
const size_t compressed = (size_t)numChunks << BlockSizeLog; // up to 256 MB
RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed)) // writes into 1‑byte buffer!

The variable compressed can reach 256 MB (e.g., numChunks = 1, BlockSizeLog = 28), far exceeding the 1‑byte destination, causing a classic heap buffer overflow.

2.3 vtable Hijack – Execution Path

Memory layout shows the CInStream object adjacent to _inBuf, separated by only 304 bytes (0x130). The attack proceeds as follows:

First Read() iteration writes 64 KB into _inBuf, spreading toward higher addresses.

After 304 bytes, the write overwrites the stream object's vtable pointer.

A second Read() iteration dispatches through the corrupted vtable, causing a virtual call to jump to attacker‑controlled code.

The attacker controls the NTFS image’s cluster content, thus fully controlling the overwritten vtable pointer.

This chain constitutes a textbook vtable hijack from heap overflow to code execution.

2.4 Platform Differences

32‑bit builds : (size_t)2 << 32 also triggers UB, yielding 2, so both _inBuf.Alloc(1) and _outBuf.Alloc(2) succeed, leading to an unconditional overflow.

64‑bit builds : (size_t)2 << 32 is a valid 64‑bit shift, producing 8 GB. _outBuf.Alloc(8 GB) succeeds on machines with sufficient memory (tested on a 64 GB system), after which the same heap overflow occurs. On low‑memory systems the allocation may throw CNewException, degrading to a denial‑of‑service.

2.5 Attack Surface – Beyond .ntfs and .img

7‑Zip employs a signature‑fallback mechanism: if a file‑extension handler fails, it tries remaining handlers based on signature priority. The NTFS handler matches the "NTFS " signature at byte offset 3 ( NtfsHandler.cpp:2889 via REGISTER_ARC_I). Consequently, a crafted NTFS image can be disguised with any extension (.7z, .zip, .rar, or no extension) and still be processed by the NTFS handler after the primary handler fails.

Thus, even a user who believes they are opening a normal .zip file may trigger the vulnerability without any additional interaction.

3. Vulnerability Verification and PoC

GHSL released a PoC script gen_ntfs_sparse.py. The core construction sets ClusterSizeLog = 28 and CompressionUnit = 4:

# Boot sector: ClusterSizeLog = 28
boot[13] = 0xED  # SectorsPerCluster encoding → ClusterSizeLog = 28

# MFT record: construct compressed $DATA attribute, CompressionUnit = 4
a[0x22] = 4  # CompressionUnit = 4

Running the script produces poc_ntfs_sparse.ntfs, a 512 MB sparse NTFS image (≈8 KB actual data). Opening this file with 7‑Zip 26.00 triggers the vulnerability.

The PoC is available at the GHSL advisory: https://securitylab.github.com/advisories/GHSL-2026-140_7-Zip/.

GHSL also used UBSan on Linux x64, which reported:

../../Archive/NtfsHandler.cpp:687:47: runtime error: shift exponent 32 is too large for 32-bit type 'UInt32' (aka 'unsigned int')

This leads to a segmentation fault, confirming the crash path.

4. Impact Scope and Fix

Affected versions : The faulty GetCuSize() logic has existed since NTFS compression support was introduced; all versions up to 26.00 are vulnerable.

Remediation : Upgrade to 7‑Zip 26.01, released 27 April 2026. Download link: https://sourceforge.net/p/sevenzip/discussion/45797/thread/555e132ba4/

CVSS score : Base metrics 3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H → 8.8 (High).

5. Detection and Mitigation

Temporary mitigations :

Avoid opening untrusted NTFS images or suspicious archive files with 7‑Zip.

For suspicious files, inspect byte offset 3 with a hex editor for the "NTFS " signature.

Detection methods :

Compile 7‑Zip with UBSan to catch the shift‑exponent undefined behavior.

Monitor 7‑Zip processes for abnormal termination patterns typical of heap‑overflow crashes.

6. Conclusion

CVE‑2026‑48095 exemplifies a textbook heap‑overflow vulnerability: a mathematically undefined shift leads to a 1‑byte allocation, a carefully crafted overflow overwrites a nearby vtable pointer, and the attacker gains remote code execution with a few hundred lines of code.

The attack surface is broad because the NTFS handler can be invoked via signature fallback even when the file extension suggests a different archive type. Given the massive user base of 7‑Zip in China and its integration in many packaging and imaging tools, immediate upgrade to 7‑Zip 26.01 is the only effective mitigation.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

security analysis7-Zipheap overflowNTFSCVE-2026-48095vtable hijack
Black & White Path
Written by

Black & White Path

We are the beacon of the cyber world, a stepping stone on the road to security.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.