← ALL ADVISORIES

MEDIUM BYTERAY-2026-0283Disclosed

EDK II - Out-of-Bounds Read in PxeBcExtractDiscoverInfo

PxeBcExtractDiscoverInfo iterates over variable-length PXEBC_BOOT_SVR_ENTRY structures from the DHCP4 vendor option 43 boot-servers sub-option using a loop guarded only by (UINT8)(Entry - VendorOpt->BootSvr) < VendorOpt->BootSvrLen.

Advisory
BYTERAY-2026-0283
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/UefiPxeBcDxe/PxeBcBoot.c.
Credit
Argus-Systems

Executive Summary

PxeBcExtractDiscoverInfo iterates over variable-length PXEBC_BOOT_SVR_ENTRY structures from the DHCP4 vendor option 43 boot-servers sub-option using a loop guarded only by (UINT8)(Entry - VendorOpt->BootSvr) < VendorOpt->BootSvrLen. That pointer difference counts PXEBC_BOOT_SVR_ENTRY elements (7 bytes each with #pragma pack(1)), not bytes, and is truncated to UINT8, so it does not even prove the entry start byte is within the data region. The loop body reads Entry->Type (2 bytes), Entry->IpCnt (1 byte), and a variable-length IpAddr array driven by the attacker-controlled IpCnt field, with no check that the full struct or its IpAddr array fits within the remaining buffer. With IpCnt=255, the CopyMem loop at lines 817-818 reads up to 1020 bytes past the boot-server data boundary. The destination is allocated from the same IpCnt (line 808), so this is a source over-read only. The source lies in the cached DHCP packet inside PXEBC_PRIVATE_DATA (ProxyOffer or DhcpAck, PxeBcImpl.h:183-184), so the over-read runs into the following fields of that structure (OptList, VendorOpt, the next packet cache), and the bytes read are stored in SrvList as boot server addresses.

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/PxeBcBoot.c:817-818 (copy), PxeBcBoot.c:793 (loop guard)
  • Function: PxeBcExtractDiscoverInfo
  • Category: CWE-125 Out-of-bounds Read

Technical Details

Controllability: EXTERNAL_UNTRUSTED — confidence: high

Data Flow

The vulnerability trace begins with a rogue DHCP4 server on the local network segment sending a crafted OFFER/ACK packet during PXE boot. The packet is received by PxeBcDhcp4CallBack (PxeBcDhcp4.c:1174) via the DHCP4 protocol on a Dhcp4RcvdOffer or Dhcp4RcvdAck event. The packet is cached by PxeBcCacheDhcp4Offer, and PxeBcParseVendorOptions (PxeBcDhcp4.c:144–145) extracts VendorOption->BootSvr and BootSvrLen directly from DHCP4 option 43 BOOT_SERVERS sub-option data with no validation — both values are externally untrusted. EfiPxeBcDiscover (PxeBcImpl.c:621) calls PxeBcExtractDiscoverInfo on the default PXE boot path (Info==NULL). The loop guard at PxeBcBoot.c:793 compares the entry index (in 7-byte element units, truncated to UINT8) against the byte length BootSvrLen. Line 794 reads Entry->Type (2 bytes) without a full-fit check; line 806 reads Entry->IpCnt (attacker-controlled); line 808 allocates SrvList for IpCnt entries; the sink is the copy at lines 817-818, which reads IpCnt*4 bytes (up to 1020 with IpCnt=255) from Entry+3, extending past the boot-server data boundary into the following fields of PXEBC_PRIVATE_DATA, and stores the over-read data into SrvList. EfiPxeBcDiscover then uses these entries as unicast discover destinations (PxeBcImpl.c:691-697).

Affected Callers

  • EfiPxeBcDiscover

Sanitization / Security Controls

  • DHCP4 protocol callback filters event types (Dhcp4RcvdOffer, Dhcp4SelectOffer, Dhcp4SendDiscover, Dhcp4RcvdAck) — ineffective: does not validate packet contents or vendor option data.
  • Optional EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL user callback — bypassable: skipped entirely if Callback==NULL; even if registered, cannot re-validate internal struct field bounds.
  • No sanitization points exist on the data path from network input to vulnerable sinks.

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 has access to the local network segment where PXE boot occurs; target machine has PXE boot enabled; no DHCP snooping or 802.1X port authentication.
  2. Set up rogue DHCP4 server.
  3. Respond to target's DHCP DISCOVER with crafted OFFER containing option 43 BOOT_SERVERS with an entry whose Type matches the boot type, IpCnt=0xFF, and minimal trailing data.
  4. Victim ACKs with rogue server.
  5. EfiPxeBcDiscover calls PxeBcExtractDiscoverInfo.
  6. The CopyMem at lines 817-818 reads up to 1020 bytes past the boot-server data into the following fields of PXEBC_PRIVATE_DATA, and the firmware sends unicast discover packets to the resulting addresses.

Impact

Remote out-of-bounds read of up to 1020 bytes past the boot-server sub-option, within PXEBC_PRIVATE_DATA (the rest of the cached packet buffer, its option pointers and vendor option fields, and the next packet cache). The bytes read become SrvList boot server addresses, and the firmware sends unicast discover packets to them, so parts of that memory (pointers, other cached DHCP data) can be observed on the local network as destination IP addresses. Because the read stays inside a large driver structure, a crash is unlikely.

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