← ALL ADVISORIES

MEDIUM BYTERAY-2026-0281Disclosed

EDK II - Out-of-Bounds Read in Ip6IsExtsValid

Ip6IsExtsValid iterates over the IPv6 extension-header chain using a loop guarded only by while (Offset <= ExtHdrsLen).

Advisory
BYTERAY-2026-0281
CWE
CWE-125
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/Ip6Dxe/Ip6Option.c.
Credit
Argus-Systems

Executive Summary

Ip6IsExtsValid iterates over the IPv6 extension-header chain using a loop guarded only by while (Offset <= ExtHdrsLen). The <= operator allows the loop body to execute when zero bytes remain, and even with < only a single byte is proven valid at the cursor. Each of four switch branches then dereferences multi-byte structures at ExtHdrs + Offset without any per-branch check that enough bytes remain (e.g., Offset + N <= ExtHdrsLen). The buffer is tightly allocated via AllocatePool(PayloadLen) where PayloadLen comes directly from the attacker-controlled IPv6 PayloadLength header field, so OOB reads escape the pool block into adjacent heap memory.

The largest read is in the Hop-by-Hop / Destination Options branch: OptionLen = IP6_HDR_EXT_LEN (*Option) - sizeof (IP6_EXT_HDR) (line 455, up to 2046) is passed to Ip6IsOptionValid (line 459) without checking Offset + OptionLen <= ExtHdrsLen. Ip6IsOptionValid (Ip6Option.c:31) then walks the options for up to 2046 bytes, so an 8-byte payload with Hdr Ext Len 255 makes it read about 2 KB past the pool block.

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/Ip6Dxe/Ip6Option.c:371
  • Function: Ip6IsExtsValid
  • Category: CWE-125 Out-of-bounds Read

Technical Details

Controllability: EXTERNAL_UNTRUSTED — Confidence: High

Data Flow

The IPv6 packet is received from the network by Ip6AcceptFrame (a MNP receive callback registered in Ip6Driver.c:638). The packet flows to Ip6PreProcessPacket (Ip6Input.c:1009), which extracts PayloadLen = (*Head)->PayloadLength directly from the attacker-controlled IPv6 header (Ip6Input.c:819). The buffer is tightly allocated with AllocatePool((UINTN)PayloadLen) (Ip6Input.c:845) and filled with exactly PayloadLen bytes via NetbufCopy (Ip6Input.c:850). The buffer and length are passed to Ip6IsExtsValid (Ip6Input.c:853-865). Inside the function, the loop guard while (Offset <= ExtHdrsLen) at line 371 enters even with 0 bytes remaining. Each switch branch dereferences 2-8 byte structures at ExtHdrs+Offset without per-branch bounds checks — the vulnerable sinks are at lines 454-455 and 459 (Hop/Dest, including the unchecked OptionLen passed to Ip6IsOptionValid), 483 and 487 (Routing), 542 (Fragment, only when ExtHdrsLen % 8 != 0 and IpSb/Packet are non-NULL), and 584 (AH).

Affected Callers

  • Ip6PreProcessPacket (Ip6Input.c:853, 937)
  • Ip6InstanceFrameAcceptable (Ip6Input.c:1305, 1340)
  • Ip6Output (Ip6Output.c:536, 657), locally built packets

Sanitization / Security Controls

None. No authentication occurs before packet processing. No bounds validation exists within Ip6IsExtsValid.

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 can send IPv6 packets to the target UEFI firmware's network interface (on-link, to its unicast or a joined multicast address); IPv6 stack enabled; no authentication required.
  2. Craft an IPv6 packet with NextHeader = 60 (Destination Options) and PayloadLength = 8, matching the bytes actually sent.
  3. In the 8-byte payload, set Hdr Ext Len (byte 1) to 255 so OptionLen becomes 2046, and start the options at byte 2 with a PadN option of length 255 so the option walk jumps past the 8-byte buffer.
  4. Ip6PreProcessPacket allocates 8 bytes and calls Ip6IsExtsValid, which passes OptionLen 2046 to Ip6IsOptionValid; it keeps reading option bytes from pool memory beyond the buffer until it hits a discard/unknown option type or reaches 2046.
  5. Send to the target's IPv6 address. Truncated Routing (43) or AH (51) headers in the last bytes of the payload give the smaller reads at lines 483/487 and 584.

Impact

Remote, unauthenticated out-of-bounds read from an on-link IPv6 sender: 1-4 bytes past the pool block in the Routing and AH branches and for a header starting in the last bytes of the payload, and up to about 2 KB past it through Ip6IsOptionValid. The bytes read are only used for validation and are not returned to the sender. The only observable effect is an ICMPv6 Parameter Problem message whose Pointer field shows where an unrecognized option type was found, a weak oracle. The firmware can crash if the read reaches unmapped memory.

Remediation and Mitigation

As of commit 70741a15d9a714323a5598eac47727e60507e22f this issue is unfixed upstream and no CVE has been assigned. Before reading each field, validate that its full width fits within the remaining bytes derived from the packet or record size, and stop parsing or reject the input when it does not. 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