← ALL ADVISORIES

MEDIUM BYTERAY-2026-0271Disclosed

EDK II - Buffer Overflow via Wrong Bounds Check in DHCP6 ACK Copy in PxeBcCopyDhcp6Ack

Identical pattern to the DHCP4 variant.

Advisory
BYTERAY-2026-0271
CWE
CWE-805
Vendor
TianoCore
Product
EDK II
Reported
2026-06-25
Disclosure
2026-10-29
Affected
EDK II at commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21); affected code in NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c.
Credit
Argus-Systems

Executive Summary

Identical pattern to the DHCP4 variant. CopyMem(&Mode->DhcpAck.Dhcpv6, &Ack->Dhcp6, Ack->Length) at line 763 copies Ack->Length bytes (network-controlled, up to 1480 after cache validation) into EFI_PXE_BASE_CODE_PACKET (1472 bytes). The root cause is in PxeBcCacheDhcp6Packet (line 188), which compares Dst->Size (1480) against Src->Length, but copies at &Dst->Dhcp6 (offset 8) where only 1472 bytes are available. The Dhcp6RcvdReply callback case (line 2124) does NOT check Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE unlike Dhcp6RcvdAdvertise, Dhcp6SendSolicit, and Dhcp6SendRequest. With fragmented DHCP6 packets, Ack->Length can be 1473–1480, overflowing by 1–8 bytes into Mode->ProxyOffer. Dhcp6Dxe sets Packet->Length from the UDP payload size with no upper bound (Dhcp6Io.c:3060-3069), and a payload above 1452 bytes needs IPv6 fragmentation on a 1500-byte MTU link, which Ip6Dxe reassembles. In the cache copy at line 192 the extra bytes land past the 1480-byte packet union in the OfferType field and padding of the same PXEBC_DHCP6_PACKET_CACHE (on x64 they stop before OptList[]); these fields are rewritten by PxeBcParseDhcp6Packet.

This advisory is one of a set reported to VulnCheck on 2026-06-25 for coordinated disclosure to the EDK II maintainers. After several follow-ups over the following months no response was received. 126 days after the initial report, ByteRay is publishing the findings in good faith so that affected integrators can assess and remediate them. All findings were identified against EDK II commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21).

Affected Products and Versions

  • Vendor: TianoCore
  • Product: EDK II (NetworkPkg)
  • Affected commit: 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21). The code is present on that commit and later revisions that have not changed it.
  • Location: NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c:763, with the faulty bound check at NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c:188 and the first overflowing copy at NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c:192 (PxeBcCacheDhcp6Packet)
  • Function: PxeBcCopyDhcp6Ack
  • Category: Buffer Access with Incorrect Length Value

Technical Details

Controllability: EXTERNAL_UNTRUSTED — confidence: high

Data Flow

Dhcp6Io.c:3069 sets Packet->Length from the reassembled UDP6 payload size → PxeBcDhcp6.c:2374 registers PxeBcDhcp6CallBack as the DHCP6 callback → PxeBcDhcp6.c:2124–2130 the Dhcp6RcvdReply case has NO length guard (unlike Dhcp6RcvdAdvertise which checks > 1472) and calls PxeBcCopyDhcp6Ack(Private, Packet, FALSE) → PxeBcDhcp6.c:753 calls PxeBcCacheDhcp6Packet with the network-controlled packet → PxeBcDhcp6.c:188–192 the bounds check Dst->Size (1480) < Src->Length passes when Src->Length is in [1473, 1480], but CopyMem(&Dst->Dhcp6, &Src->Dhcp6, Src->Length) writes at offset 8 where only 1472 bytes are available → PxeBcDhcp6.c:1533 PxeBcHandleDhcp6Offer calls PxeBcCopyDhcp6Ack again with the cached ack and Verified=TRUE → PxeBcDhcp6.c:763 when Verified=TRUE, CopyMem(&Mode->DhcpAck.Dhcpv6, &Ack->Dhcp6, Ack->Length) copies up to 1480 bytes into the 1472-byte EFI_PXE_BASE_CODE_PACKET, overflowing into Mode->ProxyOffer.

Affected Callers

  • PxeBcHandleDhcp6Offer
  • PxeBcDhcp6CallBack
  • PxeBcDhcp6Sarr (calls PxeBcHandleDhcp6Offer at line 2493)

Sanitization / Security Controls

  • PxeBcDhcp6.c:2061: length guard exists for Dhcp6RcvdAdvertise (checks Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE = 1472) but is ABSENT for Dhcp6RcvdReply at line 2124 — ineffective for the Reply path.
  • PxeBcDhcp6.c:188: if (Dst->Size < Src->Length) return EFI_BUFFER_TOO_SMALL; compares against Dst->Size (PXEBC_CACHED_DHCP6_PACKET_MAX_SIZE = 8 + 1472, set at PxeBcImpl.c:106), which includes the 8-byte Size/Length header that the copy at line 192 skips. Bypassable by up to 8 bytes.

Reachability and Preconditions

Attacker position and trust level for this issue are stated in the Controllability line and Data Flow above, and the concrete trigger is in Reproduction below.

Exploitability: Medium
Realism: Medium

Reproduction

  1. Attacker on the same IPv6 local network segment as the PXE-booting client; can observe/respond to client's DHCP6 SOLICIT; target uses UefiPxeBcDxe for IPv6 network boot.
  2. Set up rogue DHCP6 server; respond to client's SOLICIT with a valid ADVERTISE.
  3. After client sends REQUEST, send crafted DHCP6 REPLY with data length in [1473, 1480], split into IPv6 fragments so it fits the link MTU.
  4. REPLY passes Dhcp6RcvdReply callback with no length guard; CopyMem at line 192 writes 1473–1480 bytes starting at offset 8 into 1472-byte space; after PXE offer handling completes, the mode-data copy at line 763 (reached from line 1533) also overflows into Mode->ProxyOffer.

Impact

1–8 byte overflow inside the heap-allocated PXEBC_PRIVATE_DATA: into the OfferType field and padding of PXEBC_DHCP6_PACKET_CACHE (cache path) and into the start of EFI_PXE_BASE_CODE_MODE.ProxyOffer (mode-data path). Both targets are plain data in the same structure, and the cache fields are rewritten during parsing, so no pointer or control-flow data is shown to be reachable. The result is corruption of PXE mode data visible to later consumers of Mode->ProxyOffer, not a demonstrated route to code execution.

Remediation and Mitigation

As of commit 70741a15d9a714323a5598eac47727e60507e22f this issue is unfixed upstream and no CVE has been assigned. Derive the bounds check from the destination buffer size and validate the copy length before the copy. The specific control that is absent or ineffective is identified in the Sanitization / Security Controls list under Technical Details.

Timeline

  • 2026-06-25 - Reported to VulnCheck for coordinated disclosure to the TianoCore / EDK II security team.
  • 2026-07 to 2026-10 - Several follow-ups sent; no response received.
  • 2026-10-29 - Public disclosure in good faith, 126 days after the initial report.

Credits

Discovered and reported by Argus-Systems.

References