← ALL ADVISORIES

MEDIUM BYTERAY-2026-0229Disclosed

EDK II - Out-of-Bounds Read in PxeBcParseDhcp6Options

PxeBcParseDhcp6Options iterates over DHCP6 options using a loop guarded only by Offset < Length (line 50).

Advisory
BYTERAY-2026-0229
CWE
CWE-130
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

PxeBcParseDhcp6Options iterates over DHCP6 options using a loop guarded only by Offset < Length (line 50). The loop body reads the 4-byte option header (Option->OpCode at Offset+0..1 and Option->OpLen at Offset+2..3 via the EFI_DHCP6_PACKET_OPTION struct pointer) without verifying that Offset+4 fits within Length. Loop advancement uses Offset += (NTOHS(Option->OpLen) + 4) (line 55), so the attacker-controlled OpLen of each sub-option moves the read cursor.

The larger problem is the only caller. PxeBcParseDhcp6Packet passes Option->Data + 12 with Length = NTOHS(Option->OpLen) of the IA_NA option (lines 686-688). The length is not reduced by the 12-byte IAID/T1/T2 header, so the scan always covers 12 bytes past the end of the IA_NA option, and the IA_NA OpLen is never checked against the bytes left in the packet: the outer option loop (lines 660-678) only checks that each option starts before the end of the option area. A rogue server can therefore send a trailing IA_NA with OpLen up to 0xFFFF, and the walker, guided by attacker-chosen sub-option lengths, reads option headers up to about 64 KB past the 1480-byte cached packet held in PXEBC_PRIVATE_DATA (OfferBuffer[], ProxyOffer, DhcpAck). If a sub-option with code DHCP6_OPT_STATUS_CODE is matched there, line 691 also reads Option->Data[0] from that location.

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:50 (reads at lines 51 and 55), called with an unchecked buffer and length from NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c:686-690 (PxeBcParseDhcp6Packet)
  • Function: PxeBcParseDhcp6Options
  • Category: CWE-130 — Out-of-bounds read in DHCP6 option walker

Technical Details

Controllability: EXTERNAL_UNTRUSTED — high confidence. DHCP6 IA option inner data from remote PXE boot packet. No authentication.

Data Flow

PxeBcDhcp6CallBack (line 1985) receives a DHCPv6 Advertise on Dhcp6RcvdAdvertise and caches it through PxeBcCacheDhcp6Offer (line 2073), which copies it into the fixed PXEBC_DHCP6_PACKET_CACHE buffer and calls PxeBcParseDhcp6Packet (line 1195). The outer loop at line 660 stores the last option with code IA_NA in Options[PXEBC_DHCP6_IDX_IA_NA] (lines 661-662) regardless of its IAID. PxeBcParseDhcp6Packet (line 686) then calls PxeBcParseDhcp6Options(Option->Data + 12, NTOHS(Option->OpLen), DHCP6_OPT_STATUS_CODE). The loop at line 50 (while (Offset < Length)) reads Option->OpCode (2 bytes) and Option->OpLen (2 bytes) via struct pointer at Offset without verifying Offset+4 <= Length, and advances by Offset += (NTOHS(Option->OpLen) + 4), so with an oversized IA_NA OpLen the reads land far past the cached packet.

Affected Callers

PxeBcParseDhcp6Packet, reached from PxeBcCacheDhcp6Offer, PxeBcRetryDhcp6Binl (after PxeBcRequestBootService), PxeBcCopyDhcp6Ack and PxeBcCopyDhcp6Proxy

Sanitization / Security Controls

  • Offers longer than PXEBC_DHCP6_PACKET_MAX_SIZE are dropped in PxeBcDhcp6CallBack (line 2061). This bounds the cached packet but not the IA_NA OpLen used as the walk length.
  • Dhcp6Dxe Dhcp6SeekStsOption (Dhcp6Io.c:846-885) bounds only the IA_NA whose IAID matches the client's (Dhcp6SeekIaOption, Dhcp6Utility.c:1182); an extra IA_NA with a different IAID is not validated before the PxeBc callback.

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. IPv6 PXE boot; attacker controls/MITMs PXE/DHCP6 server.
  2. Craft a DHCPv6 Advertise whose last option is an IA_NA with an IAID different from the client's and OpLen set to 0xFFFF, followed by a few inner sub-options whose OpLen values push the walk past the end of the packet.
  3. Send the crafted DHCP6 offer. PxeBcParseDhcp6Options walks up to 0xFFFF bytes from IA_NA->Data + 12, reading option headers beyond the 1480-byte cached packet.

Impact

Out-of-bounds read during IPv6 PXE boot offer parsing, up to about 64 KB past the cached DHCPv6 packet, into the rest of PXEBC_PRIVATE_DATA and possibly beyond that allocation. The value read only decides whether the offer is classified as a proxy offer (IsProxyOffer, line 691), so no data is returned to the attacker. The practical effects are a wrong offer classification or a fault if the walk reaches unmapped or guard memory.

Remediation and Mitigation

As of commit 70741a15d9a714323a5598eac47727e60507e22f this issue is unfixed upstream and no CVE has been assigned. Before reading each option header or field, verify that the full field fits within the remaining buffer length, not just that the cursor currently sits in bounds. 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